/**
  * @param AbstractDataTable $table
  * @param \Symfony\Component\HttpFoundation\Request $request
  * @return \Symfony\Component\HttpFoundation\JsonResponse
  * @throws \Exception
  */
 public function processRequest(AbstractDataTable $table, \Symfony\Component\HttpFoundation\Request $request)
 {
     $this->table = $table;
     $this->request = new DataTablesRequest($request);
     $response = new Response();
     $response->draw = $this->request->getDraw();
     $qb = $this->createQueryBuilder();
     $response->recordsTotal = $this->countTotals($qb);
     $response->recordsFiltered = $this->applyFilterAndCount($qb);
     if (null === $response->recordsFiltered) {
         $response->recordsFiltered = $response->recordsTotal;
     }
     // select entities
     $prefixes = array_merge([$this->table->getPrefix()], $this->table->getJoinPrefixes());
     call_user_func_array([$qb, 'select'], $prefixes);
     // add count
     if ($this->table->getHasScalarColumns()) {
         foreach ($this->table->getColumns() as $column) {
             if ($column instanceof EntitiesCountColumn) {
                 $qb->addSelect('count(' . $column->getEntityPrefix() . ') as ' . $column->getField() . '_count');
                 // '.' .  $column->getField() .
             } elseif ($column instanceof EntitiesScalarColumn) {
                 $qb->addSelect($column->getOperation() . '(' . $column->getEntityPrefix() . '.' . $column->getEntityField() . ') as ' . $column->getField() . '_' . $column->getOperation());
                 // '.' .  $column->getField() .
                 $qb->addGroupBy($this->table->getPrefix() . '.id');
             }
         }
     }
     // paginate
     $paginate = clone $qb;
     $paginate->select('distinct(' . $this->table->getPrefix() . '.' . $this->getIdentifierField() . ')');
     // add scalar fields as hidden (todo: clean up this mess)
     if ($this->table->getHasScalarColumns()) {
         foreach ($this->table->getColumns() as $column) {
             if ($column instanceof EntitiesCountColumn) {
                 $paginate->addSelect('count(' . $column->getEntityPrefix() . ') as hidden ' . $column->getField() . '_count');
                 // '.' .  $column->getField() .
             } elseif ($column instanceof EntitiesScalarColumn) {
                 $paginate->addSelect($column->getOperation() . '(' . $column->getEntityPrefix() . '.' . $column->getEntityField() . ') as hidden ' . $column->getField() . '_' . $column->getOperation());
                 // '.' .  $column->getField() .
                 $paginate->addGroupBy($this->table->getPrefix() . '.id');
             }
         }
     }
     $paginate->setFirstResult($this->request->getStart())->setMaxResults($this->request->getLength());
     $ids = $paginate->getQuery()->getResult();
     // order
     $this->applyOrder($qb);
     $qb->andWhere($this->table->getPrefix() . '.' . $this->getIdentifierField() . ' in (:ids)')->setParameter('ids', $ids);
     // get result
     $resultCallback = $this->table->getResultCallback();
     if (null !== $resultCallback) {
         call_user_func($resultCallback, $this->table, $qb, $response, $this->dataConverter);
     } else {
         call_user_func(['Voelkel\\DataTablesBundle\\DataTables\\DataBuilder', 'build'], $this->table, $qb, $response, $this->dataConverter, $this->table->getRowCallback());
     }
     return $response->create();
 }
 /**
  * @param AbstractDataTable $table
  * @param \Doctrine\ORM\QueryBuilder $qb
  * @param Response $response
  * @param DataToStringConverter $dataToStringConverter
  * @throws \Exception
  */
 public static function build(AbstractDataTable $table, \Doctrine\ORM\QueryBuilder $qb, Response $response, DataToStringConverter $dataToStringConverter, $rowCallback = null)
 {
     $entities = $qb->getQuery()->getResult();
     foreach ($entities as $result) {
         $entity = $result;
         if ($table->getHasScalarColumns()) {
             $entity = $result[0];
         }
         $tmp = [];
         if (method_exists($entity, 'getId')) {
             $tmp['DT_RowId'] = 'row_' . $entity->getId();
             $tmp['DT_RowAttr'] = ['data-entity' => $entity->getId()];
             // DT_RowClass
             // DT_RowData
         }
         if (is_callable($rowCallback)) {
             $cbResult = $rowCallback($entity, $table);
             $tmp = array_merge($tmp, $cbResult);
         }
         foreach ($table->getColumns() as $column) {
             if ($column instanceof EntitiesCountColumn) {
                 $tmp[$column->getName()] = $result[$column->getField() . '_count'];
             } elseif ($column instanceof EntitiesScalarColumn) {
                 $tmp[$column->getName()] = $result[$column->getField() . '_' . $column->getOperation()];
             } else {
                 $tmp[$column->getName()] = self::getColumnProperty($entity, $column, $dataToStringConverter);
             }
         }
         $response->data[] = $tmp;
     }
 }