Upgraded drupal core with security updates
[yaffs-website] / web / core / tests / Drupal / KernelTests / Core / Entity / EntityQueryAggregateTest.php
1 <?php
2
3 namespace Drupal\KernelTests\Core\Entity;
4
5 use Drupal\field\Entity\FieldConfig;
6 use Drupal\field\Entity\FieldStorageConfig;
7
8 /**
9  * Tests the Entity Query Aggregation API.
10  *
11  * @group Entity
12  * @see \Drupal\entity_test\Entity\EntityTest
13  */
14 class EntityQueryAggregateTest extends EntityKernelTestBase {
15
16   /**
17    * Modules to enable.
18    *
19    * @var array
20    */
21   public static $modules = [];
22
23   /**
24    * The entity_test storage to create the test entities.
25    *
26    * @var \Drupal\entity_test\EntityTestStorage
27    */
28   protected $entityStorage;
29
30   /**
31    * The actual query result, to compare later.
32    *
33    * @var array
34    */
35   protected $queryResult;
36
37   /**
38    * The query factory to create entity queries.
39    *
40    * @var \Drupal\Core\Entity\Query\QueryFactory
41    */
42   public $factory;
43
44   protected function setUp() {
45     parent::setUp();
46
47     $this->entityStorage = $this->entityManager->getStorage('entity_test');
48     $this->factory = $this->container->get('entity.query');
49
50     // Add some fieldapi fields to be used in the test.
51     for ($i = 1; $i <= 2; $i++) {
52       $field_name = 'field_test_' . $i;
53       FieldStorageConfig::create([
54         'field_name' => $field_name,
55         'entity_type' => 'entity_test',
56         'type' => 'integer',
57         'cardinality' => 2,
58       ])->save();
59       FieldConfig::create([
60         'field_name' => $field_name,
61         'entity_type' => 'entity_test',
62         'bundle' => 'entity_test',
63       ])->save();
64     }
65
66     $entity = $this->entityStorage->create([
67       'id' => 1,
68       'user_id' => 1,
69       'field_test_1' => 1,
70       'field_test_2' => 2,
71     ]);
72     $entity->enforceIsNew();
73     $entity->save();
74
75     $entity = $this->entityStorage->create([
76       'id' => 2,
77       'user_id' => 2,
78       'field_test_1' => 1,
79       'field_test_2' => 7,
80     ]);
81     $entity->enforceIsNew();
82     $entity->save();
83     $entity = $this->entityStorage->create([
84       'id' => 3,
85       'user_id' => 2,
86       'field_test_1' => 2,
87       'field_test_2' => 1,
88     ]);
89     $entity->enforceIsNew();
90     $entity->save();
91     $entity = $this->entityStorage->create([
92       'id' => 4,
93       'user_id' => 2,
94       'field_test_1' => 2,
95       'field_test_2' => 8,
96     ]);
97     $entity->enforceIsNew();
98     $entity->save();
99     $entity = $this->entityStorage->create([
100       'id' => 5,
101       'user_id' => 3,
102       'field_test_1' => 2,
103       'field_test_2' => 2,
104     ]);
105     $entity->enforceIsNew();
106     $entity->save();
107     $entity = $this->entityStorage->create([
108       'id' => 6,
109       'user_id' => 3,
110       'field_test_1' => 3,
111       'field_test_2' => 8,
112     ]);
113     $entity->enforceIsNew();
114     $entity->save();
115
116   }
117
118   /**
119    * Test aggregation support.
120    */
121   public function testAggregation() {
122     // Apply a simple groupby.
123     $this->queryResult = $this->factory->getAggregate('entity_test')
124       ->groupBy('user_id')
125       ->execute();
126
127     $this->assertResults([
128       ['user_id' => 1],
129       ['user_id' => 2],
130       ['user_id' => 3],
131     ]);
132
133     $function_expected = [];
134     $function_expected['count'] = [['id_count' => 6]];
135     $function_expected['min'] = [['id_min' => 1]];
136     $function_expected['max'] = [['id_max' => 6]];
137     $function_expected['sum'] = [['id_sum' => 21]];
138     $function_expected['avg'] = [['id_avg' => (21.0 / 6.0)]];
139
140     // Apply a simple aggregation for different aggregation functions.
141     foreach ($function_expected as $aggregation_function => $expected) {
142       $this->queryResult = $this->factory->getAggregate('entity_test')
143         ->aggregate('id', $aggregation_function)
144         ->execute();
145       $this->assertEqual($this->queryResult, $expected);
146     }
147
148     // Apply aggregation and groupby on the same query.
149     $this->queryResult = $this->factory->getAggregate('entity_test')
150       ->aggregate('id', 'COUNT')
151       ->groupBy('user_id')
152       ->execute();
153     $this->assertResults([
154       ['user_id' => 1, 'id_count' => 1],
155       ['user_id' => 2, 'id_count' => 3],
156       ['user_id' => 3, 'id_count' => 2],
157     ]);
158
159     // Apply aggregation and a condition which matches.
160     $this->queryResult = $this->factory->getAggregate('entity_test')
161       ->aggregate('id', 'COUNT')
162       ->groupBy('id')
163       ->conditionAggregate('id', 'COUNT', 8)
164       ->execute();
165     $this->assertResults([]);
166
167     // Don't call aggregate to test the implicit aggregate call.
168     $this->queryResult = $this->factory->getAggregate('entity_test')
169       ->groupBy('id')
170       ->conditionAggregate('id', 'COUNT', 8)
171       ->execute();
172     $this->assertResults([]);
173
174     // Apply aggregation and a condition which matches.
175     $this->queryResult = $this->factory->getAggregate('entity_test')
176       ->aggregate('id', 'count')
177       ->groupBy('id')
178       ->conditionAggregate('id', 'COUNT', 6)
179       ->execute();
180     $this->assertResults([['id_count' => 6]]);
181
182     // Apply aggregation, a groupby and a condition which matches partially via
183     // the operator '='.
184     $this->queryResult = $this->factory->getAggregate('entity_test')
185       ->aggregate('id', 'count')
186       ->conditionAggregate('id', 'count', 2)
187       ->groupBy('user_id')
188       ->execute();
189     $this->assertResults([['id_count' => 2, 'user_id' => 3]]);
190
191     // Apply aggregation, a groupby and a condition which matches partially via
192     // the operator '>'.
193     $this->queryResult = $this->factory->getAggregate('entity_test')
194       ->aggregate('id', 'count')
195       ->conditionAggregate('id', 'COUNT', 1, '>')
196       ->groupBy('user_id')
197       ->execute();
198     $this->assertResults([
199       ['id_count' => 2, 'user_id' => 3],
200       ['id_count' => 3, 'user_id' => 2],
201     ]);
202
203     // Apply aggregation and a sort. This might not be useful, but have a proper
204     // test coverage.
205     $this->queryResult = $this->factory->getAggregate('entity_test')
206       ->aggregate('id', 'COUNT')
207       ->sortAggregate('id', 'COUNT')
208       ->execute();
209     $this->assertSortedResults([['id_count' => 6]]);
210
211     // Don't call aggregate to test the implicit aggregate call.
212     $this->queryResult = $this->factory->getAggregate('entity_test')
213       ->sortAggregate('id', 'COUNT')
214       ->execute();
215     $this->assertSortedResults([['id_count' => 6]]);
216
217     // Apply aggregation, groupby and a sort descending.
218     $this->queryResult = $this->factory->getAggregate('entity_test')
219       ->aggregate('id', 'COUNT')
220       ->groupBy('user_id')
221       ->sortAggregate('id', 'COUNT', 'DESC')
222       ->execute();
223     $this->assertSortedResults([
224       ['user_id' => 2, 'id_count' => 3],
225       ['user_id' => 3, 'id_count' => 2],
226       ['user_id' => 1, 'id_count' => 1],
227     ]);
228
229     // Apply aggregation, groupby and a sort ascending.
230     $this->queryResult = $this->factory->getAggregate('entity_test')
231       ->aggregate('id', 'COUNT')
232       ->groupBy('user_id')
233       ->sortAggregate('id', 'COUNT', 'ASC')
234       ->execute();
235     $this->assertSortedResults([
236       ['user_id' => 1, 'id_count' => 1],
237       ['user_id' => 3, 'id_count' => 2],
238       ['user_id' => 2, 'id_count' => 3],
239     ]);
240
241     // Apply aggregation, groupby, an aggregation condition and a sort with the
242     // operator '='.
243     $this->queryResult = $this->factory->getAggregate('entity_test')
244       ->aggregate('id', 'COUNT')
245       ->groupBy('user_id')
246       ->sortAggregate('id', 'COUNT')
247       ->conditionAggregate('id', 'COUNT', 2)
248       ->execute();
249     $this->assertSortedResults([['id_count' => 2, 'user_id' => 3]]);
250
251     // Apply aggregation, groupby, an aggregation condition and a sort with the
252     // operator '<' and order ASC.
253     $this->queryResult = $this->factory->getAggregate('entity_test')
254       ->aggregate('id', 'COUNT')
255       ->groupBy('user_id')
256       ->sortAggregate('id', 'COUNT', 'ASC')
257       ->conditionAggregate('id', 'COUNT', 3, '<')
258       ->execute();
259     $this->assertSortedResults([
260       ['id_count' => 1, 'user_id' => 1],
261       ['id_count' => 2, 'user_id' => 3],
262     ]);
263
264     // Apply aggregation, groupby, an aggregation condition and a sort with the
265     // operator '<' and order DESC.
266     $this->queryResult = $this->factory->getAggregate('entity_test')
267       ->aggregate('id', 'COUNT')
268       ->groupBy('user_id')
269       ->sortAggregate('id', 'COUNT', 'DESC')
270       ->conditionAggregate('id', 'COUNT', 3, '<')
271       ->execute();
272     $this->assertSortedResults([
273       ['id_count' => 2, 'user_id' => 3],
274       ['id_count' => 1, 'user_id' => 1],
275     ]);
276
277     // Test aggregation/groupby support for fieldapi fields.
278
279     // Just group by a fieldapi field.
280     $this->queryResult = $this->factory->getAggregate('entity_test')
281       ->groupBy('field_test_1')
282       ->execute();
283     $this->assertResults([
284       ['field_test_1' => 1],
285       ['field_test_1' => 2],
286       ['field_test_1' => 3],
287     ]);
288
289     // Group by a fieldapi field and aggregate a normal property.
290     $this->queryResult = $this->factory->getAggregate('entity_test')
291       ->aggregate('user_id', 'COUNT')
292       ->groupBy('field_test_1')
293       ->execute();
294
295     $this->assertResults([
296       ['field_test_1' => 1, 'user_id_count' => 2],
297       ['field_test_1' => 2, 'user_id_count' => 3],
298       ['field_test_1' => 3, 'user_id_count' => 1],
299     ]);
300
301     // Group by a normal property and aggregate a fieldapi field.
302     $this->queryResult = $this->factory->getAggregate('entity_test')
303       ->aggregate('field_test_1', 'COUNT')
304       ->groupBy('user_id')
305       ->execute();
306
307     $this->assertResults([
308       ['user_id' => 1, 'field_test_1_count' => 1],
309       ['user_id' => 2, 'field_test_1_count' => 3],
310       ['user_id' => 3, 'field_test_1_count' => 2],
311     ]);
312
313     $this->queryResult = $this->factory->getAggregate('entity_test')
314       ->aggregate('field_test_1', 'SUM')
315       ->groupBy('user_id')
316       ->execute();
317     $this->assertResults([
318       ['user_id' => 1, 'field_test_1_sum' => 1],
319       ['user_id' => 2, 'field_test_1_sum' => 5],
320       ['user_id' => 3, 'field_test_1_sum' => 5],
321     ]);
322
323     // Aggregate by two different fieldapi fields.
324     $this->queryResult = $this->factory->getAggregate('entity_test')
325       ->aggregate('field_test_1', 'SUM')
326       ->aggregate('field_test_2', 'SUM')
327       ->groupBy('user_id')
328       ->execute();
329     $this->assertResults([
330       ['user_id' => 1, 'field_test_1_sum' => 1, 'field_test_2_sum' => 2],
331       ['user_id' => 2, 'field_test_1_sum' => 5, 'field_test_2_sum' => 16],
332       ['user_id' => 3, 'field_test_1_sum' => 5, 'field_test_2_sum' => 10],
333     ]);
334
335     // This time aggregate the same field twice.
336     $this->queryResult = $this->factory->getAggregate('entity_test')
337       ->aggregate('field_test_1', 'SUM')
338       ->aggregate('field_test_1', 'COUNT')
339       ->groupBy('user_id')
340       ->execute();
341     $this->assertResults([
342       ['user_id' => 1, 'field_test_1_sum' => 1, 'field_test_1_count' => 1],
343       ['user_id' => 2, 'field_test_1_sum' => 5, 'field_test_1_count' => 3],
344       ['user_id' => 3, 'field_test_1_sum' => 5, 'field_test_1_count' => 2],
345     ]);
346
347     // Group by and aggregate by a fieldapi field.
348     $this->queryResult = $this->factory->getAggregate('entity_test')
349       ->groupBy('field_test_1')
350       ->aggregate('field_test_2', 'COUNT')
351       ->execute();
352     $this->assertResults([
353       ['field_test_1' => 1, 'field_test_2_count' => 2],
354       ['field_test_1' => 2, 'field_test_2_count' => 3],
355       ['field_test_1' => 3, 'field_test_2_count' => 1],
356     ]);
357
358     // Group by and aggregate by a fieldapi field and use multiple aggregate
359     // functions.
360     $this->queryResult = $this->factory->getAggregate('entity_test')
361       ->groupBy('field_test_1')
362       ->aggregate('field_test_2', 'COUNT')
363       ->aggregate('field_test_2', 'SUM')
364       ->execute();
365     $this->assertResults([
366       ['field_test_1' => 1, 'field_test_2_count' => 2, 'field_test_2_sum' => 9],
367       ['field_test_1' => 2, 'field_test_2_count' => 3, 'field_test_2_sum' => 11],
368       ['field_test_1' => 3, 'field_test_2_count' => 1, 'field_test_2_sum' => 8],
369     ]);
370
371     // Apply an aggregate condition for a fieldapi field and group by a simple
372     // property.
373     $this->queryResult = $this->factory->getAggregate('entity_test')
374       ->conditionAggregate('field_test_1', 'COUNT', 3)
375       ->groupBy('user_id')
376       ->execute();
377     $this->assertResults([
378       ['user_id' => 2, 'field_test_1_count' => 3],
379       ['user_id' => 3, 'field_test_1_count' => 2],
380     ]);
381
382     $this->queryResult = $this->factory->getAggregate('entity_test')
383       ->aggregate('field_test_1', 'SUM')
384       ->conditionAggregate('field_test_1', 'COUNT', 2, '>')
385       ->groupBy('user_id')
386       ->execute();
387     $this->assertResults([
388       ['user_id' => 2, 'field_test_1_sum' => 5, 'field_test_1_count' => 3],
389       ['user_id' => 3, 'field_test_1_sum' => 5, 'field_test_1_count' => 2],
390     ]);
391
392     // Apply an aggregate condition for a simple property and a group by a
393     // fieldapi field.
394     $this->queryResult = $this->factory->getAggregate('entity_test')
395       ->conditionAggregate('user_id', 'COUNT', 2)
396       ->groupBy('field_test_1')
397       ->execute();
398     $this->assertResults([
399       ['field_test_1' => 1, 'user_id_count' => 2],
400     ]);
401
402     $this->queryResult = $this->factory->getAggregate('entity_test')
403       ->conditionAggregate('user_id', 'COUNT', 2, '>')
404       ->groupBy('field_test_1')
405       ->execute();
406     $this->assertResults([
407       ['field_test_1' => 1, 'user_id_count' => 2],
408       ['field_test_1' => 2, 'user_id_count' => 3],
409     ]);
410
411     // Apply an aggregate condition and a group by fieldapi fields.
412     $this->queryResult = $this->factory->getAggregate('entity_test')
413       ->groupBy('field_test_1')
414       ->conditionAggregate('field_test_2', 'COUNT', 2)
415       ->execute();
416     $this->assertResults([
417       ['field_test_1' => 1, 'field_test_2_count' => 2],
418     ]);
419     $this->queryResult = $this->factory->getAggregate('entity_test')
420       ->groupBy('field_test_1')
421       ->conditionAggregate('field_test_2', 'COUNT', 2, '>')
422       ->execute();
423     $this->assertResults([
424       ['field_test_1' => 1, 'field_test_2_count' => 2],
425       ['field_test_1' => 2, 'field_test_2_count' => 3],
426     ]);
427
428     // Apply an aggregate condition and a group by fieldapi fields with multiple
429     // conditions via AND.
430     $this->queryResult = $this->factory->getAggregate('entity_test')
431       ->groupBy('field_test_1')
432       ->conditionAggregate('field_test_2', 'COUNT', 2)
433       ->conditionAggregate('field_test_2', 'SUM', 8)
434       ->execute();
435     $this->assertResults([]);
436
437     // Apply an aggregate condition and a group by fieldapi fields with multiple
438     // conditions via OR.
439     $this->queryResult = $this->factory->getAggregate('entity_test', 'OR')
440       ->groupBy('field_test_1')
441       ->conditionAggregate('field_test_2', 'COUNT', 2)
442       ->conditionAggregate('field_test_2', 'SUM', 8)
443       ->execute();
444     $this->assertResults([
445       ['field_test_1' => 1, 'field_test_2_count' => 2, 'field_test_2_sum' => 9],
446       ['field_test_1' => 3, 'field_test_2_count' => 1, 'field_test_2_sum' => 8],
447     ]);
448
449     // Group by a normal property and aggregate a fieldapi field and sort by the
450     // groupby field.
451     $this->queryResult = $this->factory->getAggregate('entity_test')
452       ->aggregate('field_test_1', 'COUNT')
453       ->groupBy('user_id')
454       ->sort('user_id', 'DESC')
455       ->execute();
456     $this->assertSortedResults([
457       ['user_id' => 3, 'field_test_1_count' => 2],
458       ['user_id' => 2, 'field_test_1_count' => 3],
459       ['user_id' => 1, 'field_test_1_count' => 1],
460     ]);
461
462     $this->queryResult = $this->factory->getAggregate('entity_test')
463       ->aggregate('field_test_1', 'COUNT')
464       ->groupBy('user_id')
465       ->sort('user_id', 'ASC')
466       ->execute();
467     $this->assertSortedResults([
468       ['user_id' => 1, 'field_test_1_count' => 1],
469       ['user_id' => 2, 'field_test_1_count' => 3],
470       ['user_id' => 3, 'field_test_1_count' => 2],
471     ]);
472
473     $this->queryResult = $this->factory->getAggregate('entity_test')
474       ->conditionAggregate('field_test_1', 'COUNT', 2, '>')
475       ->groupBy('user_id')
476       ->sort('user_id', 'ASC')
477       ->execute();
478     $this->assertSortedResults([
479       ['user_id' => 2, 'field_test_1_count' => 3],
480       ['user_id' => 3, 'field_test_1_count' => 2],
481     ]);
482
483     // Group by a normal property, aggregate a fieldapi field, and sort by the
484     // aggregated field.
485     $this->queryResult = $this->factory->getAggregate('entity_test')
486       ->sortAggregate('field_test_1', 'COUNT', 'DESC')
487       ->groupBy('user_id')
488       ->execute();
489     $this->assertSortedResults([
490       ['user_id' => 2, 'field_test_1_count' => 3],
491       ['user_id' => 3, 'field_test_1_count' => 2],
492       ['user_id' => 1, 'field_test_1_count' => 1],
493     ]);
494
495     $this->queryResult = $this->factory->getAggregate('entity_test')
496       ->sortAggregate('field_test_1', 'COUNT', 'ASC')
497       ->groupBy('user_id')
498       ->execute();
499     $this->assertSortedResults([
500       ['user_id' => 1, 'field_test_1_count' => 1],
501       ['user_id' => 3, 'field_test_1_count' => 2],
502       ['user_id' => 2, 'field_test_1_count' => 3],
503     ]);
504
505     // Group by and aggregate by fieldapi field, and sort by the groupby field.
506     $this->queryResult = $this->factory->getAggregate('entity_test')
507       ->groupBy('field_test_1')
508       ->aggregate('field_test_2', 'COUNT')
509       ->sort('field_test_1', 'ASC')
510       ->execute();
511     $this->assertSortedResults([
512       ['field_test_1' => 1, 'field_test_2_count' => 2],
513       ['field_test_1' => 2, 'field_test_2_count' => 3],
514       ['field_test_1' => 3, 'field_test_2_count' => 1],
515     ]);
516
517     $this->queryResult = $this->factory->getAggregate('entity_test')
518       ->groupBy('field_test_1')
519       ->aggregate('field_test_2', 'COUNT')
520       ->sort('field_test_1', 'DESC')
521       ->execute();
522     $this->assertSortedResults([
523       ['field_test_1' => 3, 'field_test_2_count' => 1],
524       ['field_test_1' => 2, 'field_test_2_count' => 3],
525       ['field_test_1' => 1, 'field_test_2_count' => 2],
526     ]);
527
528     // Groupby and aggregate by fieldapi field, and sort by the aggregated
529     // field.
530     $this->queryResult = $this->factory->getAggregate('entity_test')
531       ->groupBy('field_test_1')
532       ->sortAggregate('field_test_2', 'COUNT', 'DESC')
533       ->execute();
534     $this->assertSortedResults([
535       ['field_test_1' => 2, 'field_test_2_count' => 3],
536       ['field_test_1' => 1, 'field_test_2_count' => 2],
537       ['field_test_1' => 3, 'field_test_2_count' => 1],
538     ]);
539
540     $this->queryResult = $this->factory->getAggregate('entity_test')
541       ->groupBy('field_test_1')
542       ->sortAggregate('field_test_2', 'COUNT', 'ASC')
543       ->execute();
544     $this->assertSortedResults([
545       ['field_test_1' => 3, 'field_test_2_count' => 1],
546       ['field_test_1' => 1, 'field_test_2_count' => 2],
547       ['field_test_1' => 2, 'field_test_2_count' => 3],
548     ]);
549
550   }
551
552   /**
553    * Asserts the results as expected regardless of order between and in rows.
554    *
555    * @param array $expected
556    *   An array of the expected results.
557    */
558   protected function assertResults($expected, $sorted = FALSE) {
559     $found = TRUE;
560     $expected_keys = array_keys($expected);
561     foreach ($this->queryResult as $key => $row) {
562       $keys = $sorted ? [$key] : $expected_keys;
563       foreach ($keys as $key) {
564         $expected_row = $expected[$key];
565         if (!array_diff_assoc($row, $expected_row) && !array_diff_assoc($expected_row, $row)) {
566           continue 2;
567         }
568       }
569       $found = FALSE;
570       break;
571     }
572     return $this->assertTrue($found, strtr('!expected expected, !found found', ['!expected' => print_r($expected, TRUE), '!found' => print_r($this->queryResult, TRUE)]));
573   }
574
575   /**
576    * Asserts the results as expected regardless of order in rows.
577    *
578    * @param array $expected
579    *   An array of the expected results.
580    */
581   protected function assertSortedResults($expected) {
582     return $this->assertResults($expected, TRUE);
583   }
584
585 }