diff --git a/Datatable/AbstractDatatable.php b/Datatable/AbstractDatatable.php index 805d13cf..ef484a87 100755 --- a/Datatable/AbstractDatatable.php +++ b/Datatable/AbstractDatatable.php @@ -155,7 +155,8 @@ public function __construct( $translator, RouterInterface $router, EntityManagerInterface $em, - Environment $twig + Environment $twig, + iterable $columnTypes ) { $this->validateName(); @@ -177,7 +178,7 @@ public function __construct( $this->twig = $twig; $metadata = $em->getClassMetadata($this->getEntity()); - $this->columnBuilder = new ColumnBuilder($metadata, $twig, $router, $this->getName(), $em); + $this->columnBuilder = new ColumnBuilder($metadata, $twig, $this->getName(), $em, $columnTypes); $this->ajax = new Ajax(); $this->options = new Options(); diff --git a/Datatable/Column/AbstractColumn.php b/Datatable/Column/AbstractColumn.php index e5c5f2cb..c073855e 100755 --- a/Datatable/Column/AbstractColumn.php +++ b/Datatable/Column/AbstractColumn.php @@ -240,14 +240,6 @@ abstract class AbstractColumn implements ColumnInterface */ protected $twig; - /** - * The Router. - * Is set in the ColumnBuilder. - * - * @var RouterInterface - */ - protected $router; - /** * The position in the Columns array. * Is set in the ColumnBuilder. diff --git a/Datatable/Column/ColumnBuilder.php b/Datatable/Column/ColumnBuilder.php index ef439007..4e130e01 100755 --- a/Datatable/Column/ColumnBuilder.php +++ b/Datatable/Column/ColumnBuilder.php @@ -35,13 +35,6 @@ class ColumnBuilder */ private $twig; - /** - * The router. - * - * @var RouterInterface - */ - private $router; - /** * The name of the associated Datatable. * @@ -85,14 +78,18 @@ class ColumnBuilder */ private $entityClassName; + /** + * @var iterable + */ + private $columnTypes; + /** * @param string $datatableName */ - public function __construct(ClassMetadata $metadata, Environment $twig, RouterInterface $router, $datatableName, EntityManagerInterface $em) + public function __construct(ClassMetadata $metadata, Environment $twig, $datatableName, EntityManagerInterface $em, iterable $columnTypes) { $this->metadata = $metadata; $this->twig = $twig; - $this->router = $router; $this->datatableName = $datatableName; $this->em = $em; @@ -100,6 +97,7 @@ public function __construct(ClassMetadata $metadata, Environment $twig, RouterIn $this->columnNames = []; $this->uniqueColumns = []; $this->entityClassName = $metadata->getName(); + $this->columnTypes = $columnTypes; } //------------------------------------------------- @@ -118,7 +116,22 @@ public function __construct(ClassMetadata $metadata, Environment $twig, RouterIn */ public function add($dql, $class, array $options = []) { - $column = Factory::create($class, ColumnInterface::class); + if (\is_object($class)) { + $column = Factory::create($class, ColumnInterface::class); + @trigger_error(sprintf('Using an object as column type is deprecated and will be removed in 2.0. Use a class name (FQCN) instead.'), E_USER_DEPRECATED); + } else { + $columns = []; + foreach ($this->columnTypes as $column) { + $columns[\get_class($column)] = $column; + } + + if (! \array_key_exists($class, $columns)) { + throw new \RuntimeException(sprintf('Column %s is not a service', $class)); + } + + $column = clone $columns[$class]; + } + $column->initOptions(); $this->handleDqlProperties($dql, $options, $column); @@ -269,7 +282,6 @@ private function setEnvironmentProperties(AbstractColumn $column) $column->setDatatableName($this->datatableName); $column->setEntityClassName($this->entityClassName); $column->setTwig($this->twig); - $column->setRouter($this->router); return $this; } diff --git a/Datatable/Column/LinkColumn.php b/Datatable/Column/LinkColumn.php index 51f0683e..b7df63d0 100644 --- a/Datatable/Column/LinkColumn.php +++ b/Datatable/Column/LinkColumn.php @@ -14,6 +14,7 @@ use Sg\DatatablesBundle\Datatable\Filter\TextFilter; use Sg\DatatablesBundle\Datatable\Helper; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Routing\RouterInterface; class LinkColumn extends AbstractColumn { @@ -68,6 +69,16 @@ class LinkColumn extends AbstractColumn */ protected $email; + /** + * @var RouterInterface + */ + private $router; + + public function __construct(RouterInterface $router) + { + $this->router = $router; + } + //------------------------------------------------- // ColumnInterface //------------------------------------------------- diff --git a/Datatable/Column/NumberColumn.php b/Datatable/Column/NumberColumn.php index f363b4f3..676fd031 100644 --- a/Datatable/Column/NumberColumn.php +++ b/Datatable/Column/NumberColumn.php @@ -221,6 +221,8 @@ private function renderTemplate($data, $pk = null, $path = null) } $data = $this->formatter->formatCurrency($data, $this->currency); + } elseif ($data === null) { + $data = null; } else { // expected number (int or float), other values will be converted to a numeric value $data = $this->formatter->format($data); diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index a0fea356..b2d82740 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -20,7 +20,7 @@ class Configuration implements ConfigurationInterface /** * {@inheritdoc} */ - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): TreeBuilder { $treeBuilder = new TreeBuilder('sg_datatables'); if (method_exists($treeBuilder, 'getRootNode')) { diff --git a/DependencyInjection/SgDatatablesExtension.php b/DependencyInjection/SgDatatablesExtension.php index de9e785b..ad23cd40 100644 --- a/DependencyInjection/SgDatatablesExtension.php +++ b/DependencyInjection/SgDatatablesExtension.php @@ -11,6 +11,7 @@ namespace Sg\DatatablesBundle\DependencyInjection; +use Sg\DatatablesBundle\Datatable\Column\ColumnInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; @@ -31,6 +32,9 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('services.yml'); $container->setParameter('sg_datatables.datatable.query', $config['datatable']['query']); + $container->registerForAutoconfiguration(ColumnInterface::class) + ->addTag('sg_datatables.column') + ; } /** diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 594ca6ea..9e6230cc 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -1,12 +1,16 @@ services: - sg_datatables.twig.extension: - class: Sg\DatatablesBundle\Twig\DatatableTwigExtension - public: false - tags: - - { name: twig.extension } + _defaults: + autoconfigure: true + autowire: true - sg_datatables.datatable.abstract: - class: Sg\DatatablesBundle\Datatable\AbstractDatatable + _instanceof: + Sg\DatatablesBundle\Datatable\Column\Column: + tags: ['sg_datatables.column'] + + Sg\DatatablesBundle\Datatable\Column\: + resource: '../../Datatable/Column/*' + + Sg\DatatablesBundle\Datatable\AbstractDatatable: abstract: true arguments: - '@security.authorization_checker' @@ -15,20 +19,29 @@ services: - '@router' - '@doctrine.orm.entity_manager' - '@twig' + - ! tagged sg_datatables.column - sg_datatables.response: - class: Sg\DatatablesBundle\Response\DatatableResponse + Sg\DatatablesBundle\Response\DatatableResponse: public: true arguments: - '@request_stack' + Sg\DatatablesBundle\Datatable\DatatableFactory: + public: true + + Sg\DatatablesBundle\Twig\DatatableTwigExtension: ~ + + # aliases for backwards compatibility, will be removed in 2.0 + sg_datatables.twig.extension: + alias: Sg\DatatablesBundle\Twig\DatatableTwigExtension + + sg_datatables.datatable.abstract: + alias: Sg\DatatablesBundle\Datatable\AbstractDatatable + + sg_datatables.response: + alias: Sg\DatatablesBundle\Response\DatatableResponse + public: true + sg_datatables.factory: - class: Sg\DatatablesBundle\Datatable\DatatableFactory + alias: Sg\DatatablesBundle\Datatable\DatatableFactory public: true - arguments: - - '@security.authorization_checker' - - '@security.token_storage' - - '@translator' - - '@router' - - '@doctrine.orm.entity_manager' - - '@twig' diff --git a/Resources/doc/cache.md b/Resources/doc/cache.md index 5a669ee1..20abb7d9 100644 --- a/Resources/doc/cache.md +++ b/Resources/doc/cache.md @@ -12,9 +12,10 @@ Doctrine Query when creating response for DataTable. ``` php <?php +use Sg\DatatablesBundle\Response\DatatableResponse; // ... if ($isAjax) { - $responseService = $this->get('sg_datatables.response'); + $responseService = $this->get(DatatableResponse::class); $responseService->setDatatable($datatable); $datatableQueryBuilder = $responseService->getDatatableQueryBuilder(); diff --git a/Resources/doc/installation.md b/Resources/doc/installation.md index 7cb98963..e0d17313 100644 --- a/Resources/doc/installation.md +++ b/Resources/doc/installation.md @@ -370,14 +370,19 @@ When declaring datatable "by hand" as extending `AbstractDatatable` class watch # app/config/services.yml services: - app.datatable.post: - class: AppBundle\Datatables\PostDatatable - parent: sg_datatables.datatable.abstract + _defaults: + autoconfigure: true + autowire: true + AppBundle\Datatables\PostDatatable: + bind: + $columnTypes: !tagged sg_datatables.column ``` ### Step 3: The Controller actions ``` php +use Sg\DatatablesBundle\Datatable\DatatableFactory; +use Sg\DatatablesBundle\Response\DatatableResponse; /** * Lists all Post entities. * @@ -398,11 +403,11 @@ public function indexAction(Request $request) // or use the DatatableFactory /** @var DatatableInterface $datatable */ - $datatable = $this->get('sg_datatables.factory')->create(PostDatatable::class); + $datatable = $this->get(DatatableFactory::class)->create(PostDatatable::class); $datatable->buildDatatable(); if ($isAjax) { - $responseService = $this->get('sg_datatables.response'); + $responseService = $this->get(DatatableResponse::class); $responseService->setDatatable($datatable); $responseService->getDatatableQueryBuilder(); diff --git a/Resources/doc/query.md b/Resources/doc/query.md index aba9af1e..41c64802 100644 --- a/Resources/doc/query.md +++ b/Resources/doc/query.md @@ -40,12 +40,14 @@ class Post Now you can view all posts created by `root`. The additional `where statement` now works like a filter. ``` php +use Sg\DatatablesBundle\Response\DatatableResponse; + public function indexAction(Request $request) { // ... if ($request->isXmlHttpRequest()) { - $responseService = $this->get('sg_datatables.response'); + $responseService = $this->get(DatatableResponse::class); $responseService->setDatatable($datatable); $datatableQueryBuilder = $responseService->getDatatableQueryBuilder(); diff --git a/Response/DatatableQueryBuilder.php b/Response/DatatableQueryBuilder.php index 8d8a340d..2445d5bb 100644 --- a/Response/DatatableQueryBuilder.php +++ b/Response/DatatableQueryBuilder.php @@ -186,6 +186,7 @@ class DatatableQueryBuilder //------------------------------------------------- // Ctor. && Init column arrays //------------------------------------------------- + private $columnNames; /** * @throws Exception diff --git a/composer.json b/composer.json index 3ce8d32a..8494161a 100755 --- a/composer.json +++ b/composer.json @@ -21,21 +21,21 @@ "php": ">=7.2|>=8.0", "doctrine/orm": "^2.5", "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", + "symfony/config": "^4.4|^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^4.4|^5.4|^6.0|^7.0", + "symfony/http-foundation": "^4.4|^5.4|^6.0|^7.0", + "symfony/http-kernel": "^4.4|^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^4.4|^5.4|^6.0|^7.0", + "symfony/options-resolver": "^4.4|^5.4|^6.0|^7.0", + "symfony/property-access": "^4.4|^5.4|^6.0|^7.0", + "symfony/routing": "^4.4|^5.4|^6.0|^7.0", + "symfony/security-core": "^4.4|^5.4|^6.0|^7.0", + "symfony/translation": "^4.4|^5.4|^6.0|^7.0", "twig/twig": "^2.9|^3.0" }, "require-dev": { - "phpunit/phpunit": "^8.5|^9.5", - "friendsofphp/php-cs-fixer": "^3.6" + "phpunit/phpunit": "^7.5|^8.5", + "friendsofphp/php-cs-fixer": "^2.15" }, "autoload": { "psr-4": { "Sg\\DatatablesBundle\\": "" }