1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066 |
- <?php
- namespace Drupal\KernelTests\Core\Entity;
- use Drupal\Component\Utility\Unicode;
- use Drupal\entity_test\Entity\EntityTest;
- use Drupal\entity_test\Entity\EntityTestMulRev;
- use Drupal\field\Entity\FieldConfig;
- use Drupal\field\Entity\FieldStorageConfig;
- use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
- use Drupal\language\Entity\ConfigurableLanguage;
- use Drupal\taxonomy\Entity\Term;
- use Drupal\taxonomy\Entity\Vocabulary;
- use Symfony\Component\HttpFoundation\Request;
- /**
- * Tests Entity Query functionality.
- *
- * @group Entity
- */
- class EntityQueryTest extends EntityKernelTestBase {
- use EntityReferenceTestTrait;
- /**
- * Modules to enable.
- *
- * @var array
- */
- public static $modules = ['field_test', 'language'];
- /**
- * @var array
- */
- protected $queryResults;
- /**
- * @var \Drupal\Core\Entity\Query\QueryFactory
- */
- protected $factory;
- /**
- * A list of bundle machine names created for this test.
- *
- * @var string[]
- */
- protected $bundles;
- /**
- * Field name for the greetings field.
- *
- * @var string
- */
- public $greetings;
- /**
- * Field name for the figures field.
- *
- * @var string
- */
- public $figures;
- protected function setUp() {
- parent::setUp();
- $this->installEntitySchema('entity_test_mulrev');
- $this->installConfig(['language']);
- $figures = Unicode::strtolower($this->randomMachineName());
- $greetings = Unicode::strtolower($this->randomMachineName());
- foreach ([$figures => 'shape', $greetings => 'text'] as $field_name => $field_type) {
- $field_storage = FieldStorageConfig::create([
- 'field_name' => $field_name,
- 'entity_type' => 'entity_test_mulrev',
- 'type' => $field_type,
- 'cardinality' => 2,
- ]);
- $field_storage->save();
- $field_storages[] = $field_storage;
- }
- $bundles = [];
- for ($i = 0; $i < 2; $i++) {
- // For the sake of tablesort, make sure the second bundle is higher than
- // the first one. Beware: MySQL is not case sensitive.
- do {
- $bundle = $this->randomMachineName();
- } while ($bundles && strtolower($bundles[0]) >= strtolower($bundle));
- entity_test_create_bundle($bundle);
- foreach ($field_storages as $field_storage) {
- FieldConfig::create([
- 'field_storage' => $field_storage,
- 'bundle' => $bundle,
- ])->save();
- }
- $bundles[] = $bundle;
- }
- // Each unit is a list of field name, langcode and a column-value array.
- $units[] = [$figures, 'en', [
- 'color' => 'red',
- 'shape' => 'triangle',
- ],
- ];
- $units[] = [$figures, 'en', [
- 'color' => 'blue',
- 'shape' => 'circle',
- ],
- ];
- // To make it easier to test sorting, the greetings get formats according
- // to their langcode.
- $units[] = [$greetings, 'tr', [
- 'value' => 'merhaba',
- 'format' => 'format-tr',
- ],
- ];
- $units[] = [$greetings, 'pl', [
- 'value' => 'siema',
- 'format' => 'format-pl',
- ],
- ];
- // Make these languages available to the greetings field.
- ConfigurableLanguage::createFromLangcode('tr')->save();
- ConfigurableLanguage::createFromLangcode('pl')->save();
- // Calculate the cartesian product of the unit array by looking at the
- // bits of $i and add the unit at the bits that are 1. For example,
- // decimal 13 is binary 1101 so unit 3,2 and 0 will be added to the
- // entity.
- for ($i = 1; $i <= 15; $i++) {
- $entity = EntityTestMulRev::create([
- 'type' => $bundles[$i & 1],
- 'name' => $this->randomMachineName(),
- 'langcode' => 'en',
- ]);
- // Make sure the name is set for every language that we might create.
- foreach (['tr', 'pl'] as $langcode) {
- $entity->addTranslation($langcode)->name = $this->randomMachineName();
- }
- foreach (array_reverse(str_split(decbin($i))) as $key => $bit) {
- if ($bit) {
- list($field_name, $langcode, $values) = $units[$key];
- $entity->getTranslation($langcode)->{$field_name}[] = $values;
- }
- }
- $entity->save();
- }
- $this->bundles = $bundles;
- $this->figures = $figures;
- $this->greetings = $greetings;
- $this->factory = \Drupal::service('entity.query');
- }
- /**
- * Test basic functionality.
- */
- public function testEntityQuery() {
- $greetings = $this->greetings;
- $figures = $this->figures;
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->exists($greetings, 'tr')
- ->condition("$figures.color", 'red')
- ->sort('id')
- ->execute();
- // As unit 0 was the red triangle and unit 2 was the turkish greeting,
- // bit 0 and bit 2 needs to be set.
- $this->assertResult(5, 7, 13, 15);
- $query = $this->factory->get('entity_test_mulrev', 'OR')
- ->exists($greetings, 'tr')
- ->condition("$figures.color", 'red')
- ->sort('id');
- $count_query = clone $query;
- $this->assertEqual(12, $count_query->count()->execute());
- $this->queryResults = $query->execute();
- // Now bit 0 (1, 3, 5, 7, 9, 11, 13, 15) or bit 2 (4, 5, 6, 7, 12, 13, 14,
- // 15) needs to be set.
- $this->assertResult(1, 3, 4, 5, 6, 7, 9, 11, 12, 13, 14, 15);
- // Test cloning of query conditions.
- $query = $this->factory->get('entity_test_mulrev')
- ->condition("$figures.color", 'red')
- ->sort('id');
- $cloned_query = clone $query;
- $cloned_query
- ->condition("$figures.shape", 'circle');
- // Bit 0 (1, 3, 5, 7, 9, 11, 13, 15) needs to be set.
- $this->queryResults = $query->execute();
- $this->assertResult(1, 3, 5, 7, 9, 11, 13, 15);
- // No red color has a circle shape.
- $this->queryResults = $cloned_query->execute();
- $this->assertResult();
- $query = $this->factory->get('entity_test_mulrev');
- $group = $query->orConditionGroup()
- ->exists($greetings, 'tr')
- ->condition("$figures.color", 'red');
- $this->queryResults = $query
- ->condition($group)
- ->condition("$greetings.value", 'sie', 'STARTS_WITH')
- ->sort('revision_id')
- ->execute();
- // Bit 3 and (bit 0 or 2) -- the above 8 part of the above.
- $this->assertResult(9, 11, 12, 13, 14, 15);
- // No figure has both the colors blue and red at the same time.
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("$figures.color", 'blue')
- ->condition("$figures.color", 'red')
- ->sort('id')
- ->execute();
- $this->assertResult();
- // But an entity might have a red and a blue figure both.
- $query = $this->factory->get('entity_test_mulrev');
- $group_blue = $query->andConditionGroup()->condition("$figures.color", 'blue');
- $group_red = $query->andConditionGroup()->condition("$figures.color", 'red');
- $this->queryResults = $query
- ->condition($group_blue)
- ->condition($group_red)
- ->sort('revision_id')
- ->execute();
- // Unit 0 and unit 1, so bits 0 1.
- $this->assertResult(3, 7, 11, 15);
- // Do the same test but with IN operator.
- $query = $this->factory->get('entity_test_mulrev');
- $group_blue = $query->andConditionGroup()->condition("$figures.color", ['blue'], 'IN');
- $group_red = $query->andConditionGroup()->condition("$figures.color", ['red'], 'IN');
- $this->queryResults = $query
- ->condition($group_blue)
- ->condition($group_red)
- ->sort('id')
- ->execute();
- // Unit 0 and unit 1, so bits 0 1.
- $this->assertResult(3, 7, 11, 15);
- // An entity might have either red or blue figure.
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("$figures.color", ['blue', 'red'], 'IN')
- ->sort('id')
- ->execute();
- // Bit 0 or 1 is on.
- $this->assertResult(1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15);
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->exists("$figures.color")
- ->notExists("$greetings.value")
- ->sort('id')
- ->execute();
- // Bit 0 or 1 is on but 2 and 3 are not.
- $this->assertResult(1, 2, 3);
- // Now update the 'merhaba' string to xsiemax which is not a meaningful
- // word but allows us to test revisions and string operations.
- $ids = $this->factory->get('entity_test_mulrev')
- ->condition("$greetings.value", 'merhaba')
- ->sort('id')
- ->execute();
- $entities = EntityTestMulRev::loadMultiple($ids);
- $first_entity = reset($entities);
- $old_name = $first_entity->name->value;
- foreach ($entities as $entity) {
- $entity->setNewRevision();
- $entity->getTranslation('tr')->$greetings->value = 'xsiemax';
- $entity->name->value .= 'x';
- $entity->save();
- }
- // We changed the entity names, so the current revision should not match.
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition('name.value', $old_name)
- ->execute();
- $this->assertResult();
- // Only if all revisions are queried, we find the old revision.
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition('name.value', $old_name)
- ->allRevisions()
- ->sort('revision_id')
- ->execute();
- $this->assertRevisionResult([$first_entity->id()], [$first_entity->id()]);
- // When querying current revisions, this string is no longer found.
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("$greetings.value", 'merhaba')
- ->execute();
- $this->assertResult();
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("$greetings.value", 'merhaba')
- ->allRevisions()
- ->sort('revision_id')
- ->execute();
- // The query only matches the original revisions.
- $this->assertRevisionResult([4, 5, 6, 7, 12, 13, 14, 15], [4, 5, 6, 7, 12, 13, 14, 15]);
- $results = $this->factory->get('entity_test_mulrev')
- ->condition("$greetings.value", 'siema', 'CONTAINS')
- ->sort('id')
- ->execute();
- // This matches both the original and new current revisions, multiple
- // revisions are returned for some entities.
- $assert = [16 => '4', 17 => '5', 18 => '6', 19 => '7', 8 => '8', 9 => '9', 10 => '10', 11 => '11', 20 => '12', 21 => '13', 22 => '14', 23 => '15'];
- $this->assertIdentical($results, $assert);
- $results = $this->factory->get('entity_test_mulrev')
- ->condition("$greetings.value", 'siema', 'STARTS_WITH')
- ->sort('revision_id')
- ->execute();
- // Now we only get the ones that originally were siema, entity id 8 and
- // above.
- $this->assertIdentical($results, array_slice($assert, 4, 8, TRUE));
- $results = $this->factory->get('entity_test_mulrev')
- ->condition("$greetings.value", 'a', 'ENDS_WITH')
- ->sort('revision_id')
- ->execute();
- // It is very important that we do not get the ones which only have
- // xsiemax despite originally they were merhaba, ie. ended with a.
- $this->assertIdentical($results, array_slice($assert, 4, 8, TRUE));
- $results = $this->factory->get('entity_test_mulrev')
- ->condition("$greetings.value", 'a', 'ENDS_WITH')
- ->allRevisions()
- ->sort('id')
- ->sort('revision_id')
- ->execute();
- // Now we get everything.
- $assert = [4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', 10 => '10', 11 => '11', 12 => '12', 20 => '12', 13 => '13', 21 => '13', 14 => '14', 22 => '14', 15 => '15', 23 => '15'];
- $this->assertIdentical($results, $assert);
- // Check that a query on the latest revisions without any condition returns
- // the correct results.
- $results = $this->factory->get('entity_test_mulrev')
- ->latestRevision()
- ->sort('id')
- ->sort('revision_id')
- ->execute();
- $expected = [1 => '1', 2 => '2', 3 => '3', 16 => '4', 17 => '5', 18 => '6', 19 => '7', 8 => '8', 9 => '9', 10 => '10', 11 => '11', 20 => '12', 21 => '13', 22 => '14', 23 => '15'];
- $this->assertSame($expected, $results);
- }
- /**
- * Test sort().
- *
- * Warning: this is complicated.
- */
- public function testSort() {
- $greetings = $this->greetings;
- $figures = $this->figures;
- // Order up and down on a number.
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->sort('id')
- ->execute();
- $this->assertResult(range(1, 15));
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->sort('id', 'DESC')
- ->execute();
- $this->assertResult(range(15, 1));
- $query = $this->factory->get('entity_test_mulrev')
- ->sort("$figures.color")
- ->sort("$greetings.format")
- ->sort('id');
- // As we do not have any conditions, here are the possible colors and
- // language codes, already in order, with the first occurrence of the
- // entity id marked with *:
- // 8 NULL pl *
- // 12 NULL pl *
- // 4 NULL tr *
- // 12 NULL tr
- // 2 blue NULL *
- // 3 blue NULL *
- // 10 blue pl *
- // 11 blue pl *
- // 14 blue pl *
- // 15 blue pl *
- // 6 blue tr *
- // 7 blue tr *
- // 14 blue tr
- // 15 blue tr
- // 1 red NULL
- // 3 red NULL
- // 9 red pl *
- // 11 red pl
- // 13 red pl *
- // 15 red pl
- // 5 red tr *
- // 7 red tr
- // 13 red tr
- // 15 red tr
- $count_query = clone $query;
- $this->assertEqual(15, $count_query->count()->execute());
- $this->queryResults = $query->execute();
- $this->assertResult(8, 12, 4, 2, 3, 10, 11, 14, 15, 6, 7, 1, 9, 13, 5);
- // Test the pager by setting element #1 to page 2 with a page size of 4.
- // Results will be #8-12 from above.
- $request = Request::createFromGlobals();
- $request->query->replace([
- 'page' => '0,2',
- ]);
- \Drupal::getContainer()->get('request_stack')->push($request);
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->sort("$figures.color")
- ->sort("$greetings.format")
- ->sort('id')
- ->pager(4, 1)
- ->execute();
- $this->assertResult(15, 6, 7, 1);
- // Now test the reversed order.
- $query = $this->factory->get('entity_test_mulrev')
- ->sort("$figures.color", 'DESC')
- ->sort("$greetings.format", 'DESC')
- ->sort('id', 'DESC');
- $count_query = clone $query;
- $this->assertEqual(15, $count_query->count()->execute());
- $this->queryResults = $query->execute();
- $this->assertResult(15, 13, 7, 5, 11, 9, 3, 1, 14, 6, 10, 2, 12, 4, 8);
- }
- /**
- * Test tablesort().
- */
- public function testTableSort() {
- // While ordering on bundles do not give us a definite order, we can still
- // assert that all entities from one bundle are after the other as the
- // order dictates.
- $request = Request::createFromGlobals();
- $request->query->replace([
- 'sort' => 'asc',
- 'order' => 'Type',
- ]);
- \Drupal::getContainer()->get('request_stack')->push($request);
- $header = [
- 'id' => ['data' => 'Id', 'specifier' => 'id'],
- 'type' => ['data' => 'Type', 'specifier' => 'type'],
- ];
- $this->queryResults = array_values($this->factory->get('entity_test_mulrev')
- ->tableSort($header)
- ->execute());
- $this->assertBundleOrder('asc');
- $request->query->add([
- 'sort' => 'desc',
- ]);
- \Drupal::getContainer()->get('request_stack')->push($request);
- $header = [
- 'id' => ['data' => 'Id', 'specifier' => 'id'],
- 'type' => ['data' => 'Type', 'specifier' => 'type'],
- ];
- $this->queryResults = array_values($this->factory->get('entity_test_mulrev')
- ->tableSort($header)
- ->execute());
- $this->assertBundleOrder('desc');
- // Ordering on ID is definite, however.
- $request->query->add([
- 'order' => 'Id',
- ]);
- \Drupal::getContainer()->get('request_stack')->push($request);
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->tableSort($header)
- ->execute();
- $this->assertResult(range(15, 1));
- }
- /**
- * Test that count queries are separated across entity types.
- */
- public function testCount() {
- // Create a field with the same name in a different entity type.
- $field_name = $this->figures;
- $field_storage = FieldStorageConfig::create([
- 'field_name' => $field_name,
- 'entity_type' => 'entity_test',
- 'type' => 'shape',
- 'cardinality' => 2,
- 'translatable' => TRUE,
- ]);
- $field_storage->save();
- $bundle = $this->randomMachineName();
- FieldConfig::create([
- 'field_storage' => $field_storage,
- 'bundle' => $bundle,
- ])->save();
- $entity = EntityTest::create([
- 'id' => 1,
- 'type' => $bundle,
- ]);
- $entity->enforceIsNew();
- $entity->save();
- // As the single entity of this type we just saved does not have a value
- // in the color field, the result should be 0.
- $count = $this->factory->get('entity_test')
- ->exists("$field_name.color")
- ->count()
- ->execute();
- $this->assertFalse($count);
- }
- /**
- * Tests that nested condition groups work as expected.
- */
- public function testNestedConditionGroups() {
- // Query for all entities of the first bundle that have either a red
- // triangle as a figure or the Turkish greeting as a greeting.
- $query = $this->factory->get('entity_test_mulrev');
- $first_and = $query->andConditionGroup()
- ->condition($this->figures . '.color', 'red')
- ->condition($this->figures . '.shape', 'triangle');
- $second_and = $query->andConditionGroup()
- ->condition($this->greetings . '.value', 'merhaba')
- ->condition($this->greetings . '.format', 'format-tr');
- $or = $query->orConditionGroup()
- ->condition($first_and)
- ->condition($second_and);
- $this->queryResults = $query
- ->condition($or)
- ->condition('type', reset($this->bundles))
- ->sort('id')
- ->execute();
- $this->assertResult(6, 14);
- }
- /**
- * Test queries with delta conditions.
- */
- public function testDelta() {
- $figures = $this->figures;
- // Test numeric delta value in field condition.
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("$figures.0.color", 'red')
- ->sort('id')
- ->execute();
- // As unit 0 at delta 0 was the red triangle bit 0 needs to be set.
- $this->assertResult(1, 3, 5, 7, 9, 11, 13, 15);
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("$figures.1.color", 'red')
- ->sort('id')
- ->execute();
- // Delta 1 is not red.
- $this->assertResult();
- // Test on two different deltas.
- $query = $this->factory->get('entity_test_mulrev');
- $or = $query->andConditionGroup()
- ->condition("$figures.0.color", 'red')
- ->condition("$figures.1.color", 'blue');
- $this->queryResults = $query
- ->condition($or)
- ->sort('id')
- ->execute();
- $this->assertResult(3, 7, 11, 15);
- // Test the delta range condition.
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("$figures.%delta.color", ['blue', 'red'], 'IN')
- ->condition("$figures.%delta", [0, 1], 'IN')
- ->sort('id')
- ->execute();
- // Figure delta 0 or 1 can be blue or red, this matches a lot of entities.
- $this->assertResult(1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15);
- // Test the delta range condition without conditions on the value.
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("$figures.%delta", 1)
- ->sort('id')
- ->execute();
- // Entity needs to have atleast two figures.
- $this->assertResult(3, 7, 11, 15);
- // Numeric delta on single value base field should return results only if
- // the first item is being targeted.
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("id.0.value", [1, 3, 5], 'IN')
- ->sort('id')
- ->execute();
- $this->assertResult(1, 3, 5);
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("id.1.value", [1, 3, 5], 'IN')
- ->sort('id')
- ->execute();
- $this->assertResult();
- // Delta range condition on single value base field should return results
- // only if just the field value is targeted.
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("id.%delta.value", [1, 3, 5], 'IN')
- ->sort('id')
- ->execute();
- $this->assertResult(1, 3, 5);
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("id.%delta.value", [1, 3, 5], 'IN')
- ->condition("id.%delta", 0, '=')
- ->sort('id')
- ->execute();
- $this->assertResult(1, 3, 5);
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition("id.%delta.value", [1, 3, 5], 'IN')
- ->condition("id.%delta", 1, '=')
- ->sort('id')
- ->execute();
- $this->assertResult();
- }
- protected function assertResult() {
- $assert = [];
- $expected = func_get_args();
- if ($expected && is_array($expected[0])) {
- $expected = $expected[0];
- }
- foreach ($expected as $binary) {
- $assert[$binary] = strval($binary);
- }
- $this->assertIdentical($this->queryResults, $assert);
- }
- protected function assertRevisionResult($keys, $expected) {
- $assert = [];
- foreach ($expected as $key => $binary) {
- $assert[$keys[$key]] = strval($binary);
- }
- $this->assertIdentical($this->queryResults, $assert);
- return $assert;
- }
- protected function assertBundleOrder($order) {
- // This loop is for bundle1 entities.
- for ($i = 1; $i <= 15; $i += 2) {
- $ok = TRUE;
- $index1 = array_search($i, $this->queryResults);
- $this->assertNotIdentical($index1, FALSE, "$i found at $index1.");
- // This loop is for bundle2 entities.
- for ($j = 2; $j <= 15; $j += 2) {
- if ($ok) {
- if ($order == 'asc') {
- $ok = $index1 > array_search($j, $this->queryResults);
- }
- else {
- $ok = $index1 < array_search($j, $this->queryResults);
- }
- }
- }
- $this->assertTrue($ok, "$i is after all entities in bundle2");
- }
- }
- /**
- * Test adding a tag and metadata to the Entity query object.
- *
- * The tags and metadata should propagate to the SQL query object.
- */
- public function testMetaData() {
- $query = \Drupal::entityQuery('entity_test_mulrev');
- $query
- ->addTag('efq_metadata_test')
- ->addMetaData('foo', 'bar')
- ->execute();
- global $efq_test_metadata;
- $this->assertEqual($efq_test_metadata, 'bar', 'Tag and metadata propagated to the SQL query object.');
- }
- /**
- * Test case sensitive and in-sensitive query conditions.
- */
- public function testCaseSensitivity() {
- $bundle = $this->randomMachineName();
- $field_storage = FieldStorageConfig::create([
- 'field_name' => 'field_ci',
- 'entity_type' => 'entity_test_mulrev',
- 'type' => 'string',
- 'cardinality' => 1,
- 'translatable' => FALSE,
- 'settings' => [
- 'case_sensitive' => FALSE,
- ]
- ]);
- $field_storage->save();
- FieldConfig::create([
- 'field_storage' => $field_storage,
- 'bundle' => $bundle,
- ])->save();
- $field_storage = FieldStorageConfig::create([
- 'field_name' => 'field_cs',
- 'entity_type' => 'entity_test_mulrev',
- 'type' => 'string',
- 'cardinality' => 1,
- 'translatable' => FALSE,
- 'settings' => [
- 'case_sensitive' => TRUE,
- ],
- ]);
- $field_storage->save();
- FieldConfig::create([
- 'field_storage' => $field_storage,
- 'bundle' => $bundle,
- ])->save();
- $fixtures = [];
- for ($i = 0; $i < 2; $i++) {
- // If the last 4 of the string are all numbers, then there is no
- // difference between upper and lowercase and the case sensitive CONTAINS
- // test will fail. Ensure that can not happen by appending a non-numeric
- // character. See https://www.drupal.org/node/2397297.
- $string = $this->randomMachineName(7) . 'a';
- $fixtures[] = [
- 'original' => $string,
- 'uppercase' => Unicode::strtoupper($string),
- 'lowercase' => Unicode::strtolower($string),
- ];
- }
- EntityTestMulRev::create([
- 'type' => $bundle,
- 'name' => $this->randomMachineName(),
- 'langcode' => 'en',
- 'field_ci' => $fixtures[0]['uppercase'] . $fixtures[1]['lowercase'],
- 'field_cs' => $fixtures[0]['uppercase'] . $fixtures[1]['lowercase']
- ])->save();
- // Check the case insensitive field, = operator.
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_ci', $fixtures[0]['lowercase'] . $fixtures[1]['lowercase']
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case insensitive, lowercase');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_ci', $fixtures[0]['uppercase'] . $fixtures[1]['uppercase']
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case insensitive, uppercase');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_ci', $fixtures[0]['uppercase'] . $fixtures[1]['lowercase']
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case insensitive, mixed.');
- // Check the case sensitive field, = operator.
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_cs', $fixtures[0]['lowercase'] . $fixtures[1]['lowercase']
- )->execute();
- $this->assertIdentical(count($result), 0, 'Case sensitive, lowercase.');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_cs', $fixtures[0]['uppercase'] . $fixtures[1]['uppercase']
- )->execute();
- $this->assertIdentical(count($result), 0, 'Case sensitive, uppercase.');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_cs', $fixtures[0]['uppercase'] . $fixtures[1]['lowercase']
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case sensitive, exact match.');
- // Check the case insensitive field, IN operator.
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_ci', [$fixtures[0]['lowercase'] . $fixtures[1]['lowercase']], 'IN'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case insensitive, lowercase');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_ci', [$fixtures[0]['uppercase'] . $fixtures[1]['uppercase']], 'IN'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case insensitive, uppercase');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_ci', [$fixtures[0]['uppercase'] . $fixtures[1]['lowercase']], 'IN'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case insensitive, mixed');
- // Check the case sensitive field, IN operator.
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_cs', [$fixtures[0]['lowercase'] . $fixtures[1]['lowercase']], 'IN'
- )->execute();
- $this->assertIdentical(count($result), 0, 'Case sensitive, lowercase');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_cs', [$fixtures[0]['uppercase'] . $fixtures[1]['uppercase']], 'IN'
- )->execute();
- $this->assertIdentical(count($result), 0, 'Case sensitive, uppercase');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_cs', [$fixtures[0]['uppercase'] . $fixtures[1]['lowercase']], 'IN'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case sensitive, mixed');
- // Check the case insensitive field, STARTS_WITH operator.
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_ci', $fixtures[0]['lowercase'], 'STARTS_WITH'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case sensitive, lowercase.');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_ci', $fixtures[0]['uppercase'], 'STARTS_WITH'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case sensitive, exact match.');
- // Check the case sensitive field, STARTS_WITH operator.
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_cs', $fixtures[0]['lowercase'], 'STARTS_WITH'
- )->execute();
- $this->assertIdentical(count($result), 0, 'Case sensitive, lowercase.');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_cs', $fixtures[0]['uppercase'], 'STARTS_WITH'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case sensitive, exact match.');
- // Check the case insensitive field, ENDS_WITH operator.
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_ci', $fixtures[1]['lowercase'], 'ENDS_WITH'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case sensitive, lowercase.');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_ci', $fixtures[1]['uppercase'], 'ENDS_WITH'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case sensitive, exact match.');
- // Check the case sensitive field, ENDS_WITH operator.
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_cs', $fixtures[1]['lowercase'], 'ENDS_WITH'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case sensitive, lowercase.');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_cs', $fixtures[1]['uppercase'], 'ENDS_WITH'
- )->execute();
- $this->assertIdentical(count($result), 0, 'Case sensitive, exact match.');
- // Check the case insensitive field, CONTAINS operator, use the inner 8
- // characters of the uppercase and lowercase strings.
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_ci', Unicode::substr($fixtures[0]['uppercase'] . $fixtures[1]['lowercase'], 4, 8), 'CONTAINS'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case sensitive, lowercase.');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_ci', Unicode::strtolower(Unicode::substr($fixtures[0]['uppercase'] . $fixtures[1]['lowercase'], 4, 8)), 'CONTAINS'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case sensitive, exact match.');
- // Check the case sensitive field, CONTAINS operator.
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_cs', Unicode::substr($fixtures[0]['uppercase'] . $fixtures[1]['lowercase'], 4, 8), 'CONTAINS'
- )->execute();
- $this->assertIdentical(count($result), 1, 'Case sensitive, lowercase.');
- $result = \Drupal::entityQuery('entity_test_mulrev')->condition(
- 'field_cs', Unicode::strtolower(Unicode::substr($fixtures[0]['uppercase'] . $fixtures[1]['lowercase'], 4, 8)), 'CONTAINS'
- )->execute();
- $this->assertIdentical(count($result), 0, 'Case sensitive, exact match.');
- }
- /**
- * Test base fields with multiple columns.
- */
- public function testBaseFieldMultipleColumns() {
- $this->enableModules(['taxonomy']);
- $this->installEntitySchema('taxonomy_term');
- Vocabulary::create(['vid' => 'tags']);
- $term1 = Term::create([
- 'name' => $this->randomMachineName(),
- 'vid' => 'tags',
- 'description' => [
- 'value' => $this->randomString(),
- 'format' => 'format1',
- ],
- ]);
- $term1->save();
- $term2 = Term::create([
- 'name' => $this->randomMachineName(),
- 'vid' => 'tags',
- 'description' => [
- 'value' => $this->randomString(),
- 'format' => 'format2',
- ],
- ]);
- $term2->save();
- $ids = \Drupal::entityQuery('taxonomy_term')
- ->condition('description.format', 'format1')
- ->execute();
- $this->assertEqual(count($ids), 1);
- $this->assertEqual($term1->id(), reset($ids));
- }
- /**
- * Test pending revisions.
- */
- public function testPendingRevisions() {
- // Ensure entity 14 is returned.
- $result = \Drupal::entityQuery('entity_test_mulrev')
- ->condition('id', [14], 'IN')
- ->execute();
- $this->assertEqual(count($result), 1);
- // Set a revision on entity 14 that isn't the current default.
- $entity = EntityTestMulRev::load(14);
- $current_values = $entity->{$this->figures}->getValue();
- $entity->setNewRevision(TRUE);
- $entity->isDefaultRevision(FALSE);
- $entity->{$this->figures}->setValue([
- 'color' => 'red',
- 'shape' => 'square'
- ]);
- $entity->save();
- // Entity query should still return entity 14.
- $result = \Drupal::entityQuery('entity_test_mulrev')
- ->condition('id', [14], 'IN')
- ->execute();
- $this->assertEqual(count($result), 1);
- // Verify that field conditions on the default and pending revision are
- // work as expected.
- $result = \Drupal::entityQuery('entity_test_mulrev')
- ->condition('id', [14], 'IN')
- ->condition("$this->figures.color", $current_values[0]['color'])
- ->execute();
- $this->assertEqual($result, [14 => '14']);
- $result = $this->factory->get('entity_test_mulrev')
- ->condition('id', [14], 'IN')
- ->condition("$this->figures.color", 'red')
- ->allRevisions()
- ->execute();
- $this->assertEqual($result, [16 => '14']);
- // Add another pending revision on the same entity and repeat the checks.
- $entity->setNewRevision(TRUE);
- $entity->isDefaultRevision(FALSE);
- $entity->{$this->figures}->setValue([
- 'color' => 'red',
- 'shape' => 'square'
- ]);
- $entity->save();
- // A non-revisioned entity query should still return entity 14.
- $result = $this->factory->get('entity_test_mulrev')
- ->condition('id', [14], 'IN')
- ->execute();
- $this->assertCount(1, $result);
- $this->assertSame([14 => '14'], $result);
- // Now check an entity query on the latest revision.
- $result = $this->factory->get('entity_test_mulrev')
- ->condition('id', [14], 'IN')
- ->latestRevision()
- ->execute();
- $this->assertCount(1, $result);
- $this->assertSame([17 => '14'], $result);
- // Verify that field conditions on the default and pending revision still
- // work as expected.
- $result = $this->factory->get('entity_test_mulrev')
- ->condition('id', [14], 'IN')
- ->condition("$this->figures.color", $current_values[0]['color'])
- ->execute();
- $this->assertSame([14 => '14'], $result);
- // Now there are two revisions with same value for the figure color.
- $result = $this->factory->get('entity_test_mulrev')
- ->condition('id', [14], 'IN')
- ->condition("$this->figures.color", 'red')
- ->allRevisions()
- ->execute();
- $this->assertSame([16 => '14', 17 => '14'], $result);
- // Check that querying for the latest revision returns the correct one.
- $result = $this->factory->get('entity_test_mulrev')
- ->condition('id', [14], 'IN')
- ->condition("$this->figures.color", 'red')
- ->latestRevision()
- ->execute();
- $this->assertSame([17 => '14'], $result);
- }
- /**
- * Test against SQL inject of condition field. This covers a
- * database driver's EntityQuery\Condition class.
- */
- public function testInjectionInCondition() {
- try {
- $this->queryResults = $this->factory->get('entity_test_mulrev')
- ->condition('1 ; -- ', [0, 1], 'IN')
- ->sort('id')
- ->execute();
- $this->fail('SQL Injection attempt in Entity Query condition in operator should result in an exception.');
- }
- catch (\Exception $e) {
- $this->pass('SQL Injection attempt in Entity Query condition in operator should result in an exception.');
- }
- }
- /**
- * Tests that EntityQuery works when querying the same entity from two fields.
- */
- public function testWithTwoEntityReferenceFieldsToSameEntityType() {
- // Create two entity reference fields referring 'entity_test' entities.
- $this->createEntityReferenceField('entity_test', 'entity_test', 'ref1', $this->randomMachineName(), 'entity_test');
- $this->createEntityReferenceField('entity_test', 'entity_test', 'ref2', $this->randomMachineName(), 'entity_test');
- // Create two entities to be referred.
- $ref1 = EntityTest::create(['type' => 'entity_test']);
- $ref1->save();
- $ref2 = EntityTest::create(['type' => 'entity_test']);
- $ref2->save();
- // Create a main entity referring the previous created entities.
- $entity = EntityTest::create([
- 'type' => 'entity_test',
- 'ref1' => $ref1->id(),
- 'ref2' => $ref2->id(),
- ]);
- $entity->save();
- // Check that works when referring with "{$field_name}".
- $result = $this->factory->get('entity_test')
- ->condition('type', 'entity_test')
- ->condition('ref1', $ref1->id())
- ->condition('ref2', $ref2->id())
- ->execute();
- $this->assertCount(1, $result);
- $this->assertEquals($entity->id(), reset($result));
- // Check that works when referring with "{$field_name}.target_id".
- $result = $this->factory->get('entity_test')
- ->condition('type', 'entity_test')
- ->condition('ref1.target_id', $ref1->id())
- ->condition('ref2.target_id', $ref2->id())
- ->execute();
- $this->assertCount(1, $result);
- $this->assertEquals($entity->id(), reset($result));
- // Check that works when referring with "{$field_name}.entity.id".
- $result = $this->factory->get('entity_test')
- ->condition('type', 'entity_test')
- ->condition('ref1.entity.id', $ref1->id())
- ->condition('ref2.entity.id', $ref2->id())
- ->execute();
- $this->assertCount(1, $result);
- $this->assertEquals($entity->id(), reset($result));
- }
- }
|