Skip to content
This repository has been archived by the owner on Feb 4, 2023. It is now read-only.

Pass the container to the Factory so datatables and columns can be a service #784

Closed
wants to merge 12 commits into from
4 changes: 4 additions & 0 deletions Datatable/AbstractDatatable.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use Sg\DatatablesBundle\Datatable\Column\ColumnBuilder;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Translation\TranslatorInterface;
Expand Down Expand Up @@ -158,6 +159,7 @@ abstract class AbstractDatatable implements DatatableInterface
/**
* AbstractDatatable constructor.
*
* @param ContainerInterface $container
* @param AuthorizationCheckerInterface $authorizationChecker
* @param TokenStorageInterface $securityToken
* @param TranslatorInterface $translator
Expand All @@ -168,6 +170,7 @@ abstract class AbstractDatatable implements DatatableInterface
* @throws Exception
*/
public function __construct(
ContainerInterface $container,
AuthorizationCheckerInterface $authorizationChecker,
TokenStorageInterface $securityToken,
TranslatorInterface $translator,
Expand All @@ -192,6 +195,7 @@ public function __construct(

$metadata = $em->getClassMetadata($this->getEntity());
$this->columnBuilder = new ColumnBuilder($metadata, $twig, $router, $this->getName(), $em);
$this->columnBuilder->setContainer($container);

$this->ajax = new Ajax();
$this->options = new Options();
Expand Down
17 changes: 16 additions & 1 deletion Datatable/Column/AbstractColumn.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use Sg\DatatablesBundle\Datatable\OptionsTrait;
use Sg\DatatablesBundle\Datatable\AddIfTrait;
use Sg\DatatablesBundle\Datatable\Editable\EditableInterface;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Routing\RouterInterface;
use Doctrine\DBAL\Types\Type as DoctrineType;
Expand Down Expand Up @@ -72,6 +72,11 @@ abstract class AbstractColumn implements ColumnInterface
// pre-assigned with a value (true or false).
//--------------------------------------------------------------------------------------------------

/**
* @var ContainerInterface
*/
protected $container;

/**
* Change the cell type created for the column - either TD cells or TH cells.
* DataTables default: td
Expand Down Expand Up @@ -312,6 +317,16 @@ abstract class AbstractColumn implements ColumnInterface
//-------------------------------------------------

/**
* AbstractColumn constructor.
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}


/**
* Config options.
*
* @param OptionsResolver $resolver
Expand Down
3 changes: 3 additions & 0 deletions Datatable/Column/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Sg\DatatablesBundle\Datatable\Filter\TextFilter;
use Sg\DatatablesBundle\Datatable\Editable\EditableInterface;

use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
Expand All @@ -24,6 +25,8 @@
*/
class Column extends AbstractColumn
{
use ContainerAwareTrait;

/**
* The Column is editable.
*/
Expand Down
5 changes: 4 additions & 1 deletion Datatable/Column/ColumnBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\MappingException;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\Routing\RouterInterface;
use Twig_Environment;
use Exception;
Expand All @@ -27,6 +28,8 @@
*/
class ColumnBuilder
{
use ContainerAwareTrait;

/**
* The class metadata.
*
Expand Down Expand Up @@ -134,7 +137,7 @@ public function __construct(ClassMetadata $metadata, Twig_Environment $twig, Rou
*/
public function add($dql, $class, array $options = array())
{
$column = Factory::create($class, ColumnInterface::class);
$column = Factory::create($this->container, $class, ColumnInterface::class);
$column->initOptions();

$this->handleDqlProperties($dql, $options, $column);
Expand Down
3 changes: 2 additions & 1 deletion Datatable/Column/EditableTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Sg\DatatablesBundle\Datatable\Factory;

use Exception;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;

/**
* Class EditableTrait
Expand Down Expand Up @@ -68,7 +69,7 @@ public function setEditable($editableClassAndOptions)
throw new Exception('EditableTrait::setEditable(): Set an options array.');
}

$newEditable = Factory::create($editableClassAndOptions[0], EditableInterface::class);
$newEditable = Factory::create($this->container, $editableClassAndOptions[0], EditableInterface::class);
$this->editable = $newEditable->set($editableClassAndOptions[1]);
} else {
$this->editable = $editableClassAndOptions;
Expand Down
3 changes: 2 additions & 1 deletion Datatable/Column/FilterableTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Sg\DatatablesBundle\Datatable\Factory;

use Exception;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;

/**
* Class FilterableTrait
Expand Down Expand Up @@ -67,7 +68,7 @@ public function setFilter(array $filterClassAndOptions)
throw new Exception('AbstractColumn::setFilter(): Set an options array.');
}

$newFilter = Factory::create($filterClassAndOptions[0], FilterInterface::class);
$newFilter = Factory::create($this->container, $filterClassAndOptions[0], FilterInterface::class);
$this->filter = $newFilter->set($filterClassAndOptions[1]);

return $this;
Expand Down
10 changes: 10 additions & 0 deletions Datatable/DatatableFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Sg\DatatablesBundle\Datatable;

use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Translation\TranslatorInterface;
Expand All @@ -26,6 +27,8 @@
*/
class DatatableFactory
{
use ContainerAwareTrait;

/**
* The AuthorizationChecker service.
*
Expand Down Expand Up @@ -122,6 +125,13 @@ public function create($class)
}

if (in_array(DatatableInterface::class, class_implements($class))) {
if ($this->container->has($class)) {
/** @var DatatableInterface $datatable */
$datatable = $this->container->get($class);

return $datatable;
}

return new $class(
$this->authorizationChecker,
$this->securityToken,
Expand Down
10 changes: 8 additions & 2 deletions Datatable/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Sg\DatatablesBundle\Datatable;

use Exception;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Class Factory
Expand All @@ -23,13 +24,14 @@ class Factory
/**
* Create.
*
* @param ContainerInterface $container
* @param mixed $class
* @param mixed $interface
*
* @return mixed
* @throws Exception
*/
public static function create($class, $interface)
public static function create(ContainerInterface $container, $class, $interface)
{
if (empty($class) || !is_string($class) && !$class instanceof $interface) {
throw new Exception("Factory::create(): String or $interface expected.");
Expand All @@ -40,7 +42,11 @@ public static function create($class, $interface)
}

if (is_string($class) && class_exists($class)) {
$instance = new $class();
if ($container->has($class)) {
$instance = $container->get($class);
} else {
$instance = new $class($container);
}

if (!$instance instanceof $interface) {
throw new Exception("Factory::create(): String or $interface expected.");
Expand Down
1 change: 1 addition & 0 deletions Datatable/OptionsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ trait OptionsTrait
* @param bool $resolve
*
* @return $this
* @throws Exception
*/
public function initOptions($resolve = false)
{
Expand Down
2 changes: 2 additions & 0 deletions Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@ services:
- '@router'
- '@doctrine.orm.entity_manager'
- '@twig'
calls:
- [ setContainer, ['@service_container'] ]
3 changes: 3 additions & 0 deletions Resources/views/datatable/datatable_js.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@
$.extend(defaults, columns);
$.extend(defaults, initialSearch);

// Disables the alert when datatable fails to get data
$.fn.dataTable.ext.errMode = 'none';

if (!$.fn.dataTable.isDataTable(selector)) {
$(selector)
{% include '@SgDatatables/datatable/events.html.twig' %}
Expand Down
27 changes: 25 additions & 2 deletions Response/DatatableQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Sg\DatatablesBundle\Response;

use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Platforms\Keywords\KeywordList;
use Sg\DatatablesBundle\Datatable\Column\ColumnInterface;
use Sg\DatatablesBundle\Datatable\Filter\AbstractFilter;
use Sg\DatatablesBundle\Datatable\Filter\FilterInterface;
Expand Down Expand Up @@ -187,6 +188,11 @@ class DatatableQueryBuilder
*/
private $useCountResultCacheArgs = [false];

/**
* @var KeywordList
*/
private $reservedKeywordsList;

//-------------------------------------------------
// Ctor. && Init column arrays
//-------------------------------------------------
Expand All @@ -204,6 +210,7 @@ public function __construct(array $requestParams, DatatableInterface $datatable)
$this->requestParams = $requestParams;

$this->em = $datatable->getEntityManager();
$this->reservedKeywordsList = $this->em->getConnection()->getDatabasePlatform()->getReservedKeywordsList();
$this->entityName = $datatable->getEntity();

$this->metadata = $this->getMetadata($this->entityName);
Expand Down Expand Up @@ -263,6 +270,14 @@ private function initColumnArrays()
$currentPart = array_shift($parts);
$currentAlias = ($previousPart === $this->entityShortName ? '' : $previousPart.'_').$currentPart;

try {
$isReservedKeyword = $this->reservedKeywordsList->isKeyword($currentAlias);
} catch (DBALException $exception) {
$isReservedKeyword = false;
}

$currentAlias = $isReservedKeyword ? "_{$currentAlias}" : $currentAlias;

if (!array_key_exists($previousAlias.'.'.$currentPart, $this->joins)) {
$this->addJoin($previousAlias.'.'.$currentPart, $currentAlias, $this->accessor->getValue($column, 'joinType'));
}
Expand Down Expand Up @@ -727,6 +742,14 @@ private function addSearchOrderColumn($column, $columnTableName, $data)
*/
private function addJoin($columnTableName, $alias, $type)
{
try {
$isReservedKeyword = $this->reservedKeywordsList->isKeyword($alias);
} catch (DBALException $exception) {
$isReservedKeyword = false;
}

$alias = $isReservedKeyword ? "_{$alias}" : $alias;

$this->joins[$columnTableName] = array(
'alias' => $alias,
'type' => $type,
Expand Down Expand Up @@ -765,9 +788,9 @@ private function getMetadata($entityName)
private function getEntityShortName(ClassMetadata $metadata, EntityManagerInterface $entityManager)
{
$entityShortName = strtolower($metadata->getReflectionClass()->getShortName());

try {
$reservedKeywordsList = $entityManager->getConnection()->getDatabasePlatform()->getReservedKeywordsList();
$isReservedKeyword = $reservedKeywordsList->isKeyword($entityShortName);
$isReservedKeyword = $this->reservedKeywordsList->isKeyword($entityShortName);
} catch (DBALException $exception) {
$isReservedKeyword = false;
}
Expand Down
10 changes: 9 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@
"php": ">=7.1",
"symfony/framework-bundle": "^3.0|^4.0",
"doctrine/orm": "^2.5",
"symfony/options-resolver": "^3.0|^4.0",
"symfony/property-access": "^3.0|^4.0",
"friendsofsymfony/jsrouting-bundle": "^1.6|^2.0"
},
"require-dev": {
"symfony/security-bundle": "^3.0|^4.0",
"symfony/translation": "^3.0|^4.0",
"sensio/framework-extra-bundle": "^3.0|^4.0|^5.0",
"sensio/generator-bundle": "^3.0",
"phpspec/prophecy": "^1.7",
"twig/twig": "^1.0|^2.0",
"symfony/options-resolver": "^4.0"
},
"autoload": {
"psr-4": { "Sg\\DatatablesBundle\\": "" }
}
Expand Down