Chris@0: installEntitySchema('user'); Chris@0: $this->installEntitySchema('entity_test'); Chris@0: $this->installEntitySchema('entity_test_mul'); Chris@0: Chris@0: $this->storage = $this->container->get('entity.manager')->getStorage('entity_test'); Chris@0: Chris@0: ConfigurableLanguage::createFromLangcode('it')->save(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests aggregate count feature. Chris@0: */ Chris@0: public function testAggregateCount() { Chris@0: $this->setupTestEntities(); Chris@0: Chris@0: $view = Views::getView('test_aggregate_count'); Chris@0: $this->executeView($view); Chris@0: Chris@0: $this->assertEqual(count($view->result), 2, 'Make sure the count of items is right.'); Chris@0: Chris@0: $types = []; Chris@0: foreach ($view->result as $item) { Chris@0: // num_records is a alias for id. Chris@0: $types[$item->entity_test_name] = $item->num_records; Chris@0: } Chris@0: Chris@0: $this->assertEqual($types['name1'], 4, 'Groupby the name: name1 returned the expected amount of results.'); Chris@0: $this->assertEqual($types['name2'], 3, 'Groupby the name: name2 returned the expected amount of results.'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Provides a test helper which runs a view with some aggregation function. Chris@0: * Chris@0: * @param string|null $aggregation_function Chris@0: * Which aggregation function should be used, for example sum or count. If Chris@0: * NULL is passed the aggregation will be tested with no function. Chris@0: * @param array $values Chris@0: * The expected views result. Chris@0: */ Chris@0: public function groupByTestHelper($aggregation_function, $values) { Chris@0: $this->setupTestEntities(); Chris@0: Chris@0: $view = Views::getView('test_group_by_count'); Chris@0: $view->setDisplay(); Chris@0: // There is no need for a function in order to have aggregation. Chris@0: if (empty($aggregation_function)) { Chris@0: // The test table has 2 fields ('id' and 'name'). We'll remove 'id' Chris@0: // because it's unique and will test aggregation on 'name'. Chris@0: unset($view->displayHandlers->get('default')->options['fields']['id']); Chris@0: } Chris@0: else { Chris@0: $view->displayHandlers->get('default')->options['fields']['id']['group_type'] = $aggregation_function; Chris@0: } Chris@0: Chris@0: $this->executeView($view); Chris@0: Chris@0: $this->assertEqual(count($view->result), 2, 'Make sure the count of items is right.'); Chris@0: // Group by name to identify the right count. Chris@0: $results = []; Chris@0: foreach ($view->result as $item) { Chris@0: $results[$item->entity_test_name] = $item->id; Chris@0: } Chris@0: $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: $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: } Chris@0: Chris@0: /** Chris@0: * Helper method that creates some test entities. Chris@0: */ Chris@0: protected function setupTestEntities() { Chris@0: // Create 4 entities with name1 and 3 entities with name2. Chris@0: $entity_1 = [ Chris@0: 'name' => 'name1', Chris@0: ]; Chris@0: Chris@0: $this->storage->create($entity_1)->save(); Chris@0: $this->storage->create($entity_1)->save(); Chris@0: $this->storage->create($entity_1)->save(); Chris@0: $this->storage->create($entity_1)->save(); Chris@0: Chris@0: $entity_2 = [ Chris@0: 'name' => 'name2', Chris@0: ]; Chris@0: $this->storage->create($entity_2)->save(); Chris@0: $this->storage->create($entity_2)->save(); Chris@0: $this->storage->create($entity_2)->save(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests the count aggregation function. Chris@0: */ Chris@0: public function testGroupByCount() { Chris@0: $this->groupByTestHelper('count', [4, 3]); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests the sum aggregation function. Chris@0: */ Chris@0: public function testGroupBySum() { Chris@0: $this->groupByTestHelper('sum', [10, 18]); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests the average aggregation function. Chris@0: */ Chris@0: public function testGroupByAverage() { Chris@0: $this->groupByTestHelper('avg', [2.5, 6]); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests the min aggregation function. Chris@0: */ Chris@0: public function testGroupByMin() { Chris@0: $this->groupByTestHelper('min', [1, 5]); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests the max aggregation function. Chris@0: */ Chris@0: public function testGroupByMax() { Chris@0: $this->groupByTestHelper('max', [4, 7]); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests aggregation with no specific function. Chris@0: */ Chris@0: public function testGroupByNone() { Chris@0: $this->groupByTestHelper(NULL, [1, 5]); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests groupby with filters. Chris@0: */ Chris@0: public function testGroupByCountOnlyFilters() { Chris@0: // Check if GROUP BY and HAVING are included when a view Chris@0: // doesn't display SUM, COUNT, MAX, etc. functions in SELECT statement. Chris@0: Chris@0: for ($x = 0; $x < 10; $x++) { Chris@0: $this->storage->create(['name' => 'name1'])->save(); Chris@0: } Chris@0: Chris@0: $view = Views::getView('test_group_by_in_filters'); Chris@0: $this->executeView($view); Chris@0: Chris@0: $this->assertTrue(strpos($view->build_info['query'], 'GROUP BY'), 'Make sure that GROUP BY is in the query'); Chris@0: $this->assertTrue(strpos($view->build_info['query'], 'HAVING'), 'Make sure that HAVING is in the query'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests grouping on base field. Chris@0: */ Chris@0: public function testGroupByBaseField() { Chris@0: $this->setupTestEntities(); Chris@0: Chris@0: $view = Views::getView('test_group_by_count'); Chris@0: $view->setDisplay(); Chris@0: // This tests that the GROUP BY portion of the query is properly formatted Chris@0: // to include the base table to avoid ambiguous field errors. Chris@0: $view->displayHandlers->get('default')->options['fields']['name']['group_type'] = 'min'; Chris@0: unset($view->displayHandlers->get('default')->options['fields']['id']['group_type']); Chris@0: $this->executeView($view); Chris@0: $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: } Chris@0: Chris@0: /** Chris@0: * Tests grouping a field with cardinality > 1. Chris@0: */ Chris@0: public function testGroupByFieldWithCardinality() { Chris@0: $field_storage = FieldStorageConfig::create([ Chris@0: 'type' => 'integer', Chris@0: 'field_name' => 'field_test', Chris@0: 'cardinality' => 4, Chris@0: 'entity_type' => 'entity_test_mul', Chris@0: ]); Chris@0: $field_storage->save(); Chris@0: $field = FieldConfig::create([ Chris@0: 'field_name' => 'field_test', Chris@0: 'entity_type' => 'entity_test_mul', Chris@0: 'bundle' => 'entity_test_mul', Chris@0: ]); Chris@0: $field->save(); Chris@0: Chris@0: $entities = []; Chris@0: $entity = EntityTestMul::create([ Chris@0: 'field_test' => [1, 1, 1], Chris@0: ]); Chris@0: $entity->save(); Chris@0: $entities[] = $entity; Chris@0: Chris@0: $entity = EntityTestMul::create([ Chris@0: 'field_test' => [2, 2, 2], Chris@0: ]); Chris@0: $entity->save(); Chris@0: $entities[] = $entity; Chris@0: Chris@0: $entity = EntityTestMul::create([ Chris@0: 'field_test' => [2, 2, 2], Chris@0: ]); Chris@0: $entity->save(); Chris@0: $entities[] = $entity; Chris@0: Chris@0: $view = Views::getView('test_group_by_count_multicardinality'); Chris@0: $this->executeView($view); Chris@0: $this->assertEqual(2, count($view->result)); Chris@0: Chris@0: $this->assertEqual('3', $view->getStyle()->getField(0, 'id')); Chris@0: $this->assertEqual('1', $view->getStyle()->getField(0, 'field_test')); Chris@0: $this->assertEqual('6', $view->getStyle()->getField(1, 'id')); Chris@0: $this->assertEqual('2', $view->getStyle()->getField(1, 'field_test')); Chris@0: Chris@0: $entities[2]->field_test[0]->value = 3; Chris@0: $entities[2]->field_test[1]->value = 4; Chris@0: $entities[2]->field_test[2]->value = 5; Chris@0: $entities[2]->save(); Chris@0: Chris@0: $view = Views::getView('test_group_by_count_multicardinality'); Chris@0: $this->executeView($view); Chris@0: $this->assertEqual(5, count($view->result)); Chris@0: Chris@0: $this->assertEqual('3', $view->getStyle()->getField(0, 'id')); Chris@0: $this->assertEqual('1', $view->getStyle()->getField(0, 'field_test')); Chris@0: $this->assertEqual('3', $view->getStyle()->getField(1, 'id')); Chris@0: $this->assertEqual('2', $view->getStyle()->getField(1, 'field_test')); Chris@0: $this->assertEqual('1', $view->getStyle()->getField(2, 'id')); Chris@0: $this->assertEqual('3', $view->getStyle()->getField(2, 'field_test')); Chris@0: $this->assertEqual('1', $view->getStyle()->getField(3, 'id')); Chris@0: $this->assertEqual('4', $view->getStyle()->getField(3, 'field_test')); Chris@0: $this->assertEqual('1', $view->getStyle()->getField(4, 'id')); Chris@0: $this->assertEqual('5', $view->getStyle()->getField(4, 'field_test')); Chris@0: Chris@0: // Check that translated values are correctly retrieved and are not grouped Chris@0: // into the original entity. Chris@0: $translation = $entity->addTranslation('it'); Chris@0: $translation->field_test = [6, 6, 6]; Chris@0: $translation->save(); Chris@0: Chris@0: $view = Views::getView('test_group_by_count_multicardinality'); Chris@0: $this->executeView($view); Chris@0: Chris@0: $this->assertEqual(6, count($view->result)); Chris@0: $this->assertEqual('3', $view->getStyle()->getField(5, 'id')); Chris@0: $this->assertEqual('6', $view->getStyle()->getField(5, 'field_test')); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests groupby with a field not existing on some bundle. Chris@0: */ Chris@0: public function testGroupByWithFieldsNotExistingOnBundle() { Chris@0: $field_storage = FieldStorageConfig::create([ Chris@0: 'type' => 'integer', Chris@0: 'field_name' => 'field_test', Chris@0: 'cardinality' => 4, Chris@0: 'entity_type' => 'entity_test_mul', Chris@0: ]); Chris@0: $field_storage->save(); Chris@0: $field = FieldConfig::create([ Chris@0: 'field_name' => 'field_test', Chris@0: 'entity_type' => 'entity_test_mul', Chris@0: 'bundle' => 'entity_test_mul', Chris@0: ]); Chris@0: $field->save(); Chris@0: Chris@0: $entities = []; Chris@0: $entity = EntityTestMul::create([ Chris@0: 'field_test' => [1], Chris@0: 'type' => 'entity_test_mul', Chris@0: ]); Chris@0: $entity->save(); Chris@0: $entities[] = $entity; Chris@0: Chris@0: $entity = EntityTestMul::create([ Chris@0: 'type' => 'entity_test_mul2', Chris@0: ]); Chris@0: $entity->save(); Chris@0: $entities[] = $entity; Chris@0: Chris@0: $view = Views::getView('test_group_by_field_not_within_bundle'); Chris@0: $this->executeView($view); Chris@0: Chris@0: $this->assertEqual(2, count($view->result)); Chris@0: // The first result is coming from entity_test_mul2, so no field could be Chris@0: // rendered. Chris@0: $this->assertEqual('', $view->getStyle()->getField(0, 'field_test')); Chris@0: // The second result is coming from entity_test_mul, so its field value Chris@0: // could be rendered. Chris@0: $this->assertEqual('1', $view->getStyle()->getField(1, 'field_test')); Chris@0: } Chris@0: Chris@0: }