f865cf76ef8138d8446bc8c0d45683752c3aa602
[yaffs-website] / web / core / lib / Drupal / Core / Entity / Query / Sql / QueryAggregate.php
1 <?php
2
3 namespace Drupal\Core\Entity\Query\Sql;
4
5 use Drupal\Core\Entity\Query\QueryAggregateInterface;
6
7 /**
8  * The SQL storage entity query aggregate class.
9  */
10 class QueryAggregate extends Query implements QueryAggregateInterface {
11
12   /**
13    * Stores the sql expressions used to build the sql query.
14    *
15    * @var array
16    *   An array of expressions.
17    */
18   protected $sqlExpressions = [];
19
20   /**
21    * {@inheritdoc}
22    */
23   public function execute() {
24     return $this
25       ->prepare()
26       ->addAggregate()
27       ->compile()
28       ->compileAggregate()
29       ->addGroupBy()
30       ->addSort()
31       ->addSortAggregate()
32       ->finish()
33       ->result();
34   }
35
36   /**
37    * {@inheritdoc}
38    */
39   public function prepare() {
40     parent::prepare();
41     // Throw away the id fields.
42     $this->sqlFields = [];
43     return $this;
44   }
45
46   /**
47    * {@inheritdoc}
48    */
49   public function conditionAggregateGroupFactory($conjunction = 'AND') {
50     $class = static::getClass($this->namespaces, 'ConditionAggregate');
51     return new $class($conjunction, $this, $this->namespaces);
52   }
53
54   /**
55    * {@inheritdoc}
56    */
57   public function existsAggregate($field, $function, $langcode = NULL) {
58     return $this->conditionAggregate->exists($field, $function, $langcode);
59   }
60
61   /**
62    * {@inheritdoc}
63    */
64   public function notExistsAggregate($field, $function, $langcode = NULL) {
65     return $this->conditionAggregate->notExists($field, $function, $langcode);
66   }
67
68   /**
69    * Adds the aggregations to the query.
70    *
71    * @return \Drupal\Core\Entity\Query\Sql\QueryAggregate
72    *   Returns the called object.
73    */
74   protected function addAggregate() {
75     if ($this->aggregate) {
76       foreach ($this->aggregate as $aggregate) {
77         $sql_field = $this->getSqlField($aggregate['field'], $aggregate['langcode']);
78         $this->sqlExpressions[$aggregate['alias']] = $aggregate['function'] . "($sql_field)";
79       }
80     }
81     return $this;
82   }
83
84   /**
85    * Builds the aggregation conditions part of the query.
86    *
87    * @return \Drupal\Core\Entity\Query\Sql\QueryAggregate
88    *   Returns the called object.
89    */
90   protected function compileAggregate() {
91     $this->conditionAggregate->compile($this->sqlQuery);
92     return $this;
93   }
94
95   /**
96    * Adds the groupby values to the actual query.
97    *
98    * @return \Drupal\Core\Entity\Query\Sql\QueryAggregate
99    *   Returns the called object.
100    */
101   protected function addGroupBy() {
102     foreach ($this->groupBy as $group_by) {
103       $field = $group_by['field'];
104       $sql_field = $this->getSqlField($field, $group_by['langcode']);
105       $this->sqlGroupBy[$sql_field] = $sql_field;
106       list($table, $real_sql_field) = explode('.', $sql_field);
107       $this->sqlFields[$sql_field] = [$table, $real_sql_field, $this->createSqlAlias($field, $real_sql_field)];
108     }
109
110     return $this;
111   }
112
113   /**
114    * Builds the aggregation sort part of the query.
115    *
116    * @return \Drupal\Core\Entity\Query\Sql\QueryAggregate
117    *   Returns the called object.
118    */
119   protected function addSortAggregate() {
120     if (!$this->count) {
121       foreach ($this->sortAggregate as $alias => $sort) {
122         $this->sqlQuery->orderBy($alias, $sort['direction']);
123       }
124     }
125     return $this;
126   }
127
128   /**
129    * Overrides \Drupal\Core\Entity\Query\Sql\Query::finish().
130    *
131    * Adds the sql expressions to the query.
132    */
133   protected function finish() {
134     foreach ($this->sqlExpressions as $alias => $expression) {
135       $this->sqlQuery->addExpression($expression, $alias);
136     }
137     return parent::finish();
138   }
139
140   /**
141    * Builds a sql alias as expected in the result.
142    *
143    * @param string $field
144    *   The field as passed in by the caller.
145    * @param string $sql_field
146    *   The sql field as returned by getSqlField.
147    * @return string
148    *   The SQL alias expected in the return value. The dots in $sql_field are
149    *   replaced with underscores and if a default fallback to .value happened,
150    *   the _value is stripped.
151    */
152   public function createSqlAlias($field, $sql_field) {
153     $alias = str_replace('.', '_', $sql_field);
154     // If the alias contains of field_*_value remove the _value at the end.
155     if (substr($alias, 0, 6) === 'field_' && substr($field, -6) !== '_value' && substr($alias, -6) === '_value') {
156       $alias = substr($alias, 0, -6);
157     }
158     return $alias;
159   }
160
161   /**
162    * Overrides \Drupal\Core\Entity\Query\Sql\Query::result().
163    *
164    * @return array|int
165    *   Returns the aggregated result, or a number if it's a count query.
166    */
167   protected function result() {
168     if ($this->count) {
169       return parent::result();
170     }
171     $return = [];
172     foreach ($this->sqlQuery->execute() as $row) {
173       $return[] = (array) $row;
174     }
175     return $return;
176   }
177
178 }