ProxyQuery.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  5. * (c) Jonathan H. Wage <jonwage@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Sonata\AdminBundle\Datagrid\ORM;
  11. use Doctrine\ORM\QueryBuilder;
  12. use Doctrine\ORM\Query;
  13. use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
  14. /**
  15. * This class try to unify the query usage with Doctrine
  16. */
  17. class ProxyQuery implements ProxyQueryInterface
  18. {
  19. protected $queryBuilder;
  20. protected $sortBy;
  21. protected $sortOrder;
  22. public function __construct(QueryBuilder $queryBuilder)
  23. {
  24. $this->queryBuilder = $queryBuilder;
  25. }
  26. public function execute(array $params = array(), $hydrationMode = null)
  27. {
  28. // always clone the original queryBuilder
  29. $queryBuilder = clone $this->queryBuilder;
  30. // todo : check how doctrine behave, potential SQL injection here ...
  31. if ($this->getSortBy()) {
  32. $sortBy = $this->getSortBy();
  33. if (strpos($sortBy, '.') === false) { // add the current alias
  34. $sortBy = $queryBuilder->getRootAlias().'.'.$sortBy;
  35. }
  36. $queryBuilder->orderBy($sortBy, $this->getSortOrder());
  37. }
  38. return $this->getFixedQueryBuilder($queryBuilder)->getQuery()->execute($params, $hydrationMode);
  39. }
  40. /**
  41. * This method alters the query to return a clean set of object with a working
  42. * set of Object
  43. *
  44. * @param \Doctrine\ORM\QueryBuilder $queryBuilder
  45. * @return void
  46. */
  47. private function getFixedQueryBuilder(QueryBuilder $queryBuilder)
  48. {
  49. $queryBuilderId = clone $queryBuilder;
  50. // step 1 : retrieve the targeted class
  51. $from = $queryBuilderId->getDQLPart('from');
  52. $class = $from[0]->getFrom();
  53. // step 2 : retrieve the column id
  54. $idName = current($queryBuilderId->getEntityManager()->getMetadataFactory()->getMetadataFor($class)->getIdentifierFieldNames());
  55. // step 3 : retrieve the different subjects id
  56. $select = sprintf('%s.%s', $queryBuilderId->getRootAlias(), $idName);
  57. $queryBuilderId->select($select);
  58. $results = $queryBuilderId->getQuery()->execute(array(), Query::HYDRATE_ARRAY);
  59. $idx = array();
  60. foreach($results as $id) {
  61. $idx[] = $id[$idName];
  62. }
  63. // step 4 : alter the query to match the targeted ids
  64. $queryBuilder->andWhere(sprintf('%s IN (%s)', $select, implode(',', $idx)));
  65. $queryBuilder->setMaxResults(null);
  66. $queryBuilder->setFirstResult(null);
  67. return $queryBuilder;
  68. }
  69. public function __call($name, $args)
  70. {
  71. return call_user_func_array(array($this->queryBuilder, $name), $args);
  72. }
  73. public function setSortBy($sortBy)
  74. {
  75. $this->sortBy = $sortBy;
  76. }
  77. public function getSortBy()
  78. {
  79. return $this->sortBy;
  80. }
  81. public function setSortOrder($sortOrder)
  82. {
  83. $this->sortOrder = $sortOrder;
  84. }
  85. public function getSortOrder()
  86. {
  87. return $this->sortOrder;
  88. }
  89. public function getSingleScalarResult()
  90. {
  91. $query = $this->queryBuilder->getQuery();
  92. return $query->getSingleScalarResult();
  93. }
  94. public function __clone()
  95. {
  96. $this->queryBuilder = clone $this->queryBuilder;
  97. }
  98. }