Переглянути джерело

[orm] make the QueryProxy behave like Doctrine1 with join and limit close

Thomas Rabaix 14 роки тому
батько
коміт
61510c9eca

+ 7 - 1
Datagrid/Datagrid.php

@@ -37,6 +37,8 @@ class Datagrid implements DatagridInterface
 
     protected $formFactory;
 
+    protected $results;
+
     public function __construct(ProxyQueryInterface $query, ListCollection $columns, PagerInterface $pager, FormFactory $formFactory, array $values = array())
     {
         $this->pager    = $pager;
@@ -58,7 +60,11 @@ class Datagrid implements DatagridInterface
     {
         $this->buildPager();
 
-        return $this->pager->getResults();
+        if (!$this->results) {
+            $this->results = $this->pager->getResults();
+        }
+
+        return $this->results;
     }
 
     public function buildPager()

+ 1 - 1
Datagrid/ListMapper.php

@@ -51,7 +51,7 @@ class ListMapper
         } else if (is_string($name) && !$this->admin->hasListFieldDescription($name)) {
 
             $fieldDescription = $this->admin->getModelManager()->getNewFieldDescriptionInstance(
-                $this->admin->getClass(),
+                $this->admin->getClass(),   
                 $name,
                 $fieldDescriptionOptions
             );

+ 42 - 3
Datagrid/ORM/ProxyQuery.php

@@ -11,6 +11,7 @@
 namespace Sonata\AdminBundle\Datagrid\ORM;
 
 use Doctrine\ORM\QueryBuilder;
+use Doctrine\ORM\Query;
 use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
 
 /**
@@ -31,16 +32,54 @@ class ProxyQuery implements ProxyQueryInterface
 
     public function execute(array $params = array(), $hydrationMode = null)
     {
+        // always clone the original queryBuilder
+        $queryBuilder = clone $this->queryBuilder;
+
         // todo : check how doctrine behave, potential SQL injection here ...
         if ($this->getSortBy()) {
             $sortBy = $this->getSortBy();
             if (strpos($sortBy, '.') === false) { // add the current alias
-                $sortBy = $this->queryBuilder->getRootAlias().'.'.$sortBy;
+                $sortBy = $queryBuilder->getRootAlias().'.'.$sortBy;
             }
-            $this->queryBuilder->orderBy($sortBy, $this->getSortOrder());
+            $queryBuilder->orderBy($sortBy, $this->getSortOrder());
         }
 
-        return $this->queryBuilder->getQuery()->execute($params, $hydrationMode);
+        return $this->getFixedQueryBuilder($queryBuilder)->getQuery()->execute($params, $hydrationMode);
+    }
+
+    /**
+     * This method alters the query to return a clean set of object with a working
+     * set of Object
+     *
+     * @param \Doctrine\ORM\QueryBuilder $queryBuilder
+     * @return void
+     */
+    private function getFixedQueryBuilder(QueryBuilder $queryBuilder)
+    {
+        $queryBuilderId = clone $queryBuilder;
+
+        // step 1 : retrieve the targeted class
+        $from = $queryBuilderId->getDQLPart('from');
+        $class = $from[0]->getFrom();
+
+        // step 2 : retrieve the column id
+        $idName = current($queryBuilderId->getEntityManager()->getMetadataFactory()->getMetadataFor($class)->getIdentifierFieldNames());
+
+        // step 3 : retrieve the different subjects id
+        $select = sprintf('%s.%s', $queryBuilderId->getRootAlias(), $idName);
+        $queryBuilderId->select($select);
+        $results  = $queryBuilderId->getQuery()->execute(array(), Query::HYDRATE_ARRAY);
+        $idx      = array();
+        foreach($results as $id) {
+            $idx[] = $id[$idName];
+        }
+
+        // step 4 : alter the query to match the targeted ids
+        $queryBuilder->andWhere(sprintf('%s IN (%s)', $select, implode(',', $idx)));
+        $queryBuilder->setMaxResults(null);
+        $queryBuilder->setFirstResult(null);
+
+        return $queryBuilder;
     }
 
     public function __call($name, $args)

+ 1 - 1
Model/ORM/ModelManager.php

@@ -175,7 +175,7 @@ class ModelManager implements ModelManagerInterface
 
     public function getIdentifierFieldNames($class)
     {
-        $this->getMetadata($class)->getIdentifierFieldNames();
+        return $this->getMetadata($class)->getIdentifierFieldNames();
     }
 
     /**