vendor/lexik/form-filter-bundle/Event/Subscriber/DoctrineORMSubscriber.php line 67

Open in your IDE?
  1. <?php
  2. namespace Lexik\Bundle\FormFilterBundle\Event\Subscriber;
  3. use Doctrine\Common\Collections\Collection;
  4. use Doctrine\DBAL\Connection;
  5. use Doctrine\DBAL\Types\Types;
  6. use Doctrine\ORM\EntityManagerInterface;
  7. use Doctrine\ORM\QueryBuilder;
  8. use Doctrine\ORM\Mapping\ClassMetadataInfo;
  9. use Lexik\Bundle\FormFilterBundle\Event\GetFilterConditionEvent;
  10. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  11. /**
  12.  * Register listeners to compute conditions to be applied on a Doctrine ORM query builder.
  13.  *
  14.  * @author Cédric Girard <[email protected]>
  15.  */
  16. class DoctrineORMSubscriber extends AbstractDoctrineSubscriber implements EventSubscriberInterface
  17. {
  18.     /**
  19.      * @return array
  20.      */
  21.     public static function getSubscribedEvents()
  22.     {
  23.         return array(
  24.             // Lexik form filter types
  25.             'lexik_form_filter.apply.orm.filter_boolean'        => array('filterBoolean'),
  26.             'lexik_form_filter.apply.orm.filter_checkbox'       => array('filterCheckbox'),
  27.             'lexik_form_filter.apply.orm.filter_choice'         => array('filterValue'),
  28.             'lexik_form_filter.apply.orm.filter_date'           => array('filterDate'),
  29.             'lexik_form_filter.apply.orm.filter_date_range'     => array('filterDateRange'),
  30.             'lexik_form_filter.apply.orm.filter_datetime'       => array('filterDateTime'),
  31.             'lexik_form_filter.apply.orm.filter_datetime_range' => array('filterDateTimeRange'),
  32.             'lexik_form_filter.apply.orm.filter_entity'         => array('filterEntity'),
  33.             'lexik_form_filter.apply.orm.filter_number'         => array('filterNumber'),
  34.             'lexik_form_filter.apply.orm.filter_number_range'   => array('filterNumberRange'),
  35.             'lexik_form_filter.apply.orm.filter_text'           => array('filterText'),
  36.             // Symfony types
  37.             'lexik_form_filter.apply.orm.text'     => array('filterText'),
  38.             'lexik_form_filter.apply.orm.email'    => array('filterValue'),
  39.             'lexik_form_filter.apply.orm.integer'  => array('filterValue'),
  40.             'lexik_form_filter.apply.orm.money'    => array('filterValue'),
  41.             'lexik_form_filter.apply.orm.number'   => array('filterValue'),
  42.             'lexik_form_filter.apply.orm.percent'  => array('filterValue'),
  43.             'lexik_form_filter.apply.orm.search'   => array('filterValue'),
  44.             'lexik_form_filter.apply.orm.url'      => array('filterValue'),
  45.             'lexik_form_filter.apply.orm.choice'   => array('filterValue'),
  46.             'lexik_form_filter.apply.orm.entity'   => array('filterEntity'),
  47.             'lexik_form_filter.apply.orm.country'  => array('filterValue'),
  48.             'lexik_form_filter.apply.orm.language' => array('filterValue'),
  49.             'lexik_form_filter.apply.orm.locale'   => array('filterValue'),
  50.             'lexik_form_filter.apply.orm.timezone' => array('filterValue'),
  51.             'lexik_form_filter.apply.orm.date'     => array('filterDate'),
  52.             'lexik_form_filter.apply.orm.datetime' => array('filterDate'),
  53.             'lexik_form_filter.apply.orm.birthday' => array('filterDate'),
  54.             'lexik_form_filter.apply.orm.checkbox' => array('filterValue'),
  55.             'lexik_form_filter.apply.orm.radio'    => array('filterValue'),
  56.         );
  57.     }
  58.     /**
  59.      * @param GetFilterConditionEvent $event
  60.      * @throws \Exception
  61.      */
  62.     public function filterEntity(GetFilterConditionEvent $event)
  63.     {
  64.         $expr   $event->getFilterQuery()->getExpr();
  65.         $values $event->getValues();
  66.         if (is_object($values['value'])) {
  67.             $paramName $this->generateParameterName($event->getField());
  68.             $filterField $event->getField();
  69.             /** @var QueryBuilder $queryBuilder */
  70.             $queryBuilder $event->getQueryBuilder();
  71.             if ($dqlFrom $event->getQueryBuilder()->getDQLPart('from')) {
  72.                 $rootPart reset($dqlFrom);
  73.                 $fieldName ltrim($event->getField(), $rootPart->getAlias() . '.');
  74.                 $metadata $queryBuilder->getEntityManager()->getClassMetadata($rootPart->getFrom());
  75.                 if (isset($metadata->associationMappings[$fieldName]) && (!$metadata->associationMappings[$fieldName]['isOwningSide'] || $metadata->associationMappings[$fieldName]['type'] === ClassMetadataInfo::MANY_TO_MANY)) {
  76.                     if (!$event->getFilterQuery()->hasJoinAlias($fieldName)) {
  77.                         $queryBuilder->leftJoin($event->getField(), $fieldName);
  78.                     }
  79.                     $filterField $fieldName;
  80.                 }
  81.             }
  82.             if ($values['value'] instanceof Collection) {
  83.                 $ids = array();
  84.                 foreach ($values['value'] as $value) {
  85.                     $ids[] = $this->getEntityIdentifier($value$queryBuilder->getEntityManager());
  86.                 }
  87.                 if (count($ids) > 0) {
  88.                     $event->setCondition(
  89.                         $expr->in($filterField':'.$paramName),
  90.                         array($paramName => array($idsConnection::PARAM_INT_ARRAY))
  91.                     );
  92.                 }
  93.             } else {
  94.                 $event->setCondition(
  95.                     $expr->eq($filterField':'.$paramName),
  96.                     array($paramName => array(
  97.                         $this->getEntityIdentifier($values['value'], $queryBuilder->getEntityManager()),
  98.                         Types::INTEGER
  99.                     ))
  100.                 );
  101.             }
  102.         }
  103.     }
  104.     /**
  105.      * @param object $value
  106.      * @return integer
  107.      * @throws \RuntimeException
  108.      */
  109.     protected function getEntityIdentifier($valueEntityManagerInterface $em)
  110.     {
  111.         $class get_class($value);
  112.         $metadata $em->getClassMetadata($class);
  113.         if ($metadata->isIdentifierComposite) {
  114.             throw new \RuntimeException(sprintf('Composite identifier is not supported by FilterEntityType.'$class));
  115.         }
  116.         $identifierValues $metadata->getIdentifierValues($value);
  117.         if (empty($identifierValues)) {
  118.             throw new \RuntimeException(sprintf('Can\'t get identifier value for class "%s".'$class));
  119.         }
  120.         return array_shift($identifierValues);
  121.     }
  122. }