11
11
namespace Sonata \AdminBundle \Datagrid \ORM ;
12
12
13
13
use Doctrine \ORM \QueryBuilder ;
14
+ use Doctrine \ORM \Query ;
14
15
use Sonata \AdminBundle \Datagrid \ProxyQueryInterface ;
15
16
16
17
/**
@@ -31,16 +32,54 @@ public function __construct(QueryBuilder $queryBuilder)
31
32
32
33
public function execute (array $ params = array (), $ hydrationMode = null )
33
34
{
35
+ // always clone the original queryBuilder
36
+ $ queryBuilder = clone $ this ->queryBuilder ;
37
+
34
38
// todo : check how doctrine behave, potential SQL injection here ...
35
39
if ($ this ->getSortBy ()) {
36
40
$ sortBy = $ this ->getSortBy ();
37
41
if (strpos ($ sortBy , '. ' ) === false ) { // add the current alias
38
- $ sortBy = $ this -> queryBuilder ->getRootAlias ().'. ' .$ sortBy ;
42
+ $ sortBy = $ queryBuilder ->getRootAlias ().'. ' .$ sortBy ;
39
43
}
40
- $ this -> queryBuilder ->orderBy ($ sortBy , $ this ->getSortOrder ());
44
+ $ queryBuilder ->orderBy ($ sortBy , $ this ->getSortOrder ());
41
45
}
42
46
43
- return $ this ->queryBuilder ->getQuery ()->execute ($ params , $ hydrationMode );
47
+ return $ this ->getFixedQueryBuilder ($ queryBuilder )->getQuery ()->execute ($ params , $ hydrationMode );
48
+ }
49
+
50
+ /**
51
+ * This method alters the query to return a clean set of object with a working
52
+ * set of Object
53
+ *
54
+ * @param \Doctrine\ORM\QueryBuilder $queryBuilder
55
+ * @return void
56
+ */
57
+ private function getFixedQueryBuilder (QueryBuilder $ queryBuilder )
58
+ {
59
+ $ queryBuilderId = clone $ queryBuilder ;
60
+
61
+ // step 1 : retrieve the targeted class
62
+ $ from = $ queryBuilderId ->getDQLPart ('from ' );
63
+ $ class = $ from [0 ]->getFrom ();
64
+
65
+ // step 2 : retrieve the column id
66
+ $ idName = current ($ queryBuilderId ->getEntityManager ()->getMetadataFactory ()->getMetadataFor ($ class )->getIdentifierFieldNames ());
67
+
68
+ // step 3 : retrieve the different subjects id
69
+ $ select = sprintf ('%s.%s ' , $ queryBuilderId ->getRootAlias (), $ idName );
70
+ $ queryBuilderId ->select ($ select );
71
+ $ results = $ queryBuilderId ->getQuery ()->execute (array (), Query::HYDRATE_ARRAY );
72
+ $ idx = array ();
73
+ foreach ($ results as $ id ) {
74
+ $ idx [] = $ id [$ idName ];
75
+ }
76
+
77
+ // step 4 : alter the query to match the targeted ids
78
+ $ queryBuilder ->andWhere (sprintf ('%s IN (%s) ' , $ select , implode (', ' , $ idx )));
79
+ $ queryBuilder ->setMaxResults (null );
80
+ $ queryBuilder ->setFirstResult (null );
81
+
82
+ return $ queryBuilder ;
44
83
}
45
84
46
85
public function __call ($ name , $ args )
0 commit comments