From a8b0fcb3a8da9e4cce7c5cae8a2c11b8c1c53a51 Mon Sep 17 00:00:00 2001 From: mwansinck Date: Fri, 4 Feb 2022 15:07:09 +0100 Subject: [PATCH] Allow PHP 8, Symfony 6 --- CHANGELOG.md | 7 + Command/CreateDatatableCommand.php | 213 ----------------------------- Controller/DatatableController.php | 16 +-- Generator/DatatableGenerator.php | 106 -------------- composer.json | 28 ++-- 5 files changed, 28 insertions(+), 342 deletions(-) delete mode 100644 Command/CreateDatatableCommand.php delete mode 100644 Generator/DatatableGenerator.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 680eb4a2..e38e3953 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# Version 1.3 + +* Dropped support for PHP 7.1 +* Dropped support for Symfony 3.4 and <=4.3 +* Support for PHP 8 +* Support for Symfony 6 + # Version 1.1.1 * Bugfix: DateRangeFilter overwrites other filter (#803) diff --git a/Command/CreateDatatableCommand.php b/Command/CreateDatatableCommand.php deleted file mode 100644 index c6dcae9f..00000000 --- a/Command/CreateDatatableCommand.php +++ /dev/null @@ -1,213 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Sg\DatatablesBundle\Command; - -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Exception; -use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCommand; -use Sensio\Bundle\GeneratorBundle\Command\Validators; -use Sg\DatatablesBundle\Generator\DatatableGenerator; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\HttpKernel\Bundle\BundleInterface; - -class CreateDatatableCommand extends GenerateDoctrineCommand -{ - //------------------------------------------------- - // The 'sg:datatable:generate' Command - //------------------------------------------------- - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setName('sg:datatable:generate') - ->setAliases(['sg:datatables:generate', 'sg:generate:datatable', 'sg:generate:datatables']) - ->setDescription('Generates a new Datatable based on a Doctrine entity.') - ->addArgument('entity', InputArgument::REQUIRED, 'The entity class name (shortcut notation).') - ->addOption('fields', 'f', InputOption::VALUE_OPTIONAL, 'The fields to create columns in the new Datatable.') - ->addOption('overwrite', 'o', InputOption::VALUE_NONE, 'Allow to overwrite an existing Datatable.') - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - // get entity argument - $entity = Validators::validateEntityName($input->getArgument('entity')); - list($bundle, $entity) = $this->parseShortcutNotation($entity); - - // get entity's metadata - $entityClass = $this->getContainer()->get('doctrine')->getAliasNamespace($bundle).'\\'.$entity; - $metadata = $this->getEntityMetadata($entityClass); - - // get fields option - $fieldsOption = $input->getOption('fields'); - null === $fieldsOption ? $fields = $this->getFieldsFromMetadata($metadata[0]) : $fields = $this->parseFields($fieldsOption); - - // get overwrite option - $overwrite = $input->getOption('overwrite'); - - // get the entity's primary key - $id = $this->getIdentifierFromMetadata($metadata); - - // get the bundle in which to create the Datatable - $bundle = $this->getContainer()->get('kernel')->getBundle($bundle); - - /** @var DatatableGenerator $generator */ - $generator = $this->getGenerator($bundle); - $generator->generate($bundle, $entity, $fields, $id[0], $overwrite); - - $output->writeln( - sprintf( - 'The new Datatable %s.php has been created under %s.', - $generator->getClassName(), - $generator->getClassPath() - ) - ); - } - - /** - * {@inheritdoc} - */ - protected function createGenerator() - { - return new DatatableGenerator($this->getContainer()->get('filesystem')); - } - - /** - * {@inheritdoc} - */ - protected function getSkeletonDirs(BundleInterface $bundle = null) - { - $skeletonDirs = []; - $skeletonDirs[] = $this->getContainer()->get('kernel')->locateResource('@SgDatatablesBundle/Resources/views/skeleton'); - - return $skeletonDirs; - } - - //------------------------------------------------- - // Helper - //------------------------------------------------- - - /** - * Parse fields. - * - * @param string $input - * - * @return array - */ - private static function parseFields($input) - { - $fields = []; - - foreach (explode(' ', $input) as $value) { - $elements = explode(':', $value); - - $row = []; - $row['property'] = $elements[0]; - $row['column_type'] = 'Column::class'; - $row['data'] = null; - $row['title'] = ucwords(str_replace('.', ' ', $elements[0])); - - if (isset($elements[1])) { - switch ($elements[1]) { - case 'datetime': - $row['column_type'] = 'DateTimeColumn::class'; - - break; - case 'boolean': - $row['column_type'] = 'BooleanColumn::class'; - - break; - } - } - - $fields[] = $row; - } - - return $fields; - } - - /** - * Get Id from metadata. - * - * @throws Exception - */ - private function getIdentifierFromMetadata(array $metadata) - { - if (\count($metadata[0]->identifier) > 1) { - throw new Exception('CreateDatatableCommand::getIdentifierFromMetadata(): The Datatable generator does not support entities with multiple primary keys.'); - } - - return $metadata[0]->identifier; - } - - /** - * Returns an array of fields. Fields can be both column fields and - * association fields. - * - * @return array $fields - */ - private function getFieldsFromMetadata(ClassMetadataInfo $metadata) - { - $fields = []; - - foreach ($metadata->fieldMappings as $field) { - $row = []; - $row['property'] = $field['fieldName']; - - switch ($field['type']) { - case 'datetime': - $row['column_type'] = 'DateTimeColumn::class'; - - break; - case 'boolean': - $row['column_type'] = 'BooleanColumn::class'; - - break; - default: - $row['column_type'] = 'Column::class'; - } - - $row['title'] = ucwords($field['fieldName']); - $row['data'] = null; - $fields[] = $row; - } - - foreach ($metadata->associationMappings as $relation) { - $targetClass = $relation['targetEntity']; - $targetMetadata = $this->getEntityMetadata($targetClass); - - foreach ($targetMetadata[0]->fieldMappings as $field) { - $row = []; - $row['property'] = $relation['fieldName'].'.'.$field['fieldName']; - $row['column_type'] = 'Column::class'; - $row['title'] = ucwords(str_replace('.', ' ', $row['property'])); - if (ClassMetadataInfo::ONE_TO_MANY === $relation['type'] || ClassMetadataInfo::MANY_TO_MANY === $relation['type']) { - $row['data'] = $relation['fieldName'].'[, ].'.$field['fieldName']; - } else { - $row['data'] = null; - } - $fields[] = $row; - } - } - - return $fields; - } -} diff --git a/Controller/DatatableController.php b/Controller/DatatableController.php index 65a68250..bd5a888e 100755 --- a/Controller/DatatableController.php +++ b/Controller/DatatableController.php @@ -13,6 +13,7 @@ use DateTime; use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\EntityManagerInterface; use Exception; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; @@ -37,7 +38,7 @@ class DatatableController extends AbstractController * * @return Response */ - public function editAction(Request $request) + public function editAction(Request $request, EntityManagerInterface $entityManager): Response { if ($request->isXmlHttpRequest()) { // x-editable sends some default parameters @@ -57,7 +58,7 @@ public function editAction(Request $request) } // get an object by its primary key - $entity = $this->getEntityByPk($entityClassName, $pk); + $entity = $this->getEntityByPk($entityClassName, $pk, $entityManager); /** @var PropertyAccessor $accessor */ /** @noinspection PhpUndefinedMethodInspection */ @@ -73,9 +74,8 @@ public function editAction(Request $request) null !== $path ? $accessor->setValue($entity, $path, $value) : $accessor->setValue($entity, $field, $value); // save all - $em = $this->getDoctrine()->getManager(); - $em->persist($entity); - $em->flush(); + $entityManager->persist($entity); + $entityManager->flush(); return new Response('Success', 200); } @@ -92,11 +92,9 @@ public function editAction(Request $request) * * @param string $entityClassName */ - private function getEntityByPk($entityClassName, $pk): object + private function getEntityByPk($entityClassName, $pk, EntityManagerInterface $entityManager): object { - $em = $this->getDoctrine()->getManager(); - - $entity = $em->getRepository($entityClassName)->find($pk); + $entity = $entityManager->getRepository($entityClassName)->find($pk); if (! $entity) { throw $this->createNotFoundException('DatatableController::getEntityByPk(): The entity does not exist.'); } diff --git a/Generator/DatatableGenerator.php b/Generator/DatatableGenerator.php deleted file mode 100644 index c93df5d9..00000000 --- a/Generator/DatatableGenerator.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Sg\DatatablesBundle\Generator; - -use Exception; -use Sensio\Bundle\GeneratorBundle\Generator\Generator; -use Symfony\Component\HttpKernel\Bundle\BundleInterface; - -class DatatableGenerator extends Generator -{ - /** - * @var string - */ - private $className; - - /** - * @var string - */ - private $classPath; - - public function __construct() - { - $this->className = ''; - $this->classPath = ''; - } - - //------------------------------------------------- - // Generator - //------------------------------------------------- - - /** - * Generates a new Datatable if it does not exist. - * - * @param BundleInterface $bundle The bundle in which to create the Datatable - * @param string $entity The entity class name - * @param array $fields the fields to create columns in the new Datatable - * @param mixed $id the entity's primary key - * @param array $overwrite allow to overwrite an existing Datatable - * - * @throws Exception - */ - public function generate(BundleInterface $bundle, $entity, array $fields, $id, $overwrite) - { - $parts = explode('\\', $entity); - $entityClass = array_pop($parts); - $entityClassLowerCase = strtolower($entityClass); - - $this->className = $entityClass.'Datatable'; - $dirPath = $bundle->getPath().'/Datatables'; - $this->classPath = $dirPath.'/'.str_replace('\\', '/', $entity).'Datatable.php'; - - if (! $overwrite) { - if (file_exists($this->classPath)) { - throw new Exception(sprintf('Unable to generate the %s as it already exists under the %s.', $this->className, $this->classPath)); - } - } - - $parts = explode('\\', $entity); - array_pop($parts); - - $this->renderFile('datatable.php.twig', $this->classPath, [ - 'namespace' => $bundle->getNamespace(), - 'entity_namespace' => implode('\\', $parts), - 'entity_class' => $entityClass, - 'bundle' => $bundle->getName(), - 'datatable_class' => $this->className, - 'datatable_name' => $entityClassLowerCase.'_datatable', - 'fields' => $fields, - 'route_pref' => $entityClassLowerCase, - 'id' => $id, - ]); - } - - //------------------------------------------------- - // Getters && Setters - //------------------------------------------------- - - /** - * Get class name. - * - * @return string - */ - public function getClassName() - { - return $this->className; - } - - /** - * Get class path. - * - * @return string - */ - public function getClassPath() - { - return $this->classPath; - } -} diff --git a/composer.json b/composer.json index 83ab9052..3ce8d32a 100755 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "sg/datatablesbundle", "type": "symfony-bundle", "description": "Symfony Datatable Bundle For Doctrine2 Entities", - "keywords": ["symfony3", "datatable", "datatables", "data-table", "grid", "table", "datagrid", "pagination"], + "keywords": ["symfony", "datatable", "datatables", "data-table", "grid", "table", "datagrid", "pagination"], "homepage": "https://github.com/stwe/DatatablesBundle", "license": "MIT", "authors": [ @@ -18,23 +18,23 @@ "issues": "https://github.com/stwe/DatatablesBundle/issues" }, "require": { - "php": ">=7.1", + "php": ">=7.2|>=8.0", "doctrine/orm": "^2.5", - "friendsofsymfony/jsrouting-bundle": "^1.6|^2.0|^3.0", - "symfony/config": "^3.4|^4.1|^5.0", - "symfony/dependency-injection": "^3.4|^4.1|^5.0", - "symfony/http-foundation": "^3.4|^4.1|^5.0", - "symfony/http-kernel": "^3.4|^4.1|^5.0", - "symfony/framework-bundle": "^3.4|^4.1|^5.0", - "symfony/options-resolver": "^3.4|^4.1|^5.0", - "symfony/property-access": "^3.4|^4.1|^5.0", - "symfony/routing": "^3.4|^4.1|^5.0", - "symfony/security-core": "^3.4|^4.1|^5.0", - "symfony/translation": "^3.4|^4.1|^5.0", + "friendsofsymfony/jsrouting-bundle": "^2.0|^3.0", + "symfony/config": "^4.4|^5.4|^6.0", + "symfony/dependency-injection": "^4.4|^5.4|^6.0", + "symfony/http-foundation": "^4.4|^5.4|^6.0", + "symfony/http-kernel": "^4.4|^5.4|^6.0", + "symfony/framework-bundle": "^4.4|^5.4|^6.0", + "symfony/options-resolver": "^4.4|^5.4|^6.0", + "symfony/property-access": "^4.4|^5.4|^6.0", + "symfony/routing": "^4.4|^5.4|^6.0", + "symfony/security-core": "^4.4|^5.4|^6.0", + "symfony/translation": "^4.4|^5.4|^6.0", "twig/twig": "^2.9|^3.0" }, "require-dev": { - "phpunit/phpunit": "^7.5|^8.5", + "phpunit/phpunit": "^8.5|^9.5", "friendsofphp/php-cs-fixer": "^3.6" }, "autoload": {