annotate core/modules/views/tests/src/Kernel/QueryGroupByTest.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 129ea1e6d783
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\Tests\views\Kernel;
Chris@0 4
Chris@0 5 use Drupal\entity_test\Entity\EntityTestMul;
Chris@0 6 use Drupal\field\Entity\FieldConfig;
Chris@0 7 use Drupal\field\Entity\FieldStorageConfig;
Chris@0 8 use Drupal\language\Entity\ConfigurableLanguage;
Chris@0 9 use Drupal\views\Views;
Chris@0 10
Chris@0 11 /**
Chris@0 12 * Tests aggregate functionality of views, for example count.
Chris@0 13 *
Chris@0 14 * @group views
Chris@0 15 */
Chris@0 16 class QueryGroupByTest extends ViewsKernelTestBase {
Chris@0 17
Chris@0 18 /**
Chris@0 19 * Views used by this test.
Chris@0 20 *
Chris@0 21 * @var array
Chris@0 22 */
Chris@0 23 public static $testViews = ['test_group_by_in_filters', 'test_aggregate_count', 'test_group_by_count', 'test_group_by_count_multicardinality', 'test_group_by_field_not_within_bundle'];
Chris@0 24
Chris@0 25 /**
Chris@0 26 * Modules to enable.
Chris@0 27 *
Chris@0 28 * @var array
Chris@0 29 */
Chris@0 30 public static $modules = ['entity_test', 'system', 'field', 'user', 'language'];
Chris@0 31
Chris@0 32 /**
Chris@0 33 * The storage for the test entity type.
Chris@0 34 *
Chris@0 35 * @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage
Chris@0 36 */
Chris@0 37 public $storage;
Chris@0 38
Chris@0 39 /**
Chris@0 40 * {@inheritdoc}
Chris@0 41 */
Chris@0 42 protected function setUp($import_test_views = TRUE) {
Chris@0 43 parent::setUp();
Chris@0 44
Chris@0 45 $this->installEntitySchema('user');
Chris@0 46 $this->installEntitySchema('entity_test');
Chris@0 47 $this->installEntitySchema('entity_test_mul');
Chris@0 48
Chris@0 49 $this->storage = $this->container->get('entity.manager')->getStorage('entity_test');
Chris@0 50
Chris@0 51 ConfigurableLanguage::createFromLangcode('it')->save();
Chris@0 52 }
Chris@0 53
Chris@0 54
Chris@0 55 /**
Chris@0 56 * Tests aggregate count feature.
Chris@0 57 */
Chris@0 58 public function testAggregateCount() {
Chris@0 59 $this->setupTestEntities();
Chris@0 60
Chris@0 61 $view = Views::getView('test_aggregate_count');
Chris@0 62 $this->executeView($view);
Chris@0 63
Chris@0 64 $this->assertEqual(count($view->result), 2, 'Make sure the count of items is right.');
Chris@0 65
Chris@0 66 $types = [];
Chris@0 67 foreach ($view->result as $item) {
Chris@0 68 // num_records is a alias for id.
Chris@0 69 $types[$item->entity_test_name] = $item->num_records;
Chris@0 70 }
Chris@0 71
Chris@0 72 $this->assertEqual($types['name1'], 4, 'Groupby the name: name1 returned the expected amount of results.');
Chris@0 73 $this->assertEqual($types['name2'], 3, 'Groupby the name: name2 returned the expected amount of results.');
Chris@0 74 }
Chris@0 75
Chris@0 76 /**
Chris@0 77 * Provides a test helper which runs a view with some aggregation function.
Chris@0 78 *
Chris@0 79 * @param string|null $aggregation_function
Chris@0 80 * Which aggregation function should be used, for example sum or count. If
Chris@0 81 * NULL is passed the aggregation will be tested with no function.
Chris@0 82 * @param array $values
Chris@0 83 * The expected views result.
Chris@0 84 */
Chris@0 85 public function groupByTestHelper($aggregation_function, $values) {
Chris@0 86 $this->setupTestEntities();
Chris@0 87
Chris@0 88 $view = Views::getView('test_group_by_count');
Chris@0 89 $view->setDisplay();
Chris@0 90 // There is no need for a function in order to have aggregation.
Chris@0 91 if (empty($aggregation_function)) {
Chris@0 92 // The test table has 2 fields ('id' and 'name'). We'll remove 'id'
Chris@0 93 // because it's unique and will test aggregation on 'name'.
Chris@0 94 unset($view->displayHandlers->get('default')->options['fields']['id']);
Chris@0 95 }
Chris@0 96 else {
Chris@0 97 $view->displayHandlers->get('default')->options['fields']['id']['group_type'] = $aggregation_function;
Chris@0 98 }
Chris@0 99
Chris@0 100 $this->executeView($view);
Chris@0 101
Chris@0 102 $this->assertEqual(count($view->result), 2, 'Make sure the count of items is right.');
Chris@0 103 // Group by name to identify the right count.
Chris@0 104 $results = [];
Chris@0 105 foreach ($view->result as $item) {
Chris@0 106 $results[$item->entity_test_name] = $item->id;
Chris@0 107 }
Chris@0 108 $this->assertEqual($results['name1'], $values[0], format_string('Aggregation with @aggregation_function and groupby name: name1 returned the expected amount of results', ['@aggregation_function' => $aggregation_function]));
Chris@0 109 $this->assertEqual($results['name2'], $values[1], format_string('Aggregation with @aggregation_function and groupby name: name2 returned the expected amount of results', ['@aggregation_function' => $aggregation_function]));
Chris@0 110 }
Chris@0 111
Chris@0 112 /**
Chris@0 113 * Helper method that creates some test entities.
Chris@0 114 */
Chris@0 115 protected function setupTestEntities() {
Chris@0 116 // Create 4 entities with name1 and 3 entities with name2.
Chris@0 117 $entity_1 = [
Chris@0 118 'name' => 'name1',
Chris@0 119 ];
Chris@0 120
Chris@0 121 $this->storage->create($entity_1)->save();
Chris@0 122 $this->storage->create($entity_1)->save();
Chris@0 123 $this->storage->create($entity_1)->save();
Chris@0 124 $this->storage->create($entity_1)->save();
Chris@0 125
Chris@0 126 $entity_2 = [
Chris@0 127 'name' => 'name2',
Chris@0 128 ];
Chris@0 129 $this->storage->create($entity_2)->save();
Chris@0 130 $this->storage->create($entity_2)->save();
Chris@0 131 $this->storage->create($entity_2)->save();
Chris@0 132 }
Chris@0 133
Chris@0 134 /**
Chris@0 135 * Tests the count aggregation function.
Chris@0 136 */
Chris@0 137 public function testGroupByCount() {
Chris@0 138 $this->groupByTestHelper('count', [4, 3]);
Chris@0 139 }
Chris@0 140
Chris@0 141 /**
Chris@0 142 * Tests the sum aggregation function.
Chris@0 143 */
Chris@0 144 public function testGroupBySum() {
Chris@0 145 $this->groupByTestHelper('sum', [10, 18]);
Chris@0 146 }
Chris@0 147
Chris@0 148 /**
Chris@0 149 * Tests the average aggregation function.
Chris@0 150 */
Chris@0 151 public function testGroupByAverage() {
Chris@0 152 $this->groupByTestHelper('avg', [2.5, 6]);
Chris@0 153 }
Chris@0 154
Chris@0 155 /**
Chris@0 156 * Tests the min aggregation function.
Chris@0 157 */
Chris@0 158 public function testGroupByMin() {
Chris@0 159 $this->groupByTestHelper('min', [1, 5]);
Chris@0 160 }
Chris@0 161
Chris@0 162 /**
Chris@0 163 * Tests the max aggregation function.
Chris@0 164 */
Chris@0 165 public function testGroupByMax() {
Chris@0 166 $this->groupByTestHelper('max', [4, 7]);
Chris@0 167 }
Chris@0 168
Chris@0 169 /**
Chris@0 170 * Tests aggregation with no specific function.
Chris@0 171 */
Chris@0 172 public function testGroupByNone() {
Chris@0 173 $this->groupByTestHelper(NULL, [1, 5]);
Chris@0 174 }
Chris@0 175
Chris@0 176 /**
Chris@0 177 * Tests groupby with filters.
Chris@0 178 */
Chris@0 179 public function testGroupByCountOnlyFilters() {
Chris@0 180 // Check if GROUP BY and HAVING are included when a view
Chris@0 181 // doesn't display SUM, COUNT, MAX, etc. functions in SELECT statement.
Chris@0 182
Chris@0 183 for ($x = 0; $x < 10; $x++) {
Chris@0 184 $this->storage->create(['name' => 'name1'])->save();
Chris@0 185 }
Chris@0 186
Chris@0 187 $view = Views::getView('test_group_by_in_filters');
Chris@0 188 $this->executeView($view);
Chris@0 189
Chris@0 190 $this->assertTrue(strpos($view->build_info['query'], 'GROUP BY'), 'Make sure that GROUP BY is in the query');
Chris@0 191 $this->assertTrue(strpos($view->build_info['query'], 'HAVING'), 'Make sure that HAVING is in the query');
Chris@0 192 }
Chris@0 193
Chris@0 194 /**
Chris@0 195 * Tests grouping on base field.
Chris@0 196 */
Chris@0 197 public function testGroupByBaseField() {
Chris@0 198 $this->setupTestEntities();
Chris@0 199
Chris@0 200 $view = Views::getView('test_group_by_count');
Chris@0 201 $view->setDisplay();
Chris@0 202 // This tests that the GROUP BY portion of the query is properly formatted
Chris@0 203 // to include the base table to avoid ambiguous field errors.
Chris@0 204 $view->displayHandlers->get('default')->options['fields']['name']['group_type'] = 'min';
Chris@0 205 unset($view->displayHandlers->get('default')->options['fields']['id']['group_type']);
Chris@0 206 $this->executeView($view);
Chris@0 207 $this->assertTrue(strpos($view->build_info['query'], 'GROUP BY entity_test.id'), 'GROUP BY field includes the base table name when grouping on the base field.');
Chris@0 208 }
Chris@0 209
Chris@0 210 /**
Chris@0 211 * Tests grouping a field with cardinality > 1.
Chris@0 212 */
Chris@0 213 public function testGroupByFieldWithCardinality() {
Chris@0 214 $field_storage = FieldStorageConfig::create([
Chris@0 215 'type' => 'integer',
Chris@0 216 'field_name' => 'field_test',
Chris@0 217 'cardinality' => 4,
Chris@0 218 'entity_type' => 'entity_test_mul',
Chris@0 219 ]);
Chris@0 220 $field_storage->save();
Chris@0 221 $field = FieldConfig::create([
Chris@0 222 'field_name' => 'field_test',
Chris@0 223 'entity_type' => 'entity_test_mul',
Chris@0 224 'bundle' => 'entity_test_mul',
Chris@0 225 ]);
Chris@0 226 $field->save();
Chris@0 227
Chris@0 228 $entities = [];
Chris@0 229 $entity = EntityTestMul::create([
Chris@0 230 'field_test' => [1, 1, 1],
Chris@0 231 ]);
Chris@0 232 $entity->save();
Chris@0 233 $entities[] = $entity;
Chris@0 234
Chris@0 235 $entity = EntityTestMul::create([
Chris@0 236 'field_test' => [2, 2, 2],
Chris@0 237 ]);
Chris@0 238 $entity->save();
Chris@0 239 $entities[] = $entity;
Chris@0 240
Chris@0 241 $entity = EntityTestMul::create([
Chris@0 242 'field_test' => [2, 2, 2],
Chris@0 243 ]);
Chris@0 244 $entity->save();
Chris@0 245 $entities[] = $entity;
Chris@0 246
Chris@0 247 $view = Views::getView('test_group_by_count_multicardinality');
Chris@0 248 $this->executeView($view);
Chris@0 249 $this->assertEqual(2, count($view->result));
Chris@0 250
Chris@0 251 $this->assertEqual('3', $view->getStyle()->getField(0, 'id'));
Chris@0 252 $this->assertEqual('1', $view->getStyle()->getField(0, 'field_test'));
Chris@0 253 $this->assertEqual('6', $view->getStyle()->getField(1, 'id'));
Chris@0 254 $this->assertEqual('2', $view->getStyle()->getField(1, 'field_test'));
Chris@0 255
Chris@0 256 $entities[2]->field_test[0]->value = 3;
Chris@0 257 $entities[2]->field_test[1]->value = 4;
Chris@0 258 $entities[2]->field_test[2]->value = 5;
Chris@0 259 $entities[2]->save();
Chris@0 260
Chris@0 261 $view = Views::getView('test_group_by_count_multicardinality');
Chris@0 262 $this->executeView($view);
Chris@0 263 $this->assertEqual(5, count($view->result));
Chris@0 264
Chris@0 265 $this->assertEqual('3', $view->getStyle()->getField(0, 'id'));
Chris@0 266 $this->assertEqual('1', $view->getStyle()->getField(0, 'field_test'));
Chris@0 267 $this->assertEqual('3', $view->getStyle()->getField(1, 'id'));
Chris@0 268 $this->assertEqual('2', $view->getStyle()->getField(1, 'field_test'));
Chris@0 269 $this->assertEqual('1', $view->getStyle()->getField(2, 'id'));
Chris@0 270 $this->assertEqual('3', $view->getStyle()->getField(2, 'field_test'));
Chris@0 271 $this->assertEqual('1', $view->getStyle()->getField(3, 'id'));
Chris@0 272 $this->assertEqual('4', $view->getStyle()->getField(3, 'field_test'));
Chris@0 273 $this->assertEqual('1', $view->getStyle()->getField(4, 'id'));
Chris@0 274 $this->assertEqual('5', $view->getStyle()->getField(4, 'field_test'));
Chris@0 275
Chris@0 276 // Check that translated values are correctly retrieved and are not grouped
Chris@0 277 // into the original entity.
Chris@0 278 $translation = $entity->addTranslation('it');
Chris@0 279 $translation->field_test = [6, 6, 6];
Chris@0 280 $translation->save();
Chris@0 281
Chris@0 282 $view = Views::getView('test_group_by_count_multicardinality');
Chris@0 283 $this->executeView($view);
Chris@0 284
Chris@0 285 $this->assertEqual(6, count($view->result));
Chris@0 286 $this->assertEqual('3', $view->getStyle()->getField(5, 'id'));
Chris@0 287 $this->assertEqual('6', $view->getStyle()->getField(5, 'field_test'));
Chris@0 288 }
Chris@0 289
Chris@0 290 /**
Chris@0 291 * Tests groupby with a field not existing on some bundle.
Chris@0 292 */
Chris@0 293 public function testGroupByWithFieldsNotExistingOnBundle() {
Chris@0 294 $field_storage = FieldStorageConfig::create([
Chris@0 295 'type' => 'integer',
Chris@0 296 'field_name' => 'field_test',
Chris@0 297 'cardinality' => 4,
Chris@0 298 'entity_type' => 'entity_test_mul',
Chris@0 299 ]);
Chris@0 300 $field_storage->save();
Chris@0 301 $field = FieldConfig::create([
Chris@0 302 'field_name' => 'field_test',
Chris@0 303 'entity_type' => 'entity_test_mul',
Chris@0 304 'bundle' => 'entity_test_mul',
Chris@0 305 ]);
Chris@0 306 $field->save();
Chris@0 307
Chris@0 308 $entities = [];
Chris@0 309 $entity = EntityTestMul::create([
Chris@0 310 'field_test' => [1],
Chris@0 311 'type' => 'entity_test_mul',
Chris@0 312 ]);
Chris@0 313 $entity->save();
Chris@0 314 $entities[] = $entity;
Chris@0 315
Chris@0 316 $entity = EntityTestMul::create([
Chris@0 317 'type' => 'entity_test_mul2',
Chris@0 318 ]);
Chris@0 319 $entity->save();
Chris@0 320 $entities[] = $entity;
Chris@0 321
Chris@0 322 $view = Views::getView('test_group_by_field_not_within_bundle');
Chris@0 323 $this->executeView($view);
Chris@0 324
Chris@0 325 $this->assertEqual(2, count($view->result));
Chris@0 326 // The first result is coming from entity_test_mul2, so no field could be
Chris@0 327 // rendered.
Chris@0 328 $this->assertEqual('', $view->getStyle()->getField(0, 'field_test'));
Chris@0 329 // The second result is coming from entity_test_mul, so its field value
Chris@0 330 // could be rendered.
Chris@0 331 $this->assertEqual('1', $view->getStyle()->getField(1, 'field_test'));
Chris@0 332 }
Chris@0 333
Chris@0 334 }