/**
  * Recursive iterates through filters and builds an expression to be applied to the given data source
  *
  * @param array                              $filters
  * @param GroupingOrmFilterDatasourceAdapter $ds
  */
 protected function buildRestrictions(array &$filters, GroupingOrmFilterDatasourceAdapter $ds)
 {
     $operatorStack = [FilterUtility::CONDITION_AND];
     foreach ($filters as $item) {
         if (is_string($item)) {
             array_push($operatorStack, $item);
         } elseif (!isset($item['filter'])) {
             $ds->beginRestrictionGroup(array_pop($operatorStack));
             $this->buildRestrictions($item, $ds);
             $ds->endRestrictionGroup();
         } else {
             $operator = array_pop($operatorStack);
             /** @var FilterInterface $filter */
             $filter = $this->getFilterObject($item['filter'], $item['column']);
             $form = $filter->getForm();
             if (!$form->isSubmitted()) {
                 $form->submit($item['filterData']);
             }
             if ($form->isValid()) {
                 $ds->beginRestrictionGroup($operator);
                 $filter->apply($ds, $form->getData());
                 $ds->endRestrictionGroup();
             }
         }
     }
 }
 public function testComplexComputedExpr()
 {
     $qb = new QueryBuilder($this->getTestEntityManager());
     $qb->select(['u.status, COUNT(u.id)'])->from('Oro\\Bundle\\QueryDesignerBundle\\Tests\\Unit\\Fixtures\\Models\\CMS\\CmsUser', 'u')->groupBy('u.status')->having('COUNT(u.id) = 0');
     $ds = new GroupingOrmFilterDatasourceAdapter($qb);
     //  src: (1 AND ((2 AND (3 OR 4)) OR (5) OR (6 AND 7)) AND 8)
     // dest: (1 AND ((2 AND (3 OR 4)) OR 5 OR (6 AND 7)) AND 8)
     $ds->addRestriction($qb->expr()->eq('COUNT(u.id)', '1'), FilterUtility::CONDITION_AND, true);
     $ds->beginRestrictionGroup(FilterUtility::CONDITION_AND);
     $ds->beginRestrictionGroup(FilterUtility::CONDITION_AND);
     $ds->addRestriction($qb->expr()->eq('COUNT(u.id)', '2'), FilterUtility::CONDITION_AND, true);
     $ds->beginRestrictionGroup(FilterUtility::CONDITION_AND);
     $ds->addRestriction($qb->expr()->eq('COUNT(u.id)', '3'), FilterUtility::CONDITION_AND, true);
     $ds->addRestriction($qb->expr()->eq('COUNT(u.id)', '4'), FilterUtility::CONDITION_OR, true);
     $ds->endRestrictionGroup();
     $ds->endRestrictionGroup();
     $ds->beginRestrictionGroup(FilterUtility::CONDITION_OR);
     $ds->addRestriction($qb->expr()->eq('COUNT(u.id)', '5'), FilterUtility::CONDITION_AND, true);
     $ds->endRestrictionGroup();
     $ds->beginRestrictionGroup(FilterUtility::CONDITION_OR);
     $ds->addRestriction($qb->expr()->eq('COUNT(u.id)', '6'), FilterUtility::CONDITION_AND, true);
     $ds->addRestriction($qb->expr()->eq('COUNT(u.id)', '7'), FilterUtility::CONDITION_AND, true);
     $ds->endRestrictionGroup();
     $ds->endRestrictionGroup();
     $ds->addRestriction($qb->expr()->eq('COUNT(u.id)', '8'), FilterUtility::CONDITION_AND, true);
     $ds->applyRestrictions();
     $this->assertEquals('SELECT u.status, COUNT(u.id) FROM Oro\\Bundle\\QueryDesignerBundle\\Tests\\Unit\\Fixtures\\Models\\CMS\\CmsUser u ' . 'GROUP BY u.status ' . 'HAVING COUNT(u.id) = 0 AND ' . '(COUNT(u.id) = 1 AND ' . '((COUNT(u.id) = 2 AND (COUNT(u.id) = 3 OR COUNT(u.id) = 4)) ' . 'OR COUNT(u.id) = 5 OR (COUNT(u.id) = 6 AND COUNT(u.id) = 7)) AND ' . 'COUNT(u.id) = 8)', $qb->getDQL());
 }
 public function testComplexExpr()
 {
     $qb = new QueryBuilder($this->getTestEntityManager());
     $qb->select(['u.id'])->from('Oro\\Bundle\\QueryDesignerBundle\\Tests\\Unit\\Fixtures\\Models\\CMS\\CmsUser', 'u')->where('u.id = 0');
     $ds = new GroupingOrmFilterDatasourceAdapter($qb);
     //  src: (1 AND ((2 AND (3 OR 4)) OR (5) OR (6 AND 7)) AND 8)
     // dest: (1 AND ((2 AND (3 OR 4)) OR 5 OR (6 AND 7)) AND 8)
     $ds->addRestriction($qb->expr()->eq('u.name', '1'), FilterUtility::CONDITION_AND);
     $ds->beginRestrictionGroup(FilterUtility::CONDITION_AND);
     $ds->beginRestrictionGroup(FilterUtility::CONDITION_AND);
     $ds->addRestriction($qb->expr()->eq('u.name', '2'), FilterUtility::CONDITION_AND);
     $ds->beginRestrictionGroup(FilterUtility::CONDITION_AND);
     $ds->addRestriction($qb->expr()->eq('u.name', '3'), FilterUtility::CONDITION_AND);
     $ds->addRestriction($qb->expr()->eq('u.name', '4'), FilterUtility::CONDITION_OR);
     $ds->endRestrictionGroup();
     $ds->endRestrictionGroup();
     $ds->beginRestrictionGroup(FilterUtility::CONDITION_OR);
     $ds->addRestriction($qb->expr()->eq('u.name', '5'), FilterUtility::CONDITION_AND);
     $ds->endRestrictionGroup();
     $ds->beginRestrictionGroup(FilterUtility::CONDITION_OR);
     $ds->addRestriction($qb->expr()->eq('u.name', '6'), FilterUtility::CONDITION_AND);
     $ds->addRestriction($qb->expr()->eq('u.name', '7'), FilterUtility::CONDITION_AND);
     $ds->endRestrictionGroup();
     $ds->endRestrictionGroup();
     $ds->addRestriction($qb->expr()->eq('u.name', '8'), FilterUtility::CONDITION_AND);
     $ds->applyRestrictions();
     $this->assertEquals('SELECT u.id FROM Oro\\Bundle\\QueryDesignerBundle\\Tests\\Unit\\Fixtures\\Models\\CMS\\CmsUser u ' . 'WHERE u.id = 0 AND ' . '(u.name = 1 AND ' . '((u.name = 2 AND (u.name = 3 OR u.name = 4)) OR u.name = 5 OR (u.name = 6 AND u.name = 7)) AND ' . 'u.name = 8)', $qb->getDQL());
 }