Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions
1496
web/core/tests/Drupal/KernelTests/AssertContentTrait.php
Normal file
1496
web/core/tests/Drupal/KernelTests/AssertContentTrait.php
Normal file
File diff suppressed because it is too large
Load diff
|
@ -6,7 +6,7 @@ namespace Drupal\KernelTests;
|
|||
* Translates Simpletest assertion methods to PHPUnit.
|
||||
*
|
||||
* Protected methods are custom. Public static methods override methods of
|
||||
* \PHPUnit_Framework_Assert.
|
||||
* \PHPUnit\Framework\Assert.
|
||||
*
|
||||
* @deprecated Scheduled for removal in Drupal 9.0.0. Use PHPUnit's native
|
||||
* assert methods instead.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Drupal\KernelTests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
|
@ -28,7 +28,7 @@ class SafeMarkupKernelTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets arguments for SafeMarkup::format() based on Url::fromUri() parameters.
|
||||
* Gets arguments for FormattableMarkup based on Url::fromUri() parameters.
|
||||
*
|
||||
* @param string $uri
|
||||
* The URI of the resource.
|
||||
|
@ -38,6 +38,8 @@ class SafeMarkupKernelTest extends KernelTestBase {
|
|||
* @return array
|
||||
* Array containing:
|
||||
* - ':url': A URL string.
|
||||
*
|
||||
* @see \Drupal\Component\Render\FormattableMarkup
|
||||
*/
|
||||
protected static function getSafeMarkupUriArgs($uri, $options = []) {
|
||||
$args[':url'] = Url::fromUri($uri, $options)->toString();
|
||||
|
@ -45,13 +47,13 @@ class SafeMarkupKernelTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tests URL ":placeholders" in SafeMarkup::format().
|
||||
* Tests URL ":placeholders" in \Drupal\Component\Render\FormattableMarkup.
|
||||
*
|
||||
* @dataProvider providerTestSafeMarkupUri
|
||||
*/
|
||||
public function testSafeMarkupUri($string, $uri, $options, $expected) {
|
||||
$args = self::getSafeMarkupUriArgs($uri, $options);
|
||||
$this->assertEquals($expected, SafeMarkup::format($string, $args));
|
||||
$this->assertEquals($expected, new FormattableMarkup($string, $args));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,7 +115,7 @@ class SafeMarkupKernelTest extends KernelTestBase {
|
|||
$this->setExpectedException(\InvalidArgumentException::class);
|
||||
$args = self::getSafeMarkupUriArgs($uri);
|
||||
|
||||
SafeMarkup::format($string, $args);
|
||||
new FormattableMarkup($string, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -81,12 +81,6 @@ class DefaultConfigTest extends KernelTestBase {
|
|||
/** @var \Drupal\Core\Extension\ModuleInstallerInterface $module_installer */
|
||||
$module_installer = $this->container->get('module_installer');
|
||||
|
||||
// @todo https://www.drupal.org/node/2308745 Rest has an implicit dependency
|
||||
// on the Node module remove once solved.
|
||||
if (in_array($module, ['rest', 'hal'])) {
|
||||
$module_installer->install(['node']);
|
||||
}
|
||||
|
||||
// Work out any additional modules and themes that need installing to create
|
||||
// an optional config.
|
||||
$optional_config_storage = new FileStorage($module_path . InstallStorage::CONFIG_OPTIONAL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION);
|
||||
|
|
166
web/core/tests/Drupal/KernelTests/Config/TypedConfigTest.php
Normal file
166
web/core/tests/Drupal/KernelTests/Config/TypedConfigTest.php
Normal file
|
@ -0,0 +1,166 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Config;
|
||||
|
||||
use Drupal\Core\Config\Schema\SequenceDataDefinition;
|
||||
use Drupal\Core\Config\Schema\TypedConfigInterface;
|
||||
use Drupal\Core\TypedData\ComplexDataDefinitionInterface;
|
||||
use Drupal\Core\TypedData\ComplexDataInterface;
|
||||
use Drupal\Core\TypedData\Type\IntegerInterface;
|
||||
use Drupal\Core\TypedData\Type\StringInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Symfony\Component\Validator\ConstraintViolationListInterface;
|
||||
|
||||
/**
|
||||
* Tests config validation mechanism.
|
||||
*
|
||||
* @group Config
|
||||
*/
|
||||
class TypedConfigTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['config_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installConfig('config_test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the Typed Data API is implemented correctly.
|
||||
*/
|
||||
public function testTypedDataAPI() {
|
||||
/** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager */
|
||||
$typed_config_manager = \Drupal::service('config.typed');
|
||||
/** @var \Drupal\Core\Config\Schema\TypedConfigInterface $typed_config */
|
||||
$typed_config = $typed_config_manager->get('config_test.validation');
|
||||
|
||||
// Test a primitive.
|
||||
$string_data = $typed_config->get('llama');
|
||||
$this->assertInstanceOf(StringInterface::class, $string_data);
|
||||
$this->assertEquals('llama', $string_data->getValue());
|
||||
|
||||
// Test complex data.
|
||||
$mapping = $typed_config->get('cat');
|
||||
/** @var \Drupal\Core\TypedData\ComplexDataInterface $mapping */
|
||||
$this->assertInstanceOf(ComplexDataInterface::class, $mapping);
|
||||
$this->assertInstanceOf(StringInterface::class, $mapping->get('type'));
|
||||
$this->assertEquals('kitten', $mapping->get('type')->getValue());
|
||||
$this->assertInstanceOf(IntegerInterface::class, $mapping->get('count'));
|
||||
$this->assertEquals(2, $mapping->get('count')->getValue());
|
||||
// Verify the item metadata is available.
|
||||
$this->assertInstanceOf(ComplexDataDefinitionInterface::class, $mapping->getDataDefinition());
|
||||
$this->assertArrayHasKey('type', $mapping->getProperties());
|
||||
$this->assertArrayHasKey('count', $mapping->getProperties());
|
||||
|
||||
// Test accessing sequences.
|
||||
$sequence = $typed_config->get('giraffe');
|
||||
/** @var \Drupal\Core\TypedData\ListInterface $sequence */
|
||||
$this->assertInstanceOf(ComplexDataInterface::class, $sequence);
|
||||
$this->assertInstanceOf(StringInterface::class, $sequence->get('hum1'));
|
||||
$this->assertEquals('hum1', $sequence->get('hum1')->getValue());
|
||||
$this->assertEquals('hum2', $sequence->get('hum2')->getValue());
|
||||
$this->assertEquals(2, count($sequence->getIterator()));
|
||||
// Verify the item metadata is available.
|
||||
$this->assertInstanceOf(SequenceDataDefinition::class, $sequence->getDataDefinition());
|
||||
|
||||
// Test accessing typed config objects for simple config and config
|
||||
// entities.
|
||||
$typed_config_manager = \Drupal::service('config.typed');
|
||||
$typed_config = $typed_config_manager->createFromNameAndData('config_test.validation', \Drupal::configFactory()->get('config_test.validation')->get());
|
||||
$this->assertInstanceOf(TypedConfigInterface::class, $typed_config);
|
||||
$this->assertEquals(['llama', 'cat', 'giraffe', 'uuid', '_core'], array_keys($typed_config->getElements()));
|
||||
|
||||
$config_test_entity = \Drupal::entityTypeManager()->getStorage('config_test')->create([
|
||||
'id' => 'asterix',
|
||||
'label' => 'Asterix',
|
||||
'weight' => 11,
|
||||
'style' => 'test_style',
|
||||
]);
|
||||
|
||||
$typed_config = $typed_config_manager->createFromNameAndData($config_test_entity->getConfigDependencyName(), $config_test_entity->toArray());
|
||||
$this->assertInstanceOf(TypedConfigInterface::class, $typed_config);
|
||||
$this->assertEquals(['uuid', 'langcode', 'status', 'dependencies', 'id', 'label', 'weight', 'style', 'size', 'size_value', 'protected_property'], array_keys($typed_config->getElements()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests config validation via the Typed Data API.
|
||||
*/
|
||||
public function testSimpleConfigValidation() {
|
||||
$config = \Drupal::configFactory()->getEditable('config_test.validation');
|
||||
/** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager */
|
||||
$typed_config_manager = \Drupal::service('config.typed');
|
||||
/** @var \Drupal\Core\Config\Schema\TypedConfigInterface $typed_config */
|
||||
$typed_config = $typed_config_manager->get('config_test.validation');
|
||||
|
||||
$result = $typed_config->validate();
|
||||
$this->assertInstanceOf(ConstraintViolationListInterface::class, $result);
|
||||
$this->assertEmpty($result);
|
||||
|
||||
// Test constraints on primitive types.
|
||||
$config->set('llama', 'elephant');
|
||||
$config->save();
|
||||
|
||||
$typed_config = $typed_config_manager->get('config_test.validation');
|
||||
$result = $typed_config->validate();
|
||||
// Its not a valid llama anymore.
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('no valid llama', $result->get(0)->getMessage());
|
||||
|
||||
// Test constraints on mapping.
|
||||
$config->set('llama', 'llama');
|
||||
$config->set('cat.type', 'nyans');
|
||||
$config->save();
|
||||
|
||||
$typed_config = $typed_config_manager->get('config_test.validation');
|
||||
$result = $typed_config->validate();
|
||||
$this->assertEmpty($result);
|
||||
|
||||
// Test constrains on nested mapping.
|
||||
$config->set('cat.type', 'miaus');
|
||||
$config->save();
|
||||
|
||||
$typed_config = $typed_config_manager->get('config_test.validation');
|
||||
$result = $typed_config->validate();
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('no valid cat', $result->get(0)->getMessage());
|
||||
|
||||
// Test constrains on sequences elements.
|
||||
$config->set('cat.type', 'nyans');
|
||||
$config->set('giraffe', ['muh', 'hum2']);
|
||||
$config->save();
|
||||
$typed_config = $typed_config_manager->get('config_test.validation');
|
||||
$result = $typed_config->validate();
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('Giraffes just hum', $result->get(0)->getMessage());
|
||||
|
||||
// Test constrains on the sequence itself.
|
||||
$config->set('giraffe', ['hum', 'hum2', 'invalid-key' => 'hum']);
|
||||
$config->save();
|
||||
|
||||
$typed_config = $typed_config_manager->get('config_test.validation');
|
||||
$result = $typed_config->validate();
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('giraffe', $result->get(0)->getPropertyPath());
|
||||
$this->assertEquals('Invalid giraffe key.', $result->get(0)->getMessage());
|
||||
|
||||
// Validates mapping.
|
||||
$typed_config = $typed_config_manager->get('config_test.validation');
|
||||
$value = $typed_config->getValue();
|
||||
unset($value['giraffe']);
|
||||
$value['elephant'] = 'foo';
|
||||
$value['zebra'] = 'foo';
|
||||
$typed_config->setValue($value);
|
||||
$result = $typed_config->validate();
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals('', $result->get(0)->getPropertyPath());
|
||||
$this->assertEquals('Unexpected keys: elephant, zebra', $result->get(0)->getMessage());
|
||||
}
|
||||
|
||||
}
|
66
web/core/tests/Drupal/KernelTests/ConfigFormTestBase.php
Normal file
66
web/core/tests/Drupal/KernelTests/ConfigFormTestBase.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests;
|
||||
|
||||
use Drupal\Core\Form\FormState;
|
||||
|
||||
/**
|
||||
* Full generic test suite for any form that data with the configuration system.
|
||||
*
|
||||
* @see UserAdminSettingsFormTest
|
||||
* For a full working implementation.
|
||||
*/
|
||||
abstract class ConfigFormTestBase extends KernelTestBase {
|
||||
/**
|
||||
* Form ID to use for testing.
|
||||
*
|
||||
* @var \Drupal\Core\Form\FormInterface
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* Values to use for testing.
|
||||
*
|
||||
* Contains details for form key, configuration object name, and config key.
|
||||
* Example:
|
||||
* @code
|
||||
* array(
|
||||
* 'user_mail_cancel_confirm_body' => array(
|
||||
* '#value' => $this->randomString(),
|
||||
* '#config_name' => 'user.mail',
|
||||
* '#config_key' => 'cancel_confirm.body',
|
||||
* ),
|
||||
* );
|
||||
* @endcode
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $values;
|
||||
|
||||
/**
|
||||
* Submit the system_config_form ensure the configuration has expected values.
|
||||
*/
|
||||
public function testConfigForm() {
|
||||
// Programmatically submit the given values.
|
||||
$values = [];
|
||||
foreach ($this->values as $form_key => $data) {
|
||||
$values[$form_key] = $data['#value'];
|
||||
}
|
||||
$form_state = (new FormState())->setValues($values);
|
||||
\Drupal::formBuilder()->submitForm($this->form, $form_state);
|
||||
|
||||
// Check that the form returns an error when expected, and vice versa.
|
||||
$errors = $form_state->getErrors();
|
||||
$valid_form = empty($errors);
|
||||
$args = [
|
||||
'%values' => print_r($values, TRUE),
|
||||
'%errors' => $valid_form ? t('None') : implode(' ', $errors),
|
||||
];
|
||||
$this->assertTrue($valid_form, format_string('Input values: %values<br/>Validation handler errors: %errors', $args));
|
||||
|
||||
foreach ($this->values as $data) {
|
||||
$this->assertEqual($data['#value'], $this->config($data['#config_name'])->get($data['#config_key']));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Action;
|
||||
|
||||
use Drupal\Core\Action\Plugin\Action\Derivative\EntityDeleteActionDeriver;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRevPub;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\system\Entity\Action;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* @group Action
|
||||
*/
|
||||
class DeleteActionTest extends KernelTestBase {
|
||||
|
||||
protected $testUser;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['system', 'entity_test', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('entity_test_mulrevpub');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installSchema('system', ['sequences', 'key_value_expire']);
|
||||
|
||||
$this->testUser = User::create([
|
||||
'name' => 'foobar',
|
||||
'mail' => 'foobar@example.com',
|
||||
]);
|
||||
$this->testUser->save();
|
||||
\Drupal::service('current_user')->setAccount($this->testUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Action\Plugin\Action\Derivative\EntityDeleteActionDeriver::getDerivativeDefinitions
|
||||
*/
|
||||
public function testGetDerivativeDefinitions() {
|
||||
$deriver = new EntityDeleteActionDeriver(\Drupal::entityTypeManager(), \Drupal::translation());
|
||||
$this->assertEquals([
|
||||
'entity_test_mulrevpub' => [
|
||||
'type' => 'entity_test_mulrevpub',
|
||||
'label' => 'Delete test entity - revisions, data table, and published interface',
|
||||
'action_label' => 'Delete',
|
||||
'confirm_form_route_name' => 'entity.entity_test_mulrevpub.delete_multiple_form',
|
||||
],
|
||||
'entity_test_rev' => [
|
||||
'type' => 'entity_test_rev',
|
||||
'label' => 'Delete test entity - revisions',
|
||||
'action_label' => 'Delete',
|
||||
'confirm_form_route_name' => 'entity.entity_test_rev.delete_multiple_form',
|
||||
],
|
||||
], $deriver->getDerivativeDefinitions([
|
||||
'action_label' => 'Delete',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Action\Plugin\Action\DeleteAction::execute
|
||||
*/
|
||||
public function testDeleteAction() {
|
||||
$entity = EntityTestMulRevPub::create(['name' => 'test']);
|
||||
$entity->save();
|
||||
|
||||
$action = Action::create([
|
||||
'id' => 'entity_delete_action',
|
||||
'plugin' => 'entity:delete_action:entity_test_mulrevpub',
|
||||
]);
|
||||
$action->save();
|
||||
|
||||
$action->execute([$entity]);
|
||||
$this->assertArraySubset(['module' => ['entity_test']], $action->getDependencies());
|
||||
|
||||
/** @var \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store */
|
||||
$temp_store = \Drupal::service('tempstore.private');
|
||||
$store_entries = $temp_store->get('entity_delete_multiple_confirm')->get($this->testUser->id() . ':entity_test_mulrevpub');
|
||||
$this->assertArraySubset([$this->testUser->id() => ['en' => 'en']], $store_entries);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Action;
|
||||
|
||||
use Drupal\Core\Action\Plugin\Action\Derivative\EntityPublishedActionDeriver;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRevPub;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\system\Entity\Action;
|
||||
|
||||
/**
|
||||
* @group Action
|
||||
*/
|
||||
class PublishActionTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['system', 'entity_test', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('entity_test_mulrevpub');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Action\Plugin\Action\Derivative\EntityPublishedActionDeriver::getDerivativeDefinitions
|
||||
*/
|
||||
public function testGetDerivativeDefinitions() {
|
||||
$deriver = new EntityPublishedActionDeriver(\Drupal::entityTypeManager(), \Drupal::translation());
|
||||
$this->assertArraySubset([
|
||||
'entity_test_mulrevpub' => [
|
||||
'type' => 'entity_test_mulrevpub',
|
||||
'label' => 'Save test entity - revisions, data table, and published interface',
|
||||
'action_label' => 'Save',
|
||||
],
|
||||
], $deriver->getDerivativeDefinitions([
|
||||
'action_label' => 'Save',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Action\Plugin\Action\PublishAction::execute
|
||||
*/
|
||||
public function testPublishAction() {
|
||||
$entity = EntityTestMulRevPub::create(['name' => 'test']);
|
||||
$entity->setUnpublished()->save();
|
||||
|
||||
$action = Action::create([
|
||||
'id' => 'entity_publish_action',
|
||||
'plugin' => 'entity:publish_action:entity_test_mulrevpub',
|
||||
]);
|
||||
$action->save();
|
||||
$this->assertFalse($entity->isPublished());
|
||||
$action->execute([$entity]);
|
||||
$this->assertTrue($entity->isPublished());
|
||||
$this->assertArraySubset(['module' => ['entity_test']], $action->getDependencies());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Action\Plugin\Action\UnpublishAction::execute
|
||||
*/
|
||||
public function testUnpublishAction() {
|
||||
$entity = EntityTestMulRevPub::create(['name' => 'test']);
|
||||
$entity->setPublished()->save();
|
||||
|
||||
$action = Action::create([
|
||||
'id' => 'entity_unpublish_action',
|
||||
'plugin' => 'entity:unpublish_action:entity_test_mulrevpub',
|
||||
]);
|
||||
$action->save();
|
||||
$this->assertTrue($entity->isPublished());
|
||||
$action->execute([$entity]);
|
||||
$this->assertFalse($entity->isPublished());
|
||||
$this->assertArraySubset(['module' => ['entity_test']], $action->getDependencies());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Action;
|
||||
|
||||
use Drupal\Core\Action\Plugin\Action\Derivative\EntityChangedActionDeriver;
|
||||
use Drupal\entity_test\Entity\EntityTestMulChanged;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\system\Entity\Action;
|
||||
|
||||
/**
|
||||
* @group Action
|
||||
*/
|
||||
class SaveActionTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['system', 'entity_test', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('entity_test_mul_changed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Action\Plugin\Action\Derivative\EntityChangedActionDeriver::getDerivativeDefinitions
|
||||
*/
|
||||
public function testGetDerivativeDefinitions() {
|
||||
$deriver = new EntityChangedActionDeriver(\Drupal::entityTypeManager(), \Drupal::translation());
|
||||
$this->assertArraySubset([
|
||||
'entity_test_mul_changed' => [
|
||||
'type' => 'entity_test_mul_changed',
|
||||
'label' => 'Save test entity - data table',
|
||||
'action_label' => 'Save',
|
||||
],
|
||||
], $deriver->getDerivativeDefinitions([
|
||||
'action_label' => 'Save',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Action\Plugin\Action\SaveAction::execute
|
||||
*/
|
||||
public function testSaveAction() {
|
||||
$entity = EntityTestMulChanged::create(['name' => 'test']);
|
||||
$entity->save();
|
||||
$saved_time = $entity->getChangedTime();
|
||||
|
||||
$action = Action::create([
|
||||
'id' => 'entity_save_action',
|
||||
'plugin' => 'entity:save_action:entity_test_mul_changed',
|
||||
]);
|
||||
$action->save();
|
||||
$action->execute([$entity]);
|
||||
$this->assertNotSame($saved_time, $entity->getChangedTime());
|
||||
$this->assertArraySubset(['module' => ['entity_test']], $action->getDependencies());
|
||||
}
|
||||
|
||||
}
|
103
web/core/tests/Drupal/KernelTests/Core/Ajax/CommandsTest.php
Normal file
103
web/core/tests/Drupal/KernelTests/Core/Ajax/CommandsTest.php
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Ajax;
|
||||
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Performs tests on AJAX framework commands.
|
||||
*
|
||||
* @group Ajax
|
||||
*/
|
||||
class CommandsTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['system', 'node', 'ajax_test', 'ajax_forms_test'];
|
||||
|
||||
/**
|
||||
* Regression test: Settings command exists regardless of JS aggregation.
|
||||
*/
|
||||
public function testAttachedSettings() {
|
||||
$assert = function ($message) {
|
||||
$response = new AjaxResponse();
|
||||
$response->setAttachments([
|
||||
'library' => ['core/drupalSettings'],
|
||||
'drupalSettings' => ['foo' => 'bar'],
|
||||
]);
|
||||
|
||||
$ajax_response_attachments_processor = \Drupal::service('ajax_response.attachments_processor');
|
||||
$subscriber = new AjaxResponseSubscriber($ajax_response_attachments_processor);
|
||||
$event = new FilterResponseEvent(
|
||||
\Drupal::service('http_kernel'),
|
||||
new Request(),
|
||||
HttpKernelInterface::MASTER_REQUEST,
|
||||
$response
|
||||
);
|
||||
$subscriber->onResponse($event);
|
||||
$expected = [
|
||||
'command' => 'settings',
|
||||
];
|
||||
$this->assertCommand($response->getCommands(), $expected, $message);
|
||||
};
|
||||
|
||||
$config = $this->config('system.performance');
|
||||
|
||||
$config->set('js.preprocess', FALSE)->save();
|
||||
$assert('Settings command exists when JS aggregation is disabled.');
|
||||
|
||||
$config->set('js.preprocess', TRUE)->save();
|
||||
$assert('Settings command exists when JS aggregation is enabled.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the array of Ajax commands contains the searched command.
|
||||
*
|
||||
* An AjaxResponse object stores an array of Ajax commands. This array
|
||||
* sometimes includes commands automatically provided by the framework in
|
||||
* addition to commands returned by a particular controller. During testing,
|
||||
* we're usually interested that a particular command is present, and don't
|
||||
* care whether other commands precede or follow the one we're interested in.
|
||||
* Additionally, the command we're interested in may include additional data
|
||||
* that we're not interested in. Therefore, this function simply asserts that
|
||||
* one of the commands in $haystack contains all of the keys and values in
|
||||
* $needle. Furthermore, if $needle contains a 'settings' key with an array
|
||||
* value, we simply assert that all keys and values within that array are
|
||||
* present in the command we're checking, and do not consider it a failure if
|
||||
* the actual command contains additional settings that aren't part of
|
||||
* $needle.
|
||||
*
|
||||
* @param $haystack
|
||||
* An array of rendered Ajax commands returned by the server.
|
||||
* @param $needle
|
||||
* Array of info we're expecting in one of those commands.
|
||||
* @param $message
|
||||
* An assertion message.
|
||||
*/
|
||||
protected function assertCommand($haystack, $needle, $message) {
|
||||
$found = FALSE;
|
||||
foreach ($haystack as $command) {
|
||||
// If the command has additional settings that we're not testing for, do
|
||||
// not consider that a failure.
|
||||
if (isset($command['settings']) && is_array($command['settings']) && isset($needle['settings']) && is_array($needle['settings'])) {
|
||||
$command['settings'] = array_intersect_key($command['settings'], $needle['settings']);
|
||||
}
|
||||
// If the command has additional data that we're not testing for, do not
|
||||
// consider that a failure. Also, == instead of ===, because we don't
|
||||
// require the key/value pairs to be in any particular order
|
||||
// (http://php.net/manual/language.operators.array.php).
|
||||
if (array_intersect_key($command, $needle) == $needle) {
|
||||
$found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->assertTrue($found, $message);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,14 +3,13 @@
|
|||
namespace Drupal\KernelTests\Core\Asset;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Asset\AttachedAssets;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests #attached assets: attached asset libraries and JavaScript settings.
|
||||
*
|
||||
* i.e. tests:
|
||||
* I.e. tests:
|
||||
*
|
||||
* @code
|
||||
* $build['#attached']['library'] = …
|
||||
|
@ -70,7 +69,7 @@ class AttachedAssetsTest extends KernelTestBase {
|
|||
$build['#attached']['library'][] = 'core/unknown';
|
||||
$assets = AttachedAssets::createFromRenderArray($build);
|
||||
|
||||
$this->assertIdentical([], $this->assetResolver->getJsAssets($assets, FALSE)[0], 'Unknown library was not added to the page.');
|
||||
$this->assertSame([], $this->assetResolver->getJsAssets($assets, FALSE)[0], 'Unknown library was not added to the page.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -205,7 +204,7 @@ class AttachedAssetsTest extends KernelTestBase {
|
|||
$end = strrpos($rendered_js, $endToken);
|
||||
// Convert to a string, as $renderer_js is a \Drupal\Core\Render\Markup
|
||||
// object.
|
||||
$json = Unicode::substr($rendered_js, $start, $end - $start + 1);
|
||||
$json = mb_substr($rendered_js, $start, $end - $start + 1);
|
||||
$parsed_settings = Json::decode($json);
|
||||
|
||||
// Test whether the settings for core/drupalSettings are available.
|
||||
|
@ -299,7 +298,8 @@ class AttachedAssetsTest extends KernelTestBase {
|
|||
"-8_2",
|
||||
"-8_3",
|
||||
"-8_4",
|
||||
"-5_1", // The external script.
|
||||
// The external script.
|
||||
"-5_1",
|
||||
"-3_1",
|
||||
"-3_2",
|
||||
"0_1",
|
||||
|
@ -435,12 +435,12 @@ class AttachedAssetsTest extends KernelTestBase {
|
|||
$dynamic_library = $library_discovery->getLibraryByName('common_test', 'dynamic_library');
|
||||
$this->assertTrue(is_array($dynamic_library));
|
||||
if ($this->assertTrue(isset($dynamic_library['version']))) {
|
||||
$this->assertIdentical('1.0', $dynamic_library['version']);
|
||||
$this->assertSame('1.0', $dynamic_library['version']);
|
||||
}
|
||||
// Make sure the dynamic library definition could be altered.
|
||||
// @see common_test_library_info_alter()
|
||||
if ($this->assertTrue(isset($dynamic_library['dependencies']))) {
|
||||
$this->assertIdentical(['core/jquery'], $dynamic_library['dependencies']);
|
||||
$this->assertSame(['core/jquery'], $dynamic_library['dependencies']);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,10 @@ class ResolvedLibraryDefinitionsFilesMatchTest extends KernelTestBase {
|
|||
}
|
||||
return TRUE;
|
||||
});
|
||||
// Remove demo_umami_content module as its install hook creates content
|
||||
// that relies on the presence of entity tables and various other elements
|
||||
// not present in a kernel test.
|
||||
unset($all_modules['demo_umami_content']);
|
||||
$this->allModules = array_keys($all_modules);
|
||||
$this->allModules[] = 'system';
|
||||
sort($this->allModules);
|
||||
|
@ -145,7 +149,6 @@ class ResolvedLibraryDefinitionsFilesMatchTest extends KernelTestBase {
|
|||
* so on.
|
||||
*/
|
||||
protected function verifyLibraryFilesExist($library_definitions) {
|
||||
$root = \Drupal::root();
|
||||
foreach ($library_definitions as $extension => $libraries) {
|
||||
foreach ($libraries as $library_name => $library) {
|
||||
if (in_array("$extension/$library_name", $this->librariesToSkip)) {
|
||||
|
@ -156,7 +159,7 @@ class ResolvedLibraryDefinitionsFilesMatchTest extends KernelTestBase {
|
|||
foreach (['css', 'js'] as $asset_type) {
|
||||
foreach ($library[$asset_type] as $asset) {
|
||||
$file = $asset['data'];
|
||||
$path = $root . '/' . $file;
|
||||
$path = $this->root . '/' . $file;
|
||||
// Only check and assert each file path once.
|
||||
if (!isset($this->pathsChecked[$path])) {
|
||||
$this->assertTrue(is_file($path), "$file file referenced from the $extension/$library_name library exists.");
|
||||
|
@ -188,10 +191,9 @@ class ResolvedLibraryDefinitionsFilesMatchTest extends KernelTestBase {
|
|||
|
||||
$libraries['core'] = $this->libraryDiscovery->getLibrariesByExtension('core');
|
||||
|
||||
$root = \Drupal::root();
|
||||
foreach ($extensions as $extension_name => $extension) {
|
||||
$library_file = $extension->getPath() . '/' . $extension_name . '.libraries.yml';
|
||||
if (is_file($root . '/' . $library_file)) {
|
||||
if (is_file($this->root . '/' . $library_file)) {
|
||||
$libraries[$extension_name] = $this->libraryDiscovery->getLibrariesByExtension($extension_name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Batch;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests batch functionality.
|
||||
*
|
||||
* @group Batch
|
||||
*/
|
||||
class BatchKernelTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
require_once $this->root . '/core/includes/batch.inc';
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests _batch_needs_update().
|
||||
*/
|
||||
public function testNeedsUpdate() {
|
||||
// Before ever being called, the return value should be FALSE.
|
||||
$this->assertEquals(FALSE, _batch_needs_update());
|
||||
|
||||
// Set the value to TRUE.
|
||||
$this->assertEquals(TRUE, _batch_needs_update(TRUE));
|
||||
// Check that without a parameter TRUE is returned.
|
||||
$this->assertEquals(TRUE, _batch_needs_update());
|
||||
|
||||
// Set the value to FALSE.
|
||||
$this->assertEquals(FALSE, _batch_needs_update(FALSE));
|
||||
$this->assertEquals(FALSE, _batch_needs_update());
|
||||
}
|
||||
|
||||
}
|
|
@ -49,21 +49,24 @@ class GetFilenameTest extends KernelTestBase {
|
|||
// a fixed location and naming.
|
||||
$this->assertIdentical(drupal_get_filename('profile', 'testing'), 'core/profiles/testing/testing.info.yml');
|
||||
|
||||
|
||||
// Generate a non-existing module name.
|
||||
$non_existing_module = uniqid("", TRUE);
|
||||
|
||||
// Set a custom error handler so we can ignore the file not found error.
|
||||
set_error_handler(function($severity, $message, $file, $line) {
|
||||
set_error_handler(function ($severity, $message, $file, $line) {
|
||||
// Skip error handling if this is a "file not found" error.
|
||||
if (strstr($message, 'is missing from the file system:')) {
|
||||
\Drupal::state()->set('get_filename_test_triggered_error', TRUE);
|
||||
\Drupal::state()->set('get_filename_test_triggered_error', $message);
|
||||
return;
|
||||
}
|
||||
throw new \ErrorException($message, 0, $severity, $file, $line);
|
||||
});
|
||||
$this->assertNull(drupal_get_filename('module', $non_existing_module), 'Searching for an item that does not exist returns NULL.');
|
||||
$this->assertTrue(\Drupal::state()->get('get_filename_test_triggered_error'), 'Searching for an item that does not exist triggers an error.');
|
||||
$this->assertNull(drupal_get_filename('module', 'there_is_a_module_for_that'), 'Searching for an item that does not exist returns NULL.');
|
||||
$this->assertEquals('The following module is missing from the file system: there_is_a_module_for_that', \Drupal::state()->get('get_filename_test_triggered_error'));
|
||||
|
||||
$this->assertNull(drupal_get_filename('theme', 'there_is_a_theme_for_you'), 'Searching for an item that does not exist returns NULL.');
|
||||
$this->assertEquals('The following theme is missing from the file system: there_is_a_theme_for_you', \Drupal::state()->get('get_filename_test_triggered_error'));
|
||||
|
||||
$this->assertNull(drupal_get_filename('profile', 'there_is_an_install_profile_for_you'), 'Searching for an item that does not exist returns NULL.');
|
||||
$this->assertEquals('The following profile is missing from the file system: there_is_an_install_profile_for_you', \Drupal::state()->get('get_filename_test_triggered_error'));
|
||||
|
||||
// Restore the original error handler.
|
||||
restore_error_handler();
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ class ChainedFastBackendTest extends GenericCacheBackendUnitTestBase {
|
|||
* A new ChainedFastBackend object.
|
||||
*/
|
||||
protected function createCacheBackend($bin) {
|
||||
$consistent_backend = new DatabaseBackend(\Drupal::service('database'), \Drupal::service('cache_tags.invalidator.checksum'), $bin);
|
||||
$consistent_backend = new DatabaseBackend(\Drupal::service('database'), \Drupal::service('cache_tags.invalidator.checksum'), $bin, 100);
|
||||
$fast_backend = new PhpBackend($bin, \Drupal::service('cache_tags.invalidator.checksum'));
|
||||
$backend = new ChainedFastBackend($consistent_backend, $fast_backend, $bin);
|
||||
// Explicitly register the cache bin as it can not work through the
|
||||
|
|
|
@ -11,6 +11,13 @@ use Drupal\Core\Cache\DatabaseBackend;
|
|||
*/
|
||||
class DatabaseBackendTest extends GenericCacheBackendUnitTestBase {
|
||||
|
||||
/**
|
||||
* The max rows to use for test bins.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $maxRows = 100;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
|
@ -25,7 +32,7 @@ class DatabaseBackendTest extends GenericCacheBackendUnitTestBase {
|
|||
* A new DatabaseBackend object.
|
||||
*/
|
||||
protected function createCacheBackend($bin) {
|
||||
return new DatabaseBackend($this->container->get('database'), $this->container->get('cache_tags.invalidator.checksum'), $bin);
|
||||
return new DatabaseBackend($this->container->get('database'), $this->container->get('cache_tags.invalidator.checksum'), $bin, static::$maxRows);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,12 +47,60 @@ class DatabaseBackendTest extends GenericCacheBackendUnitTestBase {
|
|||
$cid_long = str_repeat('愛€', 500);
|
||||
$cached_value_long = $this->randomMachineName();
|
||||
$backend->set($cid_long, $cached_value_long);
|
||||
$this->assertIdentical($cached_value_long, $backend->get($cid_long)->data, "Backend contains the correct value for long, non-ASCII cache id.");
|
||||
$this->assertSame($cached_value_long, $backend->get($cid_long)->data, "Backend contains the correct value for long, non-ASCII cache id.");
|
||||
|
||||
$cid_short = '愛1€';
|
||||
$cached_value_short = $this->randomMachineName();
|
||||
$backend->set($cid_short, $cached_value_short);
|
||||
$this->assertIdentical($cached_value_short, $backend->get($cid_short)->data, "Backend contains the correct value for short, non-ASCII cache id.");
|
||||
$this->assertSame($cached_value_short, $backend->get($cid_short)->data, "Backend contains the correct value for short, non-ASCII cache id.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the row count limiting of cache bin database tables.
|
||||
*/
|
||||
public function testGarbageCollection() {
|
||||
$backend = $this->getCacheBackend();
|
||||
$max_rows = static::$maxRows;
|
||||
|
||||
$this->assertSame(0, (int) $this->getNumRows());
|
||||
|
||||
// Fill to just the limit.
|
||||
for ($i = 0; $i < $max_rows; $i++) {
|
||||
// Ensure that each cache item created happens in a different millisecond,
|
||||
// by waiting 1 ms (1000 microseconds). The garbage collection might
|
||||
// otherwise keep less than exactly 100 records (which is acceptable for
|
||||
// real-world cases, but not for this test).
|
||||
usleep(1000);
|
||||
$backend->set("test$i", $i);
|
||||
}
|
||||
$this->assertSame($max_rows, $this->getNumRows());
|
||||
|
||||
// Garbage collection has no effect.
|
||||
$backend->garbageCollection();
|
||||
$this->assertSame($max_rows, $this->getNumRows());
|
||||
|
||||
// Go one row beyond the limit.
|
||||
$backend->set('test' . ($max_rows + 1), $max_rows + 1);
|
||||
$this->assertSame($max_rows + 1, $this->getNumRows());
|
||||
|
||||
// Garbage collection removes one row: the oldest.
|
||||
$backend->garbageCollection();
|
||||
$this->assertSame($max_rows, $this->getNumRows());
|
||||
$this->assertFalse($backend->get('test0'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of rows in the test cache bin database table.
|
||||
*
|
||||
* @return int
|
||||
* The number of rows in the test cache bin database table.
|
||||
*/
|
||||
protected function getNumRows() {
|
||||
$table = 'cache_' . $this->testBin;
|
||||
$connection = $this->container->get('database');
|
||||
$query = $connection->select($table);
|
||||
$query->addExpression('COUNT(cid)', 'cid');
|
||||
return (int) $query->execute()->fetchField();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
|
|||
* @return \Drupal\Core\Cache\CacheBackendInterface
|
||||
* Cache backend to test.
|
||||
*/
|
||||
protected abstract function createCacheBackend($bin);
|
||||
abstract protected function createCacheBackend($bin);
|
||||
|
||||
/**
|
||||
* Allows specific implementation to change the environment before a test run.
|
||||
|
@ -130,22 +130,22 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
|
|||
public function testSetGet() {
|
||||
$backend = $this->getCacheBackend();
|
||||
|
||||
$this->assertIdentical(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1.");
|
||||
$this->assertSame(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1.");
|
||||
$with_backslash = ['foo' => '\Drupal\foo\Bar'];
|
||||
$backend->set('test1', $with_backslash);
|
||||
$cached = $backend->get('test1');
|
||||
$this->assert(is_object($cached), "Backend returned an object for cache id test1.");
|
||||
$this->assertIdentical($with_backslash, $cached->data);
|
||||
$this->assertSame($with_backslash, $cached->data);
|
||||
$this->assertTrue($cached->valid, 'Item is marked as valid.');
|
||||
// We need to round because microtime may be rounded up in the backend.
|
||||
$this->assertTrue($cached->created >= REQUEST_TIME && $cached->created <= round(microtime(TRUE), 3), 'Created time is correct.');
|
||||
$this->assertEqual($cached->expire, Cache::PERMANENT, 'Expire time is correct.');
|
||||
|
||||
$this->assertIdentical(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2.");
|
||||
$this->assertSame(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2.");
|
||||
$backend->set('test2', ['value' => 3], REQUEST_TIME + 3);
|
||||
$cached = $backend->get('test2');
|
||||
$this->assert(is_object($cached), "Backend returned an object for cache id test2.");
|
||||
$this->assertIdentical(['value' => 3], $cached->data);
|
||||
$this->assertSame(['value' => 3], $cached->data);
|
||||
$this->assertTrue($cached->valid, 'Item is marked as valid.');
|
||||
$this->assertTrue($cached->created >= REQUEST_TIME && $cached->created <= round(microtime(TRUE), 3), 'Created time is correct.');
|
||||
$this->assertEqual($cached->expire, REQUEST_TIME + 3, 'Expire time is correct.');
|
||||
|
@ -158,22 +158,22 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
|
|||
$this->assertTrue($cached->created >= REQUEST_TIME && $cached->created <= round(microtime(TRUE), 3), 'Created time is correct.');
|
||||
$this->assertEqual($cached->expire, REQUEST_TIME - 3, 'Expire time is correct.');
|
||||
|
||||
$this->assertIdentical(FALSE, $backend->get('test4'), "Backend does not contain data for cache id test4.");
|
||||
$this->assertSame(FALSE, $backend->get('test4'), "Backend does not contain data for cache id test4.");
|
||||
$with_eof = ['foo' => "\nEOF\ndata"];
|
||||
$backend->set('test4', $with_eof);
|
||||
$cached = $backend->get('test4');
|
||||
$this->assert(is_object($cached), "Backend returned an object for cache id test4.");
|
||||
$this->assertIdentical($with_eof, $cached->data);
|
||||
$this->assertSame($with_eof, $cached->data);
|
||||
$this->assertTrue($cached->valid, 'Item is marked as valid.');
|
||||
$this->assertTrue($cached->created >= REQUEST_TIME && $cached->created <= round(microtime(TRUE), 3), 'Created time is correct.');
|
||||
$this->assertEqual($cached->expire, Cache::PERMANENT, 'Expire time is correct.');
|
||||
|
||||
$this->assertIdentical(FALSE, $backend->get('test5'), "Backend does not contain data for cache id test5.");
|
||||
$this->assertSame(FALSE, $backend->get('test5'), "Backend does not contain data for cache id test5.");
|
||||
$with_eof_and_semicolon = ['foo' => "\nEOF;\ndata"];
|
||||
$backend->set('test5', $with_eof_and_semicolon);
|
||||
$cached = $backend->get('test5');
|
||||
$this->assert(is_object($cached), "Backend returned an object for cache id test5.");
|
||||
$this->assertIdentical($with_eof_and_semicolon, $cached->data);
|
||||
$this->assertSame($with_eof_and_semicolon, $cached->data);
|
||||
$this->assertTrue($cached->valid, 'Item is marked as valid.');
|
||||
$this->assertTrue($cached->created >= REQUEST_TIME && $cached->created <= round(microtime(TRUE), 3), 'Created time is correct.');
|
||||
$this->assertEqual($cached->expire, Cache::PERMANENT, 'Expire time is correct.');
|
||||
|
@ -182,7 +182,7 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
|
|||
$backend->set('test6', $with_variable);
|
||||
$cached = $backend->get('test6');
|
||||
$this->assert(is_object($cached), "Backend returned an object for cache id test6.");
|
||||
$this->assertIdentical($with_variable, $cached->data);
|
||||
$this->assertSame($with_variable, $cached->data);
|
||||
|
||||
// Make sure that a cached object is not affected by changing the original.
|
||||
$data = new \stdClass();
|
||||
|
@ -229,26 +229,26 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
|
|||
public function testDelete() {
|
||||
$backend = $this->getCacheBackend();
|
||||
|
||||
$this->assertIdentical(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1.");
|
||||
$this->assertSame(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1.");
|
||||
$backend->set('test1', 7);
|
||||
$this->assert(is_object($backend->get('test1')), "Backend returned an object for cache id test1.");
|
||||
|
||||
$this->assertIdentical(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2.");
|
||||
$this->assertSame(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2.");
|
||||
$backend->set('test2', 3);
|
||||
$this->assert(is_object($backend->get('test2')), "Backend returned an object for cache id %cid.");
|
||||
|
||||
$backend->delete('test1');
|
||||
$this->assertIdentical(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1 after deletion.");
|
||||
$this->assertSame(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1 after deletion.");
|
||||
|
||||
$this->assert(is_object($backend->get('test2')), "Backend still has an object for cache id test2.");
|
||||
|
||||
$backend->delete('test2');
|
||||
$this->assertIdentical(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2 after deletion.");
|
||||
$this->assertSame(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2 after deletion.");
|
||||
|
||||
$long_cid = str_repeat('a', 300);
|
||||
$backend->set($long_cid, 'test');
|
||||
$backend->delete($long_cid);
|
||||
$this->assertIdentical(FALSE, $backend->get($long_cid), "Backend does not contain data for long cache id after deletion.");
|
||||
$this->assertSame(FALSE, $backend->get($long_cid), "Backend does not contain data for long cache id after deletion.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -275,7 +275,7 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
|
|||
foreach ($variables as $cid => $value) {
|
||||
$object = $backend->get($cid);
|
||||
$this->assert(is_object($object), sprintf("Backend returned an object for cache id %s.", $cid));
|
||||
$this->assertIdentical($value, $object->data, sprintf("Data of cached id %s kept is identical in type and value", $cid));
|
||||
$this->assertSame($value, $object->data, sprintf("Data of cached id %s kept is identical in type and value", $cid));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,9 +300,11 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
|
|||
$reference = [
|
||||
'test3',
|
||||
'test7',
|
||||
'test21', // Cid does not exist.
|
||||
// Cid does not exist.
|
||||
'test21',
|
||||
'test6',
|
||||
'test19', // Cid does not exist until added before second getMultiple().
|
||||
// Cid does not exist until added before second getMultiple().
|
||||
'test19',
|
||||
'test2',
|
||||
];
|
||||
|
||||
|
@ -440,20 +442,23 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
|
|||
$backend->set('test7', 17);
|
||||
|
||||
$backend->delete('test1');
|
||||
$backend->delete('test23'); // Nonexistent key should not cause an error.
|
||||
// Nonexistent key should not cause an error.
|
||||
$backend->delete('test23');
|
||||
$backend->deleteMultiple([
|
||||
'test3',
|
||||
'test5',
|
||||
'test7',
|
||||
'test19', // Nonexistent key should not cause an error.
|
||||
'test21', // Nonexistent key should not cause an error.
|
||||
// Nonexistent key should not cause an error.
|
||||
'test19',
|
||||
// Nonexistent key should not cause an error.
|
||||
'test21',
|
||||
]);
|
||||
|
||||
// Test if expected keys have been deleted.
|
||||
$this->assertIdentical(FALSE, $backend->get('test1'), "Cache id test1 deleted.");
|
||||
$this->assertIdentical(FALSE, $backend->get('test3'), "Cache id test3 deleted.");
|
||||
$this->assertIdentical(FALSE, $backend->get('test5'), "Cache id test5 deleted.");
|
||||
$this->assertIdentical(FALSE, $backend->get('test7'), "Cache id test7 deleted.");
|
||||
$this->assertSame(FALSE, $backend->get('test1'), "Cache id test1 deleted.");
|
||||
$this->assertSame(FALSE, $backend->get('test3'), "Cache id test3 deleted.");
|
||||
$this->assertSame(FALSE, $backend->get('test5'), "Cache id test5 deleted.");
|
||||
$this->assertSame(FALSE, $backend->get('test7'), "Cache id test7 deleted.");
|
||||
|
||||
// Test if expected keys exist.
|
||||
$this->assertNotIdentical(FALSE, $backend->get('test2'), "Cache id test2 exists.");
|
||||
|
@ -461,8 +466,8 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
|
|||
$this->assertNotIdentical(FALSE, $backend->get('test6'), "Cache id test6 exists.");
|
||||
|
||||
// Test if that expected keys do not exist.
|
||||
$this->assertIdentical(FALSE, $backend->get('test19'), "Cache id test19 does not exist.");
|
||||
$this->assertIdentical(FALSE, $backend->get('test21'), "Cache id test21 does not exist.");
|
||||
$this->assertSame(FALSE, $backend->get('test19'), "Cache id test19 does not exist.");
|
||||
$this->assertSame(FALSE, $backend->get('test21'), "Cache id test21 does not exist.");
|
||||
|
||||
// Calling deleteMultiple() with an empty array should not cause an error.
|
||||
$this->assertFalse($backend->deleteMultiple([]));
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Drupal\KernelTests\Core\Command;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Command\DbDumpApplication;
|
||||
use Drupal\Core\Config\DatabaseStorage;
|
||||
use Drupal\Core\Database\Database;
|
||||
|
@ -70,7 +70,8 @@ class DbDumpTest extends KernelTestBase {
|
|||
parent::register($container);
|
||||
$container->register('cache_factory', 'Drupal\Core\Cache\DatabaseBackendFactory')
|
||||
->addArgument(new Reference('database'))
|
||||
->addArgument(new Reference('cache_tags.invalidator.checksum'));
|
||||
->addArgument(new Reference('cache_tags.invalidator.checksum'))
|
||||
->addArgument(new Reference('settings'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -204,9 +205,9 @@ class DbDumpTest extends KernelTestBase {
|
|||
foreach ($this->tables as $table) {
|
||||
$this->assertTrue(Database::getConnection()
|
||||
->schema()
|
||||
->tableExists($table), SafeMarkup::format('Table @table created by the database script.', ['@table' => $table]));
|
||||
$this->assertIdentical($this->originalTableSchemas[$table], $this->getTableSchema($table), SafeMarkup::format('The schema for @table was properly restored.', ['@table' => $table]));
|
||||
$this->assertIdentical($this->originalTableIndexes[$table], $this->getTableIndexes($table), SafeMarkup::format('The indexes for @table were properly restored.', ['@table' => $table]));
|
||||
->tableExists($table), new FormattableMarkup('Table @table created by the database script.', ['@table' => $table]));
|
||||
$this->assertSame($this->originalTableSchemas[$table], $this->getTableSchema($table), new FormattableMarkup('The schema for @table was properly restored.', ['@table' => $table]));
|
||||
$this->assertSame($this->originalTableIndexes[$table], $this->getTableIndexes($table), new FormattableMarkup('The indexes for @table were properly restored.', ['@table' => $table]));
|
||||
}
|
||||
|
||||
// Ensure the test config has been replaced.
|
||||
|
|
|
@ -6,12 +6,16 @@ use Drupal\KernelTests\KernelTestBase;
|
|||
|
||||
/**
|
||||
* @covers ::drupal_set_message
|
||||
* @group PHPUnit
|
||||
* @group Common
|
||||
* @group legacy
|
||||
*/
|
||||
class DrupalSetMessageTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* The basic functionality of drupal_set_message().
|
||||
*
|
||||
* @expectedDeprecation drupal_set_message() is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\Messenger\MessengerInterface::addMessage() instead. See https://www.drupal.org/node/2774931
|
||||
* @expectedDeprecation drupal_get_message() is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\Messenger\MessengerInterface::all() or \Drupal\Core\Messenger\MessengerInterface::messagesByType() instead. See https://www.drupal.org/node/2774931
|
||||
*/
|
||||
public function testDrupalSetMessage() {
|
||||
drupal_set_message(t('A message: @foo', ['@foo' => 'bar']));
|
||||
|
@ -20,10 +24,4 @@ class DrupalSetMessageTest extends KernelTestBase {
|
|||
$this->assertEquals('A message: bar', (string) $messages['status'][0]);
|
||||
}
|
||||
|
||||
protected function tearDown() {
|
||||
// Clear session to prevent global leakage.
|
||||
unset($_SESSION['messages']);
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,58 +12,42 @@ use Drupal\KernelTests\KernelTestBase;
|
|||
* @group Common
|
||||
*/
|
||||
class SizeTest extends KernelTestBase {
|
||||
protected $exactTestCases;
|
||||
protected $roundedTestCases;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$kb = Bytes::KILOBYTE;
|
||||
$this->exactTestCases = [
|
||||
'1 byte' => 1,
|
||||
'1 KB' => $kb,
|
||||
'1 MB' => $kb * $kb,
|
||||
'1 GB' => $kb * $kb * $kb,
|
||||
'1 TB' => $kb * $kb * $kb * $kb,
|
||||
'1 PB' => $kb * $kb * $kb * $kb * $kb,
|
||||
'1 EB' => $kb * $kb * $kb * $kb * $kb * $kb,
|
||||
'1 ZB' => $kb * $kb * $kb * $kb * $kb * $kb * $kb,
|
||||
'1 YB' => $kb * $kb * $kb * $kb * $kb * $kb * $kb * $kb,
|
||||
];
|
||||
$this->roundedTestCases = [
|
||||
'2 bytes' => 2,
|
||||
'1 MB' => ($kb * $kb) - 1, // rounded to 1 MB (not 1000 or 1024 kilobyte!)
|
||||
round(3623651 / ($this->exactTestCases['1 MB']), 2) . ' MB' => 3623651, // megabytes
|
||||
round(67234178751368124 / ($this->exactTestCases['1 PB']), 2) . ' PB' => 67234178751368124, // petabytes
|
||||
round(235346823821125814962843827 / ($this->exactTestCases['1 YB']), 2) . ' YB' => 235346823821125814962843827, // yottabytes
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that format_size() returns the expected string.
|
||||
*
|
||||
* @dataProvider providerTestCommonFormatSize
|
||||
*/
|
||||
public function testCommonFormatSize() {
|
||||
foreach ([$this->exactTestCases, $this->roundedTestCases] as $test_cases) {
|
||||
foreach ($test_cases as $expected => $input) {
|
||||
$this->assertEqual(
|
||||
($result = format_size($input, NULL)),
|
||||
$expected,
|
||||
$expected . ' == ' . $result . ' (' . $input . ' bytes)'
|
||||
);
|
||||
}
|
||||
}
|
||||
public function testCommonFormatSize($expected, $input) {
|
||||
$size = format_size($input, NULL);
|
||||
$this->assertEquals($expected, $size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross-tests Bytes::toInt() and format_size().
|
||||
* Provides a list of byte size to test.
|
||||
*/
|
||||
public function testCommonParseSizeFormatSize() {
|
||||
foreach ($this->exactTestCases as $size) {
|
||||
$this->assertEqual(
|
||||
$size,
|
||||
($parsed_size = Bytes::toInt($string = format_size($size, NULL))),
|
||||
$size . ' == ' . $parsed_size . ' (' . $string . ')'
|
||||
);
|
||||
}
|
||||
public function providerTestCommonFormatSize() {
|
||||
$kb = Bytes::KILOBYTE;
|
||||
return [
|
||||
['1 byte', 1],
|
||||
['2 bytes', 2],
|
||||
['1 KB', $kb],
|
||||
['1 MB', pow($kb, 2)],
|
||||
['1 GB', pow($kb, 3)],
|
||||
['1 TB', pow($kb, 4)],
|
||||
['1 PB', pow($kb, 5)],
|
||||
['1 EB', pow($kb, 6)],
|
||||
['1 ZB', pow($kb, 7)],
|
||||
['1 YB', pow($kb, 8)],
|
||||
// Rounded to 1 MB - not 1000 or 1024 kilobyte
|
||||
['1 MB', ($kb * $kb) - 1],
|
||||
// Decimal Megabytes
|
||||
['3.46 MB', 3623651],
|
||||
// Decimal Petabytes
|
||||
['59.72 PB', 67234178751368124],
|
||||
// Decimal Yottabytes
|
||||
['194.67 YB', 235346823821125814962843827],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class CacheabilityMetadataConfigOverrideTest extends KernelTestBase {
|
|||
'config',
|
||||
'config_override_test',
|
||||
'system',
|
||||
'user'
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace Drupal\KernelTests\Core\Config;
|
||||
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Config\ConfigNameException;
|
||||
use Drupal\Core\Config\ConfigValueException;
|
||||
use Drupal\Core\Config\InstallStorage;
|
||||
|
@ -278,12 +278,12 @@ class ConfigCRUDTest extends KernelTestBase {
|
|||
$this->assertIdentical($storage->read($name), $data);
|
||||
|
||||
// Test that schema type enforcement can be overridden by trusting the data.
|
||||
$this->assertIdentical(99, $config->get('int'));
|
||||
$this->assertSame(99, $config->get('int'));
|
||||
$config->set('int', '99')->save(TRUE);
|
||||
$this->assertIdentical('99', $config->get('int'));
|
||||
$this->assertSame('99', $config->get('int'));
|
||||
// Test that re-saving without testing the data enforces the schema type.
|
||||
$config->save();
|
||||
$this->assertIdentical($data, $config->get());
|
||||
$this->assertSame($data, $config->get());
|
||||
|
||||
// Test that setting an unsupported type for a config object with a schema
|
||||
// fails.
|
||||
|
@ -292,7 +292,7 @@ class ConfigCRUDTest extends KernelTestBase {
|
|||
$this->fail('No Exception thrown upon saving invalid data type.');
|
||||
}
|
||||
catch (UnsupportedDataTypeConfigException $e) {
|
||||
$this->pass(SafeMarkup::format('%class thrown upon saving invalid data type.', [
|
||||
$this->pass(new FormattableMarkup('%class thrown upon saving invalid data type.', [
|
||||
'%class' => get_class($e),
|
||||
]));
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ class ConfigCRUDTest extends KernelTestBase {
|
|||
$this->fail('No Exception thrown upon saving invalid data type.');
|
||||
}
|
||||
catch (UnsupportedDataTypeConfigException $e) {
|
||||
$this->pass(SafeMarkup::format('%class thrown upon saving invalid data type.', [
|
||||
$this->pass(new FormattableMarkup('%class thrown upon saving invalid data type.', [
|
||||
'%class' => get_class($e),
|
||||
]));
|
||||
}
|
||||
|
|
|
@ -50,9 +50,9 @@ class ConfigDependencyTest extends EntityKernelTestBase {
|
|||
'id' => 'entity1',
|
||||
'dependencies' => [
|
||||
'enforced' => [
|
||||
'module' => ['node']
|
||||
]
|
||||
]
|
||||
'module' => ['node'],
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
$entity1->save();
|
||||
|
@ -161,11 +161,13 @@ class ConfigDependencyTest extends EntityKernelTestBase {
|
|||
$missing_dependencies = $config_manager->findMissingContentDependencies();
|
||||
$this->assertEqual([], $missing_dependencies);
|
||||
|
||||
$expected = [$entity_test->uuid() => [
|
||||
'entity_type' => 'entity_test',
|
||||
'bundle' => $entity_test->bundle(),
|
||||
'uuid' => $entity_test->uuid(),
|
||||
]];
|
||||
$expected = [
|
||||
$entity_test->uuid() => [
|
||||
'entity_type' => 'entity_test',
|
||||
'bundle' => $entity_test->bundle(),
|
||||
'uuid' => $entity_test->uuid(),
|
||||
],
|
||||
];
|
||||
// Delete the content entity so that is it now missing.
|
||||
$entity_test->delete();
|
||||
$missing_dependencies = $config_manager->findMissingContentDependencies();
|
||||
|
@ -198,7 +200,7 @@ class ConfigDependencyTest extends EntityKernelTestBase {
|
|||
'id' => 'entity1',
|
||||
'dependencies' => [
|
||||
'enforced' => [
|
||||
'module' => ['node', 'config_test']
|
||||
'module' => ['node', 'config_test'],
|
||||
],
|
||||
],
|
||||
]
|
||||
|
@ -233,9 +235,9 @@ class ConfigDependencyTest extends EntityKernelTestBase {
|
|||
// Ensure that alphabetical order has no influence on dependency fixing and
|
||||
// removal.
|
||||
return [
|
||||
[['a', 'b', 'c', 'd']],
|
||||
[['d', 'c', 'b', 'a']],
|
||||
[['c', 'd', 'a', 'b']],
|
||||
[['a', 'b', 'c', 'd', 'e']],
|
||||
[['e', 'd', 'c', 'b', 'a']],
|
||||
[['e', 'c', 'd', 'a', 'b']],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -262,7 +264,7 @@ class ConfigDependencyTest extends EntityKernelTestBase {
|
|||
'id' => 'entity_' . $entity_id_suffixes[0],
|
||||
'dependencies' => [
|
||||
'enforced' => [
|
||||
'module' => ['node', 'config_test']
|
||||
'module' => ['node', 'config_test'],
|
||||
],
|
||||
],
|
||||
]
|
||||
|
@ -307,13 +309,32 @@ class ConfigDependencyTest extends EntityKernelTestBase {
|
|||
'dependencies' => [
|
||||
'enforced' => [
|
||||
'config' => [$entity_1->getConfigDependencyName()],
|
||||
'module' => ['node', 'config_test']
|
||||
'module' => ['node', 'config_test'],
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
$entity_4->save();
|
||||
|
||||
// Entity 5 will be fixed because it is dependent on entity 3, which is
|
||||
// unchanged, and entity 1 which will be fixed because
|
||||
// \Drupal\config_test\Entity::onDependencyRemoval() will remove the
|
||||
// dependency.
|
||||
$entity_5 = $storage->create(
|
||||
[
|
||||
'id' => 'entity_' . $entity_id_suffixes[4],
|
||||
'dependencies' => [
|
||||
'enforced' => [
|
||||
'config' => [
|
||||
$entity_1->getConfigDependencyName(),
|
||||
$entity_3->getConfigDependencyName(),
|
||||
],
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
$entity_5->save();
|
||||
|
||||
// Set a more complicated test where dependencies will be fixed.
|
||||
\Drupal::state()->set('config_test.fix_dependencies', [$entity_1->getConfigDependencyName()]);
|
||||
\Drupal::state()->set('config_test.on_dependency_removal_called', []);
|
||||
|
@ -321,14 +342,22 @@ class ConfigDependencyTest extends EntityKernelTestBase {
|
|||
// Do a dry run using
|
||||
// \Drupal\Core\Config\ConfigManager::getConfigEntitiesToChangeOnDependencyRemoval().
|
||||
$config_entities = $config_manager->getConfigEntitiesToChangeOnDependencyRemoval('module', ['node']);
|
||||
|
||||
// Assert that \Drupal\config_test\Entity\ConfigTest::onDependencyRemoval()
|
||||
// is called as expected and with the correct dependencies.
|
||||
$called = \Drupal::state()->get('config_test.on_dependency_removal_called', []);
|
||||
$this->assertArrayNotHasKey($entity_3->id(), $called, 'ConfigEntityInterface::onDependencyRemoval() is not called for entity 3.');
|
||||
$this->assertSame([$entity_1->id(), $entity_4->id(), $entity_2->id(), $entity_5->id()], array_keys($called), 'The most dependent entites have ConfigEntityInterface::onDependencyRemoval() called first.');
|
||||
$this->assertSame(['config' => [], 'content' => [], 'module' => ['node'], 'theme' => []], $called[$entity_1->id()]);
|
||||
$this->assertSame(['config' => [$entity_1->getConfigDependencyName()], 'content' => [], 'module' => [], 'theme' => []], $called[$entity_2->id()]);
|
||||
$this->assertSame(['config' => [$entity_1->getConfigDependencyName()], 'content' => [], 'module' => ['node'], 'theme' => []], $called[$entity_4->id()]);
|
||||
$this->assertSame(['config' => [$entity_1->getConfigDependencyName()], 'content' => [], 'module' => [], 'theme' => []], $called[$entity_5->id()]);
|
||||
|
||||
$this->assertEqual($entity_1->uuid(), $config_entities['delete'][1]->uuid(), 'Entity 1 will be deleted.');
|
||||
$this->assertEqual($entity_2->uuid(), reset($config_entities['update'])->uuid(), 'Entity 2 will be updated.');
|
||||
$this->assertEqual($entity_2->uuid(), $config_entities['update'][0]->uuid(), 'Entity 2 will be updated.');
|
||||
$this->assertEqual($entity_3->uuid(), reset($config_entities['unchanged'])->uuid(), 'Entity 3 is not changed.');
|
||||
$this->assertEqual($entity_4->uuid(), $config_entities['delete'][0]->uuid(), 'Entity 4 will be deleted.');
|
||||
|
||||
$called = \Drupal::state()->get('config_test.on_dependency_removal_called', []);
|
||||
$this->assertFalse(in_array($entity_3->id(), $called), 'ConfigEntityInterface::onDependencyRemoval() is not called for entity 3.');
|
||||
$this->assertIdentical([$entity_1->id(), $entity_4->id(), $entity_2->id()], $called, 'The most dependent entites have ConfigEntityInterface::onDependencyRemoval() called first.');
|
||||
$this->assertEqual($entity_5->uuid(), $config_entities['update'][1]->uuid(), 'Entity 5 is updated.');
|
||||
|
||||
// Perform a module rebuild so we can know where the node module is located
|
||||
// and uninstall it.
|
||||
|
@ -441,8 +470,11 @@ class ConfigDependencyTest extends EntityKernelTestBase {
|
|||
$this->assertSame($expected, $config_entity_ids);
|
||||
|
||||
$called = \Drupal::state()->get('config_test.on_dependency_removal_called', []);
|
||||
$this->assertFalse(in_array($entity_3->id(), $called), 'ConfigEntityInterface::onDependencyRemoval() is not called for entity 3.');
|
||||
$this->assertSame([$entity_1->id(), $entity_4->id(), $entity_2->id()], $called, 'The most dependent entities have ConfigEntityInterface::onDependencyRemoval() called first.');
|
||||
$this->assertArrayNotHasKey($entity_3->id(), $called, 'ConfigEntityInterface::onDependencyRemoval() is not called for entity 3.');
|
||||
$this->assertSame([$entity_1->id(), $entity_4->id(), $entity_2->id()], array_keys($called), 'The most dependent entities have ConfigEntityInterface::onDependencyRemoval() called first.');
|
||||
$this->assertSame(['config' => [], 'content' => [], 'module' => ['node'], 'theme' => []], $called[$entity_1->id()]);
|
||||
$this->assertSame(['config' => [], 'content' => [], 'module' => ['node'], 'theme' => []], $called[$entity_2->id()]);
|
||||
$this->assertSame(['config' => [], 'content' => [], 'module' => ['node'], 'theme' => []], $called[$entity_4->id()]);
|
||||
|
||||
// Perform a module rebuild so we can know where the node module is located
|
||||
// and uninstall it.
|
||||
|
@ -476,7 +508,7 @@ class ConfigDependencyTest extends EntityKernelTestBase {
|
|||
// Test dependencies between configuration entities.
|
||||
$entity1 = $storage->create(
|
||||
[
|
||||
'id' => 'entity1'
|
||||
'id' => 'entity1',
|
||||
]
|
||||
);
|
||||
$entity1->save();
|
||||
|
@ -589,7 +621,7 @@ class ConfigDependencyTest extends EntityKernelTestBase {
|
|||
'id' => 'entity1',
|
||||
'dependencies' => [
|
||||
'enforced' => [
|
||||
'content' => [$content_entity->getConfigDependencyName()]
|
||||
'content' => [$content_entity->getConfigDependencyName()],
|
||||
],
|
||||
],
|
||||
]
|
||||
|
@ -600,7 +632,7 @@ class ConfigDependencyTest extends EntityKernelTestBase {
|
|||
'id' => 'entity2',
|
||||
'dependencies' => [
|
||||
'enforced' => [
|
||||
'config' => [$entity1->getConfigDependencyName()]
|
||||
'config' => [$entity1->getConfigDependencyName()],
|
||||
],
|
||||
],
|
||||
]
|
||||
|
|
|
@ -75,7 +75,7 @@ class ConfigDiffTest extends KernelTestBase {
|
|||
|
||||
// Test diffing a renamed config entity.
|
||||
$test_entity_id = $this->randomMachineName();
|
||||
$test_entity = entity_create('config_test', [
|
||||
$test_entity = \Drupal::entityTypeManager()->getStorage('config_test')->create([
|
||||
'id' => $test_entity_id,
|
||||
'label' => $this->randomMachineName(),
|
||||
]);
|
||||
|
|
|
@ -24,14 +24,14 @@ class ConfigEntityNormalizeTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
public function testNormalize() {
|
||||
$config_entity = entity_create('config_test', ['id' => 'system', 'label' => 'foobar', 'weight' => 1]);
|
||||
$config_entity = \Drupal::entityTypeManager()->getStorage('config_test')->create(['id' => 'system', 'label' => 'foobar', 'weight' => 1]);
|
||||
$config_entity->save();
|
||||
|
||||
// Modify stored config entity, this is comparable with a schema change.
|
||||
$config = $this->config('config_test.dynamic.system');
|
||||
$data = [
|
||||
'label' => 'foobar',
|
||||
'additional_key' => TRUE
|
||||
'additional_key' => TRUE,
|
||||
] + $config->getRawData();
|
||||
$config->setData($data)->save();
|
||||
$this->assertNotIdentical($config_entity->toArray(), $config->getRawData(), 'Stored config entity is not is equivalent to config schema.');
|
||||
|
|
|
@ -57,7 +57,7 @@ class ConfigEntityStaticCacheTest extends KernelTestBase {
|
|||
// config_entity_static_cache_test_config_test_load() sets _loadStamp to a
|
||||
// random string. If they match, it means $entity_2 was retrieved from the
|
||||
// static cache rather than going through a separate load sequence.
|
||||
$this->assertIdentical($entity_1->_loadStamp, $entity_2->_loadStamp);
|
||||
$this->assertSame($entity_1->_loadStamp, $entity_2->_loadStamp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,7 @@ class ConfigEntityStatusTest extends KernelTestBase {
|
|||
* Tests the enabling/disabling of entities.
|
||||
*/
|
||||
public function testCRUD() {
|
||||
$entity = entity_create('config_test', [
|
||||
$entity = \Drupal::entityTypeManager()->getStorage('config_test')->create([
|
||||
'id' => strtolower($this->randomMachineName()),
|
||||
]);
|
||||
$this->assertTrue($entity->status(), 'Default status is enabled.');
|
||||
|
|
|
@ -51,4 +51,18 @@ class ConfigEntityStorageTest extends KernelTestBase {
|
|||
$this->assertIdentical($entity->toArray(), $original_properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the hasData() method for config entity storage.
|
||||
*
|
||||
* @covers \Drupal\Core\Config\Entity\ConfigEntityStorage::hasData
|
||||
*/
|
||||
public function testHasData() {
|
||||
$storage = \Drupal::entityTypeManager()->getStorage('config_test');
|
||||
$this->assertFalse($storage->hasData());
|
||||
|
||||
// Add a test config entity and check again.
|
||||
$storage->create(['id' => $this->randomMachineName()])->save();
|
||||
$this->assertTrue($storage->hasData());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ class ConfigEntityUnitTest extends KernelTestBase {
|
|||
// Compare UUIDs as the objects are not identical since
|
||||
// $entity->enforceIsNew is FALSE and $entity_loaded_by_uuid->enforceIsNew
|
||||
// is NULL.
|
||||
$this->assertIdentical($entity->uuid(), $entity_loaded_by_uuid->uuid());
|
||||
$this->assertSame($entity->uuid(), $entity_loaded_by_uuid->uuid());
|
||||
|
||||
$entities = $this->storage->loadByProperties();
|
||||
$this->assertEqual(count($entities), 3, 'Three entities are loaded when no properties are specified.');
|
||||
|
@ -97,15 +97,15 @@ class ConfigEntityUnitTest extends KernelTestBase {
|
|||
$entity = $this->storage->create([
|
||||
'id' => $this->randomMachineName(),
|
||||
'label' => $this->randomString(),
|
||||
'style' => 999
|
||||
'style' => 999,
|
||||
]);
|
||||
$entity->save();
|
||||
$this->assertIdentical('999', $entity->style);
|
||||
$this->assertSame('999', $entity->style);
|
||||
$entity->style = 999;
|
||||
$entity->trustData()->save();
|
||||
$this->assertIdentical(999, $entity->style);
|
||||
$this->assertSame(999, $entity->style);
|
||||
$entity->save();
|
||||
$this->assertIdentical('999', $entity->style);
|
||||
$this->assertSame('999', $entity->style);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ class ConfigFileContentTest extends KernelTestBase {
|
|||
$this->assertIdentical($config->get('null'), NULL);
|
||||
|
||||
// Read false that had been nested in an array value.
|
||||
$this->assertSame($config->get($casting_array_false_value_key), FALSE, "Nested boolean FALSE value returned FALSE.");
|
||||
$this->assertSame(FALSE, $config->get($casting_array_false_value_key), "Nested boolean FALSE value returned FALSE.");
|
||||
|
||||
// Unset a top level value.
|
||||
$config->clear($key);
|
||||
|
@ -210,22 +210,22 @@ class ConfigFileContentTest extends KernelTestBase {
|
|||
$config_parsed = $filestorage->read($name);
|
||||
|
||||
$key = 'numeric keys';
|
||||
$this->assertIdentical($config_data[$key], $config_parsed[$key]);
|
||||
$this->assertSame($config_data[$key], $config_parsed[$key]);
|
||||
|
||||
$key = 'nested keys';
|
||||
$this->assertIdentical($config_data[$key], $config_parsed[$key]);
|
||||
$this->assertSame($config_data[$key], $config_parsed[$key]);
|
||||
|
||||
$key = 'HTML';
|
||||
$this->assertIdentical($config_data['nested keys'][$key], $config_parsed['nested keys'][$key]);
|
||||
$this->assertSame($config_data['nested keys'][$key], $config_parsed['nested keys'][$key]);
|
||||
|
||||
$key = 'UTF-8';
|
||||
$this->assertIdentical($config_data['nested keys'][$key], $config_parsed['nested keys'][$key]);
|
||||
$this->assertSame($config_data['nested keys'][$key], $config_parsed['nested keys'][$key]);
|
||||
|
||||
$key = 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ';
|
||||
$this->assertIdentical($config_data['nested keys'][$key], $config_parsed['nested keys'][$key]);
|
||||
$this->assertSame($config_data['nested keys'][$key], $config_parsed['nested keys'][$key]);
|
||||
|
||||
$key = 'invalid xml';
|
||||
$this->assertIdentical($config_data[$key], $config_parsed[$key]);
|
||||
$this->assertSame($config_data[$key], $config_parsed[$key]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Drupal\KernelTests\Core\Config;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Config\ConfigImporter;
|
||||
use Drupal\Core\Config\StorageComparer;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
@ -33,7 +32,7 @@ class ConfigImportRecreateTest extends KernelTestBase {
|
|||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('node');
|
||||
$this->installConfig(['field', 'node']);
|
||||
$this->installConfig(['system', 'field', 'node']);
|
||||
|
||||
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync'));
|
||||
|
||||
|
@ -57,7 +56,7 @@ class ConfigImportRecreateTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
public function testRecreateEntity() {
|
||||
$type_name = Unicode::strtolower($this->randomMachineName(16));
|
||||
$type_name = mb_strtolower($this->randomMachineName(16));
|
||||
$content_type = NodeType::create([
|
||||
'type' => $type_name,
|
||||
'name' => 'Node type one',
|
||||
|
@ -92,7 +91,7 @@ class ConfigImportRecreateTest extends KernelTestBase {
|
|||
$this->assertEqual(5, count($creates), 'There are 5 configuration items to create.');
|
||||
$this->assertEqual(5, count($deletes), 'There are 5 configuration items to delete.');
|
||||
$this->assertEqual(0, count($this->configImporter->getUnprocessedConfiguration('update')), 'There are no configuration items to update.');
|
||||
$this->assertIdentical($creates, array_reverse($deletes), 'Deletes and creates contain the same configuration names in opposite orders due to dependencies.');
|
||||
$this->assertSame($creates, array_reverse($deletes), 'Deletes and creates contain the same configuration names in opposite orders due to dependencies.');
|
||||
|
||||
$this->configImporter->import();
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
namespace Drupal\KernelTests\Core\Config;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Component\Uuid\Php;
|
||||
use Drupal\Core\Config\ConfigImporter;
|
||||
use Drupal\Core\Config\ConfigImporterException;
|
||||
|
@ -40,7 +39,7 @@ class ConfigImportRenameValidationTest extends KernelTestBase {
|
|||
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('node');
|
||||
$this->installConfig(['field']);
|
||||
$this->installConfig(['system', 'field']);
|
||||
|
||||
// Set up the ConfigImporter object for testing.
|
||||
$storage_comparer = new StorageComparer(
|
||||
|
@ -67,7 +66,7 @@ class ConfigImportRenameValidationTest extends KernelTestBase {
|
|||
public function testRenameValidation() {
|
||||
// Create a test entity.
|
||||
$test_entity_id = $this->randomMachineName();
|
||||
$test_entity = entity_create('config_test', [
|
||||
$test_entity = \Drupal::entityTypeManager()->getStorage('config_test')->create([
|
||||
'id' => $test_entity_id,
|
||||
'label' => $this->randomMachineName(),
|
||||
]);
|
||||
|
@ -82,7 +81,7 @@ class ConfigImportRenameValidationTest extends KernelTestBase {
|
|||
|
||||
// Create a content type with a matching UUID in the active storage.
|
||||
$content_type = NodeType::create([
|
||||
'type' => Unicode::strtolower($this->randomMachineName(16)),
|
||||
'type' => mb_strtolower($this->randomMachineName(16)),
|
||||
'name' => $this->randomMachineName(),
|
||||
'uuid' => $uuid,
|
||||
]);
|
||||
|
@ -95,7 +94,7 @@ class ConfigImportRenameValidationTest extends KernelTestBase {
|
|||
'node.type.' . $content_type->id() . '::config_test.dynamic.' . $test_entity_id,
|
||||
];
|
||||
$renames = $this->configImporter->getUnprocessedConfiguration('rename');
|
||||
$this->assertIdentical($expected, $renames);
|
||||
$this->assertSame($expected, $renames);
|
||||
|
||||
// Try to import the configuration. We expect an exception to be thrown
|
||||
// because the staged entity is of a different type.
|
||||
|
@ -106,7 +105,7 @@ class ConfigImportRenameValidationTest extends KernelTestBase {
|
|||
catch (ConfigImporterException $e) {
|
||||
$this->pass('Expected ConfigImporterException thrown when a renamed configuration entity does not match the existing entity type.');
|
||||
$expected = [
|
||||
SafeMarkup::format('Entity type mismatch on rename. @old_type not equal to @new_type for existing configuration @old_name and staged configuration @new_name.', ['@old_type' => 'node_type', '@new_type' => 'config_test', '@old_name' => 'node.type.' . $content_type->id(), '@new_name' => 'config_test.dynamic.' . $test_entity_id])
|
||||
new FormattableMarkup('Entity type mismatch on rename. @old_type not equal to @new_type for existing configuration @old_name and staged configuration @new_name.', ['@old_type' => 'node_type', '@new_type' => 'config_test', '@old_name' => 'node.type.' . $content_type->id(), '@new_name' => 'config_test.dynamic.' . $test_entity_id]),
|
||||
];
|
||||
$this->assertEqual($expected, $this->configImporter->getErrors());
|
||||
}
|
||||
|
@ -135,10 +134,10 @@ class ConfigImportRenameValidationTest extends KernelTestBase {
|
|||
// UUIDs match.
|
||||
$this->configImporter->reset();
|
||||
$expected = [
|
||||
'config_test.old::config_test.new'
|
||||
'config_test.old::config_test.new',
|
||||
];
|
||||
$renames = $this->configImporter->getUnprocessedConfiguration('rename');
|
||||
$this->assertIdentical($expected, $renames);
|
||||
$this->assertSame($expected, $renames);
|
||||
|
||||
// Try to import the configuration. We expect an exception to be thrown
|
||||
// because the rename is for simple configuration.
|
||||
|
@ -149,7 +148,7 @@ class ConfigImportRenameValidationTest extends KernelTestBase {
|
|||
catch (ConfigImporterException $e) {
|
||||
$this->pass('Expected ConfigImporterException thrown when simple configuration is renamed.');
|
||||
$expected = [
|
||||
SafeMarkup::format('Rename operation for simple configuration. Existing configuration @old_name and staged configuration @new_name.', ['@old_name' => 'config_test.old', '@new_name' => 'config_test.new'])
|
||||
new FormattableMarkup('Rename operation for simple configuration. Existing configuration @old_name and staged configuration @new_name.', ['@old_name' => 'config_test.old', '@new_name' => 'config_test.new']),
|
||||
];
|
||||
$this->assertEqual($expected, $this->configImporter->getErrors());
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class ConfigImporterMissingContentTest extends KernelTestBase {
|
|||
$this->installSchema('system', 'sequences');
|
||||
$this->installEntitySchema('entity_test');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installConfig(['config_test']);
|
||||
$this->installConfig(['system', 'config_test']);
|
||||
// Installing config_test's default configuration pollutes the global
|
||||
// variable being used for recording hook invocations by this test already,
|
||||
// so it has to be cleared out manually.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace Drupal\KernelTests\Core\Config;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Config\ConfigImporter;
|
||||
use Drupal\Core\Config\ConfigImporterException;
|
||||
use Drupal\Core\Config\StorageComparer;
|
||||
|
@ -16,6 +16,11 @@ use Drupal\KernelTests\KernelTestBase;
|
|||
*/
|
||||
class ConfigImporterTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* The beginning of an import validation error.
|
||||
*/
|
||||
const FAIL_MESSAGE = 'There were errors validating the config synchronization.';
|
||||
|
||||
/**
|
||||
* Config Importer object used for testing.
|
||||
*
|
||||
|
@ -33,7 +38,7 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installConfig(['config_test']);
|
||||
$this->installConfig(['system', 'config_test']);
|
||||
// Installing config_test's default configuration pollutes the global
|
||||
// variable being used for recording hook invocations by this test already,
|
||||
// so it has to be cleared out manually.
|
||||
|
@ -104,10 +109,17 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
$this->fail('ConfigImporterException not thrown, invalid import was not stopped due to mis-matching site UUID.');
|
||||
}
|
||||
catch (ConfigImporterException $e) {
|
||||
$this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.');
|
||||
$error_log = $this->configImporter->getErrors();
|
||||
$expected = ['Site UUID in source storage does not match the target storage.'];
|
||||
$this->assertEqual($expected, $error_log);
|
||||
$actual_message = $e->getMessage();
|
||||
|
||||
$actual_error_log = $this->configImporter->getErrors();
|
||||
$expected_error_log = ['Site UUID in source storage does not match the target storage.'];
|
||||
$this->assertEqual($actual_error_log, $expected_error_log);
|
||||
|
||||
$expected = static::FAIL_MESSAGE . PHP_EOL . 'Site UUID in source storage does not match the target storage.';
|
||||
$this->assertEquals($expected, $actual_message);
|
||||
foreach ($expected_error_log as $log_row) {
|
||||
$this->assertTrue(preg_match("/$log_row/", $actual_message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,7 +238,7 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
// Add a dependency on primary, to ensure that is synced first.
|
||||
'dependencies' => [
|
||||
'config' => [$name_primary],
|
||||
]
|
||||
],
|
||||
];
|
||||
$sync->write($name_secondary, $values_secondary);
|
||||
|
||||
|
@ -245,7 +257,7 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
|
||||
$logs = $this->configImporter->getErrors();
|
||||
$this->assertEqual(count($logs), 1);
|
||||
$this->assertEqual($logs[0], SafeMarkup::format('Deleted and replaced configuration entity "@name"', ['@name' => $name_secondary]));
|
||||
$this->assertEqual($logs[0], new FormattableMarkup('Deleted and replaced configuration entity "@name"', ['@name' => $name_secondary]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -265,7 +277,7 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
// Add a dependency on secondary, so that is synced first.
|
||||
'dependencies' => [
|
||||
'config' => [$name_secondary],
|
||||
]
|
||||
],
|
||||
];
|
||||
$sync->write($name_primary, $values_primary);
|
||||
$values_secondary = [
|
||||
|
@ -322,7 +334,7 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
// Add a dependency on deleter, to make sure that is synced first.
|
||||
'dependencies' => [
|
||||
'config' => [$name_deleter],
|
||||
]
|
||||
],
|
||||
];
|
||||
$storage->write($name_deletee, $values_deletee);
|
||||
$values_deletee['label'] = 'Updated Deletee';
|
||||
|
@ -338,7 +350,7 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
// will also be synced after the deletee due to alphabetical ordering.
|
||||
'dependencies' => [
|
||||
'config' => [$name_deleter],
|
||||
]
|
||||
],
|
||||
];
|
||||
$storage->write($name_other, $values_other);
|
||||
$values_other['label'] = 'Updated other';
|
||||
|
@ -351,7 +363,7 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
$name_deletee,
|
||||
$name_other,
|
||||
];
|
||||
$this->assertIdentical($expected, $updates);
|
||||
$this->assertSame($expected, $updates);
|
||||
|
||||
// Import.
|
||||
$this->configImporter->import();
|
||||
|
@ -373,7 +385,7 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
|
||||
$logs = $this->configImporter->getErrors();
|
||||
$this->assertEqual(count($logs), 1);
|
||||
$this->assertEqual($logs[0], SafeMarkup::format('Update target "@name" is missing.', ['@name' => $name_deletee]));
|
||||
$this->assertEqual($logs[0], new FormattableMarkup('Update target "@name" is missing.', ['@name' => $name_deletee]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -580,7 +592,20 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
$this->fail('ConfigImporterException not thrown; an invalid import was not stopped due to missing dependencies.');
|
||||
}
|
||||
catch (ConfigImporterException $e) {
|
||||
$this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.');
|
||||
$expected = [
|
||||
static::FAIL_MESSAGE,
|
||||
'Unable to install the <em class="placeholder">unknown_module</em> module since it does not exist.',
|
||||
'Unable to install the <em class="placeholder">Book</em> module since it requires the <em class="placeholder">Node, Text, Field, Filter, User</em> modules.',
|
||||
'Unable to install the <em class="placeholder">unknown_theme</em> theme since it does not exist.',
|
||||
'Unable to install the <em class="placeholder">Bartik</em> theme since it requires the <em class="placeholder">Classy</em> theme.',
|
||||
'Unable to install the <em class="placeholder">Bartik</em> theme since it requires the <em class="placeholder">Stable</em> theme.',
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.config</em> depends on the <em class="placeholder">unknown</em> configuration that will not exist after import.',
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.existing</em> depends on the <em class="placeholder">config_test.dynamic.dotted.deleted</em> configuration that will not exist after import.',
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.module</em> depends on the <em class="placeholder">unknown</em> module that will not be installed after import.',
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.theme</em> depends on the <em class="placeholder">unknown</em> theme that will not be installed after import.',
|
||||
'Configuration <em class="placeholder">unknown.config</em> depends on the <em class="placeholder">unknown</em> extension that will not be installed after import.',
|
||||
];
|
||||
$this->assertEquals(implode(PHP_EOL, $expected), $e->getMessage());
|
||||
$error_log = $this->configImporter->getErrors();
|
||||
$expected = [
|
||||
'Unable to install the <em class="placeholder">unknown_module</em> module since it does not exist.',
|
||||
|
@ -598,7 +623,7 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
// Make a config entity have mulitple unmet dependencies.
|
||||
// Make a config entity have multiple unmet dependencies.
|
||||
$config_entity_data = $sync->read('config_test.dynamic.dotted.default');
|
||||
$config_entity_data['dependencies'] = ['module' => ['unknown', 'dblog']];
|
||||
$sync->write('config_test.dynamic.dotted.module', $config_entity_data);
|
||||
|
@ -611,7 +636,30 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
$this->fail('ConfigImporterException not thrown, invalid import was not stopped due to missing dependencies.');
|
||||
}
|
||||
catch (ConfigImporterException $e) {
|
||||
$this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.');
|
||||
$expected = [
|
||||
static::FAIL_MESSAGE,
|
||||
'Unable to install the <em class="placeholder">unknown_module</em> module since it does not exist.',
|
||||
'Unable to install the <em class="placeholder">Book</em> module since it requires the <em class="placeholder">Node, Text, Field, Filter, User</em> modules.',
|
||||
'Unable to install the <em class="placeholder">unknown_theme</em> theme since it does not exist.',
|
||||
'Unable to install the <em class="placeholder">Bartik</em> theme since it requires the <em class="placeholder">Classy</em> theme.',
|
||||
'Unable to install the <em class="placeholder">Bartik</em> theme since it requires the <em class="placeholder">Stable</em> theme.',
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.config</em> depends on the <em class="placeholder">unknown</em> configuration that will not exist after import.',
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.existing</em> depends on the <em class="placeholder">config_test.dynamic.dotted.deleted</em> configuration that will not exist after import.',
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.module</em> depends on the <em class="placeholder">unknown</em> module that will not be installed after import.',
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.theme</em> depends on the <em class="placeholder">unknown</em> theme that will not be installed after import.',
|
||||
'Configuration <em class="placeholder">unknown.config</em> depends on the <em class="placeholder">unknown</em> extension that will not be installed after import.',
|
||||
'Unable to install the <em class="placeholder">unknown_module</em> module since it does not exist.',
|
||||
'Unable to install the <em class="placeholder">Book</em> module since it requires the <em class="placeholder">Node, Text, Field, Filter, User</em> modules.',
|
||||
'Unable to install the <em class="placeholder">unknown_theme</em> theme since it does not exist.',
|
||||
'Unable to install the <em class="placeholder">Bartik</em> theme since it requires the <em class="placeholder">Classy</em> theme.',
|
||||
'Unable to install the <em class="placeholder">Bartik</em> theme since it requires the <em class="placeholder">Stable</em> theme.',
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.config</em> depends on configuration (<em class="placeholder">unknown, unknown2</em>) that will not exist after import.',
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.existing</em> depends on the <em class="placeholder">config_test.dynamic.dotted.deleted</em> configuration that will not exist after import.',
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.module</em> depends on modules (<em class="placeholder">unknown, Database Logging</em>) that will not be installed after import.',
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.theme</em> depends on themes (<em class="placeholder">unknown, Seven</em>) that will not be installed after import.',
|
||||
'Configuration <em class="placeholder">unknown.config</em> depends on the <em class="placeholder">unknown</em> extension that will not be installed after import.',
|
||||
];
|
||||
$this->assertEquals(implode(PHP_EOL, $expected), $e->getMessage());
|
||||
$error_log = $this->configImporter->getErrors();
|
||||
$expected = [
|
||||
'Configuration <em class="placeholder">config_test.dynamic.dotted.config</em> depends on configuration (<em class="placeholder">unknown, unknown2</em>) that will not exist after import.',
|
||||
|
@ -637,7 +685,8 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
$this->fail('ConfigImporterException not thrown, invalid import was not stopped due to missing dependencies.');
|
||||
}
|
||||
catch (ConfigImporterException $e) {
|
||||
$this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.');
|
||||
$expected = static::FAIL_MESSAGE . PHP_EOL . 'The core.extension configuration does not exist.';
|
||||
$this->assertEquals($expected, $e->getMessage());
|
||||
$error_log = $this->configImporter->getErrors();
|
||||
$this->assertEqual(['The core.extension configuration does not exist.'], $error_log);
|
||||
}
|
||||
|
@ -661,7 +710,8 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
$this->fail('ConfigImporterException not thrown; an invalid import was not stopped due to missing dependencies.');
|
||||
}
|
||||
catch (ConfigImporterException $e) {
|
||||
$this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.');
|
||||
$expected = static::FAIL_MESSAGE . PHP_EOL . 'Unable to install the <em class="placeholder">standard</em> module since it does not exist.';
|
||||
$this->assertEquals($expected, $e->getMessage(), 'There were errors validating the config synchronization.');
|
||||
$error_log = $this->configImporter->getErrors();
|
||||
// Install profiles should not even be scanned at this point.
|
||||
$this->assertEqual(['Unable to install the <em class="placeholder">standard</em> module since it does not exist.'], $error_log);
|
||||
|
@ -686,13 +736,14 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
$this->fail('ConfigImporterException not thrown; an invalid import was not stopped due to missing dependencies.');
|
||||
}
|
||||
catch (ConfigImporterException $e) {
|
||||
$this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.');
|
||||
$expected = static::FAIL_MESSAGE . PHP_EOL . 'Cannot change the install profile from <em class="placeholder"></em> to <em class="placeholder">this_will_not_work</em> once Drupal is installed.';
|
||||
$this->assertEquals($expected, $e->getMessage(), 'There were errors validating the config synchronization.');
|
||||
$error_log = $this->configImporter->getErrors();
|
||||
// Install profiles can not be changed. Note that KernelTestBase currently
|
||||
// does not use an install profile. This situation should be impossible
|
||||
// to get in but site's can removed the install profile setting from
|
||||
// settings.php so the test is valid.
|
||||
$this->assertEqual(['Cannot change the install profile from <em class="placeholder">this_will_not_work</em> to <em class="placeholder"></em> once Drupal is installed.'], $error_log);
|
||||
$this->assertEqual(['Cannot change the install profile from <em class="placeholder"></em> to <em class="placeholder">this_will_not_work</em> once Drupal is installed.'], $error_log);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -797,7 +848,7 @@ class ConfigImporterTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Helper meothd to test custom config installer steps.
|
||||
* Helper method to test custom config installer steps.
|
||||
*
|
||||
* @param array $context
|
||||
* Batch context.
|
||||
|
|
|
@ -146,7 +146,7 @@ class ConfigInstallTest extends KernelTestBase {
|
|||
$this->assertEqual($collections, $active_storage->getAllCollectionNames());
|
||||
$collection_storage = $active_storage->createCollection('entity');
|
||||
$data = $collection_storage->read('config_test.dynamic.dotted.default');
|
||||
$this->assertIdentical(['label' => 'entity'], $data);
|
||||
$this->assertSame(['label' => 'entity'], $data);
|
||||
|
||||
// Test that the config manager uninstalls configuration from collections
|
||||
// as expected.
|
||||
|
@ -185,7 +185,7 @@ class ConfigInstallTest extends KernelTestBase {
|
|||
$data = $active_storage->read($name);
|
||||
$this->assertTrue(isset($data['uuid']));
|
||||
$data = $collection_storage->read($name);
|
||||
$this->assertIdentical(['label' => 'entity'], $data);
|
||||
$this->assertSame(['label' => 'entity'], $data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -227,7 +227,7 @@ class ConfigInstallTest extends KernelTestBase {
|
|||
$this->assertTrue($entity, 'The config_test.dynamic.other_module_test_with_dependency configuration has been created during install.');
|
||||
// Ensure that dependencies can be added during module installation by
|
||||
// hooks.
|
||||
$this->assertIdentical('config_install_dependency_test', $entity->getDependencies()['module'][0]);
|
||||
$this->assertSame('config_install_dependency_test', $entity->getDependencies()['module'][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -253,6 +253,14 @@ class ConfigInstallTest extends KernelTestBase {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests installing configuration where the filename and ID do not match.
|
||||
*/
|
||||
public function testIdMisMatch() {
|
||||
$this->setExpectedException(\PHPUnit_Framework_Error_Warning::class, 'The configuration name "config_test.dynamic.no_id_match" does not match the ID "does_not_match"');
|
||||
$this->installModules(['config_test_id_mismatch']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs a module.
|
||||
*
|
||||
|
|
|
@ -20,6 +20,7 @@ class ConfigOverrideTest extends KernelTestBase {
|
|||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(['system']);
|
||||
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync'));
|
||||
}
|
||||
|
||||
|
|
|
@ -40,22 +40,23 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
*/
|
||||
public function testSchemaMapping() {
|
||||
// Nonexistent configuration key will have Undefined as metadata.
|
||||
$this->assertIdentical(FALSE, \Drupal::service('config.typed')->hasConfigSchema('config_schema_test.no_such_key'));
|
||||
$this->assertSame(FALSE, \Drupal::service('config.typed')->hasConfigSchema('config_schema_test.no_such_key'));
|
||||
$definition = \Drupal::service('config.typed')->getDefinition('config_schema_test.no_such_key');
|
||||
$expected = [];
|
||||
$expected['label'] = 'Undefined';
|
||||
$expected['class'] = Undefined::class;
|
||||
$expected['type'] = 'undefined';
|
||||
$expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for nonexistent configuration.');
|
||||
|
||||
// Configuration file without schema will return Undefined as well.
|
||||
$this->assertIdentical(FALSE, \Drupal::service('config.typed')->hasConfigSchema('config_schema_test.noschema'));
|
||||
$this->assertSame(FALSE, \Drupal::service('config.typed')->hasConfigSchema('config_schema_test.noschema'));
|
||||
$definition = \Drupal::service('config.typed')->getDefinition('config_schema_test.noschema');
|
||||
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for configuration with no schema.');
|
||||
|
||||
// Configuration file with only some schema.
|
||||
$this->assertIdentical(TRUE, \Drupal::service('config.typed')->hasConfigSchema('config_schema_test.someschema'));
|
||||
$this->assertSame(TRUE, \Drupal::service('config.typed')->hasConfigSchema('config_schema_test.someschema'));
|
||||
$definition = \Drupal::service('config.typed')->getDefinition('config_schema_test.someschema');
|
||||
$expected = [];
|
||||
$expected['label'] = 'Schema test data';
|
||||
|
@ -67,6 +68,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['mapping']['testlist'] = ['label' => 'Test list'];
|
||||
$expected['type'] = 'config_schema_test.someschema';
|
||||
$expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for configuration with only some schema.');
|
||||
|
||||
// Check type detection on elements with undefined types.
|
||||
|
@ -77,6 +79,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['class'] = Undefined::class;
|
||||
$expected['type'] = 'undefined';
|
||||
$expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
$this->assertEqual($definition, $expected, 'Automatic type detected for a scalar is undefined.');
|
||||
$definition = $config->get('testlist')->getDataDefinition()->toArray();
|
||||
$expected = [];
|
||||
|
@ -84,6 +87,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['class'] = Undefined::class;
|
||||
$expected['type'] = 'undefined';
|
||||
$expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
$this->assertEqual($definition, $expected, 'Automatic type detected for a list is undefined.');
|
||||
$definition = $config->get('testnoschema')->getDataDefinition()->toArray();
|
||||
$expected = [];
|
||||
|
@ -91,6 +95,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['class'] = Undefined::class;
|
||||
$expected['type'] = 'undefined';
|
||||
$expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
$this->assertEqual($definition, $expected, 'Automatic type detected for an undefined integer is undefined.');
|
||||
|
||||
// Simple case, straight metadata.
|
||||
|
@ -109,6 +114,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['mapping']['_core']['type'] = '_core_config_info';
|
||||
$expected['type'] = 'system.maintenance';
|
||||
$expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for system.maintenance');
|
||||
|
||||
// Mixed schema with ignore elements.
|
||||
|
@ -139,6 +145,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
'type' => 'integer',
|
||||
];
|
||||
$expected['type'] = 'config_schema_test.ignore';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
|
||||
$this->assertEqual($definition, $expected);
|
||||
|
||||
|
@ -149,6 +156,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['label'] = 'Irrelevant';
|
||||
$expected['class'] = Ignore::class;
|
||||
$expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
$this->assertEqual($definition, $expected);
|
||||
$definition = \Drupal::service('config.typed')->get('config_schema_test.ignore')->get('indescribable')->getDataDefinition()->toArray();
|
||||
$expected['label'] = 'Indescribable';
|
||||
|
@ -160,8 +168,9 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['label'] = 'Image style';
|
||||
$expected['class'] = Mapping::class;
|
||||
$expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
$expected['mapping']['name']['type'] = 'string';
|
||||
$expected['mapping']['uuid']['type'] = 'string';
|
||||
$expected['mapping']['uuid']['type'] = 'uuid';
|
||||
$expected['mapping']['uuid']['label'] = 'UUID';
|
||||
$expected['mapping']['langcode']['type'] = 'string';
|
||||
$expected['mapping']['langcode']['label'] = 'Language code';
|
||||
|
@ -177,7 +186,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['mapping']['effects']['sequence']['mapping']['id']['type'] = 'string';
|
||||
$expected['mapping']['effects']['sequence']['mapping']['data']['type'] = 'image.effect.[%parent.id]';
|
||||
$expected['mapping']['effects']['sequence']['mapping']['weight']['type'] = 'integer';
|
||||
$expected['mapping']['effects']['sequence']['mapping']['uuid']['type'] = 'string';
|
||||
$expected['mapping']['effects']['sequence']['mapping']['uuid']['type'] = 'uuid';
|
||||
$expected['mapping']['third_party_settings']['type'] = 'sequence';
|
||||
$expected['mapping']['third_party_settings']['label'] = 'Third party settings';
|
||||
$expected['mapping']['third_party_settings']['sequence']['type'] = '[%parent.%parent.%type].third_party.[%key]';
|
||||
|
@ -193,6 +202,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['label'] = 'Image scale';
|
||||
$expected['class'] = Mapping::class;
|
||||
$expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
$expected['mapping']['width']['type'] = 'integer';
|
||||
$expected['mapping']['width']['label'] = 'Width';
|
||||
$expected['mapping']['height']['type'] = 'integer';
|
||||
|
@ -201,7 +211,6 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['mapping']['upscale']['label'] = 'Upscale';
|
||||
$expected['type'] = 'image.effect.image_scale';
|
||||
|
||||
|
||||
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for image.effect.image_scale');
|
||||
|
||||
// Most complex case, get metadata for actual configuration element.
|
||||
|
@ -220,6 +229,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['label'] = 'Mapping';
|
||||
$expected['class'] = Mapping::class;
|
||||
$expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
$expected['mapping'] = [
|
||||
'integer' => ['type' => 'integer'],
|
||||
'string' => ['type' => 'string'],
|
||||
|
@ -241,6 +251,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['mapping']['testdescription']['label'] = 'Description';
|
||||
$expected['type'] = 'config_schema_test.someschema.somemodule.*.*';
|
||||
$expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
|
||||
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for config_schema_test.someschema.somemodule.section_one.subsection');
|
||||
|
||||
|
@ -263,6 +274,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
'label' => 'Test item nested one level',
|
||||
'class' => StringData::class,
|
||||
'definition_class' => '\Drupal\Core\TypedData\DataDefinition',
|
||||
'unwrap_for_canonical_representation' => TRUE,
|
||||
];
|
||||
$this->assertEqual($definition, $expected);
|
||||
|
||||
|
@ -274,6 +286,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
'label' => 'Test item nested two levels',
|
||||
'class' => StringData::class,
|
||||
'definition_class' => '\Drupal\Core\TypedData\DataDefinition',
|
||||
'unwrap_for_canonical_representation' => TRUE,
|
||||
];
|
||||
$this->assertEqual($definition, $expected);
|
||||
|
||||
|
@ -285,6 +298,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
'label' => 'Test item nested three levels',
|
||||
'class' => StringData::class,
|
||||
'definition_class' => '\Drupal\Core\TypedData\DataDefinition',
|
||||
'unwrap_for_canonical_representation' => TRUE,
|
||||
];
|
||||
$this->assertEqual($definition, $expected);
|
||||
}
|
||||
|
@ -321,7 +335,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$effect = $effects->get($uuid)->getElements();
|
||||
$this->assertTrue(!$effect['data']->isEmpty() && $effect['id']->getValue() == 'image_scale', 'Got data for the image scale effect from metadata.');
|
||||
$this->assertTrue($effect['data']->get('width') instanceof IntegerInterface, 'Got the right type for the scale effect width.');
|
||||
$this->assertEqual($effect['data']->get('width')->getValue(), 480, 'Got the right value for the scale effect width.' );
|
||||
$this->assertEqual($effect['data']->get('width')->getValue(), 480, 'Got the right value for the scale effect width.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -338,7 +352,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
// If the config schema doesn't have a type it shouldn't be casted.
|
||||
'no_type' => 1,
|
||||
'mapping' => [
|
||||
'string' => 1
|
||||
'string' => 1,
|
||||
],
|
||||
'float' => '3.14',
|
||||
'null_float' => '',
|
||||
|
@ -361,7 +375,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
'boolean' => TRUE,
|
||||
'no_type' => 1,
|
||||
'mapping' => [
|
||||
'string' => '1'
|
||||
'string' => '1',
|
||||
],
|
||||
'float' => 3.14,
|
||||
'null_float' => NULL,
|
||||
|
@ -395,6 +409,76 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$this->assertIdentical($installed_data, $original_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests configuration sequence sorting using schemas.
|
||||
*/
|
||||
public function testConfigSaveWithSequenceSorting() {
|
||||
$data = [
|
||||
'keyed_sort' => [
|
||||
'b' => '1',
|
||||
'a' => '2',
|
||||
],
|
||||
'no_sort' => [
|
||||
'b' => '2',
|
||||
'a' => '1',
|
||||
],
|
||||
];
|
||||
// Save config which has a schema that enforces sorting.
|
||||
$this->config('config_schema_test.schema_sequence_sort')
|
||||
->setData($data)
|
||||
->save();
|
||||
$this->assertSame(['a' => '2', 'b' => '1'], $this->config('config_schema_test.schema_sequence_sort')->get('keyed_sort'));
|
||||
$this->assertSame(['b' => '2', 'a' => '1'], $this->config('config_schema_test.schema_sequence_sort')->get('no_sort'));
|
||||
|
||||
$data = [
|
||||
'value_sort' => ['b', 'a'],
|
||||
'no_sort' => ['b', 'a'],
|
||||
];
|
||||
// Save config which has a schema that enforces sorting.
|
||||
$this->config('config_schema_test.schema_sequence_sort')
|
||||
->setData($data)
|
||||
->save();
|
||||
|
||||
$this->assertSame(['a', 'b'], $this->config('config_schema_test.schema_sequence_sort')->get('value_sort'));
|
||||
$this->assertSame(['b', 'a'], $this->config('config_schema_test.schema_sequence_sort')->get('no_sort'));
|
||||
|
||||
// Value sort does not preserve keys - this is intentional.
|
||||
$data = [
|
||||
'value_sort' => [1 => 'b', 2 => 'a'],
|
||||
'no_sort' => [1 => 'b', 2 => 'a'],
|
||||
];
|
||||
// Save config which has a schema that enforces sorting.
|
||||
$this->config('config_schema_test.schema_sequence_sort')
|
||||
->setData($data)
|
||||
->save();
|
||||
|
||||
$this->assertSame(['a', 'b'], $this->config('config_schema_test.schema_sequence_sort')->get('value_sort'));
|
||||
$this->assertSame([1 => 'b', 2 => 'a'], $this->config('config_schema_test.schema_sequence_sort')->get('no_sort'));
|
||||
|
||||
// Test sorts do not destroy complex values.
|
||||
$data = [
|
||||
'complex_sort_value' => [['foo' => 'b', 'bar' => 'b'] , ['foo' => 'a', 'bar' => 'a']],
|
||||
'complex_sort_key' => ['b' => ['foo' => '1', 'bar' => '1'] , 'a' => ['foo' => '2', 'bar' => '2']],
|
||||
];
|
||||
$this->config('config_schema_test.schema_sequence_sort')
|
||||
->setData($data)
|
||||
->save();
|
||||
$this->assertSame([['foo' => 'a', 'bar' => 'a'], ['foo' => 'b', 'bar' => 'b']], $this->config('config_schema_test.schema_sequence_sort')->get('complex_sort_value'));
|
||||
$this->assertSame(['a' => ['foo' => '2', 'bar' => '2'], 'b' => ['foo' => '1', 'bar' => '1']], $this->config('config_schema_test.schema_sequence_sort')->get('complex_sort_key'));
|
||||
|
||||
// Swap the previous test scenario around.
|
||||
$data = [
|
||||
'complex_sort_value' => ['b' => ['foo' => '1', 'bar' => '1'] , 'a' => ['foo' => '2', 'bar' => '2']],
|
||||
'complex_sort_key' => [['foo' => 'b', 'bar' => 'b'] , ['foo' => 'a', 'bar' => 'a']],
|
||||
];
|
||||
$this->config('config_schema_test.schema_sequence_sort')
|
||||
->setData($data)
|
||||
->save();
|
||||
$this->assertSame([['foo' => '1', 'bar' => '1'], ['foo' => '2', 'bar' => '2']], $this->config('config_schema_test.schema_sequence_sort')->get('complex_sort_value'));
|
||||
$this->assertSame([['foo' => 'b', 'bar' => 'b'], ['foo' => 'a', 'bar' => 'a']], $this->config('config_schema_test.schema_sequence_sort')->get('complex_sort_key'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests fallback to a greedy wildcard.
|
||||
*/
|
||||
|
@ -405,6 +489,7 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
$expected['label'] = 'Schema wildcard fallback test';
|
||||
$expected['class'] = Mapping::class;
|
||||
$expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition';
|
||||
$expected['unwrap_for_canonical_representation'] = TRUE;
|
||||
$expected['mapping']['langcode']['type'] = 'string';
|
||||
$expected['mapping']['langcode']['label'] = 'Language code';
|
||||
$expected['mapping']['_core']['type'] = '_core_config_info';
|
||||
|
@ -418,8 +503,8 @@ class ConfigSchemaTest extends KernelTestBase {
|
|||
|
||||
$definition2 = \Drupal::service('config.typed')->getDefinition('config_schema_test.wildcard_fallback.something.something');
|
||||
// This should be the schema of config_schema_test.wildcard_fallback.* as
|
||||
//well.
|
||||
$this->assertIdentical($definition, $definition2);
|
||||
// well.
|
||||
$this->assertSame($definition, $definition2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,6 +24,7 @@ class ConfigSnapshotTest extends KernelTestBase {
|
|||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(['system']);
|
||||
// Update the config snapshot. This allows the parent::setUp() to write
|
||||
// configuration files.
|
||||
\Drupal::service('config.manager')->createSnapshot(\Drupal::service('config.storage'), \Drupal::service('config.storage.snapshot'));
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Config\Entity;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityUpdater;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests \Drupal\Core\Config\Entity\ConfigEntityUpdater.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Config\Entity\ConfigEntityUpdater
|
||||
* @group config
|
||||
*/
|
||||
class ConfigEntityUpdaterTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['config_test'];
|
||||
|
||||
/**
|
||||
* @covers ::update
|
||||
*/
|
||||
public function testUpdate() {
|
||||
// Create some entities to update.
|
||||
$storage = $this->container->get('entity_type.manager')->getStorage('config_test');
|
||||
for ($i = 0; $i < 15; $i++) {
|
||||
$entity_id = 'config_test_' . $i;
|
||||
$storage->create(['id' => $entity_id, 'label' => $entity_id])->save();
|
||||
}
|
||||
|
||||
// Set up the updater.
|
||||
$sandbox = [];
|
||||
$settings = Settings::getInstance() ? Settings::getAll() : [];
|
||||
$settings['entity_update_batch_size'] = 10;
|
||||
new Settings($settings);
|
||||
$updater = $this->container->get('class_resolver')->getInstanceFromDefinition(ConfigEntityUpdater::class);
|
||||
|
||||
$callback = function ($config_entity) {
|
||||
/** @var \Drupal\config_test\Entity\ConfigTest $config_entity */
|
||||
$number = (int) str_replace('config_test_', '', $config_entity->id());
|
||||
// Only update even numbered entities.
|
||||
if ($number % 2 == 0) {
|
||||
$config_entity->set('label', $config_entity->label . ' (updated)');
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
// This should run against the first 10 entities. The even numbered labels
|
||||
// will have been updated.
|
||||
$updater->update($sandbox, 'config_test', $callback);
|
||||
$entities = $storage->loadMultiple();
|
||||
$this->assertEquals('config_test_8 (updated)', $entities['config_test_8']->label());
|
||||
$this->assertEquals('config_test_9', $entities['config_test_9']->label());
|
||||
$this->assertEquals('config_test_10', $entities['config_test_10']->label());
|
||||
$this->assertEquals('config_test_14', $entities['config_test_14']->label());
|
||||
$this->assertEquals(15, $sandbox['config_entity_updater:config_test']['count']);
|
||||
$this->assertCount(5, $sandbox['config_entity_updater:config_test']['entities']);
|
||||
$this->assertEquals(10 / 15, $sandbox['#finished']);
|
||||
|
||||
// Update the rest.
|
||||
$updater->update($sandbox, 'config_test', $callback);
|
||||
$entities = $storage->loadMultiple();
|
||||
$this->assertEquals('config_test_8 (updated)', $entities['config_test_8']->label());
|
||||
$this->assertEquals('config_test_9', $entities['config_test_9']->label());
|
||||
$this->assertEquals('config_test_10 (updated)', $entities['config_test_10']->label());
|
||||
$this->assertEquals('config_test_14 (updated)', $entities['config_test_14']->label());
|
||||
$this->assertEquals(1, $sandbox['#finished']);
|
||||
$this->assertCount(0, $sandbox['config_entity_updater:config_test']['entities']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::update
|
||||
*/
|
||||
public function testUpdateDefaultCallback() {
|
||||
// Create some entities to update.
|
||||
$storage = $this->container->get('entity_type.manager')->getStorage('config_test');
|
||||
for ($i = 0; $i < 15; $i++) {
|
||||
$entity_id = 'config_test_' . $i;
|
||||
$storage->create(['id' => $entity_id, 'label' => $entity_id])->save();
|
||||
}
|
||||
|
||||
// Set up the updater.
|
||||
$sandbox = [];
|
||||
$settings = Settings::getInstance() ? Settings::getAll() : [];
|
||||
$settings['entity_update_batch_size'] = 9;
|
||||
new Settings($settings);
|
||||
$updater = $this->container->get('class_resolver')->getInstanceFromDefinition(ConfigEntityUpdater::class);
|
||||
// Cause a dependency to be added during an update.
|
||||
\Drupal::state()->set('config_test_new_dependency', 'added_dependency');
|
||||
|
||||
// This should run against the first 10 entities.
|
||||
$updater->update($sandbox, 'config_test');
|
||||
$entities = $storage->loadMultiple();
|
||||
$this->assertEquals(['added_dependency'], $entities['config_test_7']->getDependencies()['module']);
|
||||
$this->assertEquals(['added_dependency'], $entities['config_test_8']->getDependencies()['module']);
|
||||
$this->assertEquals([], $entities['config_test_9']->getDependencies());
|
||||
$this->assertEquals([], $entities['config_test_14']->getDependencies());
|
||||
$this->assertEquals(15, $sandbox['config_entity_updater:config_test']['count']);
|
||||
$this->assertCount(6, $sandbox['config_entity_updater:config_test']['entities']);
|
||||
$this->assertEquals(9 / 15, $sandbox['#finished']);
|
||||
|
||||
// Update the rest.
|
||||
$updater->update($sandbox, 'config_test');
|
||||
$entities = $storage->loadMultiple();
|
||||
$this->assertEquals(['added_dependency'], $entities['config_test_9']->getDependencies()['module']);
|
||||
$this->assertEquals(['added_dependency'], $entities['config_test_14']->getDependencies()['module']);
|
||||
$this->assertEquals(1, $sandbox['#finished']);
|
||||
$this->assertCount(0, $sandbox['config_entity_updater:config_test']['entities']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::update
|
||||
*/
|
||||
public function testUpdateException() {
|
||||
$this->enableModules(['entity_test']);
|
||||
$this->setExpectedException(\InvalidArgumentException::class, 'The provided entity type ID \'entity_test_mul_changed\' is not a configuration entity type');
|
||||
$updater = $this->container->get('class_resolver')->getInstanceFromDefinition(ConfigEntityUpdater::class);
|
||||
$sandbox = [];
|
||||
$updater->update($sandbox, 'entity_test_mul_changed');
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,6 @@ namespace Drupal\KernelTests\Core\Config;
|
|||
use Drupal\Core\Config\Schema\SchemaCheckTrait;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
|
||||
/**
|
||||
* Tests the functionality of SchemaCheckTrait.
|
||||
*
|
||||
|
|
|
@ -151,6 +151,11 @@ abstract class ConfigStorageTestBase extends KernelTestBase {
|
|||
// Listing on a non-existing storage bin returns an empty array.
|
||||
$result = $this->invalidStorage->listAll();
|
||||
$this->assertIdentical($result, []);
|
||||
|
||||
// Getting all collections on a non-existing storage bin return an empty
|
||||
// array.
|
||||
$this->assertSame([], $this->invalidStorage->getAllCollectionNames());
|
||||
|
||||
// Writing to a non-existing storage bin creates the bin.
|
||||
$this->invalidStorage->write($name, ['foo' => 'bar']);
|
||||
$result = $this->invalidStorage->read($name);
|
||||
|
@ -189,7 +194,7 @@ abstract class ConfigStorageTestBase extends KernelTestBase {
|
|||
$data = ['foo' => 'bar'];
|
||||
$result = $this->storage->write($name, $data);
|
||||
$this->assertIdentical($result, TRUE);
|
||||
$this->assertIdentical($data, $this->storage->read($name));
|
||||
$this->assertSame($data, $this->storage->read($name));
|
||||
|
||||
// Create configuration in a new collection.
|
||||
$new_storage = $this->storage->createCollection('collection.sub.new');
|
||||
|
@ -197,13 +202,13 @@ abstract class ConfigStorageTestBase extends KernelTestBase {
|
|||
$this->assertEqual([], $new_storage->listAll());
|
||||
$new_storage->write($name, $data);
|
||||
$this->assertIdentical($result, TRUE);
|
||||
$this->assertIdentical($data, $new_storage->read($name));
|
||||
$this->assertSame($data, $new_storage->read($name));
|
||||
$this->assertEqual([$name], $new_storage->listAll());
|
||||
$this->assertTrue($new_storage->exists($name));
|
||||
$new_data = ['foo' => 'baz'];
|
||||
$new_storage->write($name, $new_data);
|
||||
$this->assertIdentical($result, TRUE);
|
||||
$this->assertIdentical($new_data, $new_storage->read($name));
|
||||
$this->assertSame($new_data, $new_storage->read($name));
|
||||
|
||||
// Create configuration in another collection.
|
||||
$another_storage = $this->storage->createCollection('collection.sub.another');
|
||||
|
@ -211,7 +216,7 @@ abstract class ConfigStorageTestBase extends KernelTestBase {
|
|||
$this->assertEqual([], $another_storage->listAll());
|
||||
$another_storage->write($name, $new_data);
|
||||
$this->assertIdentical($result, TRUE);
|
||||
$this->assertIdentical($new_data, $another_storage->read($name));
|
||||
$this->assertSame($new_data, $another_storage->read($name));
|
||||
$this->assertEqual([$name], $another_storage->listAll());
|
||||
$this->assertTrue($another_storage->exists($name));
|
||||
|
||||
|
@ -219,18 +224,18 @@ abstract class ConfigStorageTestBase extends KernelTestBase {
|
|||
$alt_storage = $this->storage->createCollection('alternate');
|
||||
$alt_storage->write($name, $new_data);
|
||||
$this->assertIdentical($result, TRUE);
|
||||
$this->assertIdentical($new_data, $alt_storage->read($name));
|
||||
$this->assertSame($new_data, $alt_storage->read($name));
|
||||
|
||||
// Switch back to the collection-less mode and check the data still exists
|
||||
// add has not been touched.
|
||||
$this->assertIdentical($data, $this->storage->read($name));
|
||||
$this->assertSame($data, $this->storage->read($name));
|
||||
|
||||
// Check that the getAllCollectionNames() method works.
|
||||
$this->assertIdentical(['alternate', 'collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
|
||||
$this->assertSame(['alternate', 'collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
|
||||
|
||||
// Check that the collections are removed when they are empty.
|
||||
$alt_storage->delete($name);
|
||||
$this->assertIdentical(['collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
|
||||
$this->assertSame(['collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
|
||||
|
||||
// Create configuration in collection called 'collection'. This ensures that
|
||||
// FileStorage's collection storage works regardless of its use of
|
||||
|
@ -240,19 +245,19 @@ abstract class ConfigStorageTestBase extends KernelTestBase {
|
|||
$this->assertEqual([], $parent_storage->listAll());
|
||||
$parent_storage->write($name, $new_data);
|
||||
$this->assertIdentical($result, TRUE);
|
||||
$this->assertIdentical($new_data, $parent_storage->read($name));
|
||||
$this->assertSame($new_data, $parent_storage->read($name));
|
||||
$this->assertEqual([$name], $parent_storage->listAll());
|
||||
$this->assertTrue($parent_storage->exists($name));
|
||||
$this->assertIdentical(['collection', 'collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
|
||||
$this->assertSame(['collection', 'collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
|
||||
$parent_storage->deleteAll();
|
||||
$this->assertIdentical(['collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
|
||||
$this->assertSame(['collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
|
||||
|
||||
// Check that the having an empty collection-less storage does not break
|
||||
// anything. Before deleting check that the previous delete did not affect
|
||||
// data in another collection.
|
||||
$this->assertIdentical($data, $this->storage->read($name));
|
||||
$this->assertSame($data, $this->storage->read($name));
|
||||
$this->storage->delete($name);
|
||||
$this->assertIdentical(['collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
|
||||
$this->assertSame(['collection.sub.another', 'collection.sub.new'], $this->storage->getAllCollectionNames());
|
||||
}
|
||||
|
||||
abstract protected function read($name);
|
||||
|
|
|
@ -68,8 +68,8 @@ class FileStorageTest extends ConfigStorageTestBase {
|
|||
// @todo https://www.drupal.org/node/2666954 FileStorage::listAll() is
|
||||
// case-sensitive. However, \Drupal\Core\Config\DatabaseStorage::listAll()
|
||||
// is case-insensitive.
|
||||
$this->assertIdentical(['system.performance'], $this->storage->listAll('system'), 'The FileStorage::listAll() with prefix works.');
|
||||
$this->assertIdentical([], $this->storage->listAll('System'), 'The FileStorage::listAll() is case sensitive.');
|
||||
$this->assertSame(['system.performance'], $this->storage->listAll('system'), 'The FileStorage::listAll() with prefix works.');
|
||||
$this->assertSame([], $this->storage->listAll('System'), 'The FileStorage::listAll() is case sensitive.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace Drupal\KernelTests\Core\Database;
|
|||
* @group Database
|
||||
*/
|
||||
class BasicSyntaxTest extends DatabaseTestBase {
|
||||
|
||||
/**
|
||||
* Tests string concatenation.
|
||||
*/
|
||||
|
@ -28,15 +29,22 @@ class BasicSyntaxTest extends DatabaseTestBase {
|
|||
|
||||
/**
|
||||
* Tests string concatenation with field values.
|
||||
*
|
||||
* We use 'job' and 'age' fields from the {test} table. Using the 'name' field
|
||||
* for concatenation causes issues with custom or contrib database drivers,
|
||||
* since its type 'varchar_ascii' may lead to using field-level collations not
|
||||
* compatible with the other fields.
|
||||
*/
|
||||
public function testConcatFields() {
|
||||
$result = db_query('SELECT CONCAT(:a1, CONCAT(name, CONCAT(:a2, CONCAT(age, :a3)))) FROM {test} WHERE age = :age', [
|
||||
':a1' => 'The age of ',
|
||||
':a2' => ' is ',
|
||||
':a3' => '.',
|
||||
':age' => 25,
|
||||
]);
|
||||
$this->assertIdentical($result->fetchField(), 'The age of John is 25.', 'Field CONCAT works.');
|
||||
$result = $this->connection->query(
|
||||
'SELECT CONCAT(:a1, CONCAT(job, CONCAT(:a2, CONCAT(age, :a3)))) FROM {test} WHERE age = :age', [
|
||||
':a1' => 'The age of ',
|
||||
':a2' => ' is ',
|
||||
':a3' => '.',
|
||||
':age' => 25,
|
||||
]
|
||||
);
|
||||
$this->assertSame('The age of Singer is 25.', $result->fetchField(), 'Field CONCAT works.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace Drupal\KernelTests\Core\Database;
|
|||
* @group Database
|
||||
*/
|
||||
class CaseSensitivityTest extends DatabaseTestBase {
|
||||
|
||||
/**
|
||||
* Tests BINARY collation in MySQL.
|
||||
*/
|
||||
|
@ -16,14 +17,15 @@ class CaseSensitivityTest extends DatabaseTestBase {
|
|||
|
||||
db_insert('test')
|
||||
->fields([
|
||||
'name' => 'john', // <- A record already exists with name 'John'.
|
||||
// A record already exists with name 'John'.
|
||||
'name' => 'john',
|
||||
'age' => 2,
|
||||
'job' => 'Baby',
|
||||
])
|
||||
->execute();
|
||||
|
||||
$num_records_after = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
|
||||
$this->assertIdentical($num_records_before + 1, (int) $num_records_after, 'Record inserts correctly.');
|
||||
$this->assertSame($num_records_before + 1, (int) $num_records_after, 'Record inserts correctly.');
|
||||
$saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'john'])->fetchField();
|
||||
$this->assertIdentical($saved_age, '2', 'Can retrieve after inserting.');
|
||||
}
|
||||
|
|
|
@ -32,18 +32,18 @@ class ConnectionTest extends DatabaseTestBase {
|
|||
// Try to open those targets another time, that should return the same objects.
|
||||
$db1b = Database::getConnection('default', 'default');
|
||||
$db2b = Database::getConnection('replica', 'default');
|
||||
$this->assertIdentical($db1, $db1b, 'A second call to getConnection() returns the same object.');
|
||||
$this->assertIdentical($db2, $db2b, 'A second call to getConnection() returns the same object.');
|
||||
$this->assertSame($db1, $db1b, 'A second call to getConnection() returns the same object.');
|
||||
$this->assertSame($db2, $db2b, 'A second call to getConnection() returns the same object.');
|
||||
|
||||
// Try to open an unknown target.
|
||||
$unknown_target = $this->randomMachineName();
|
||||
$db3 = Database::getConnection($unknown_target, 'default');
|
||||
$this->assertNotNull($db3, 'Opening an unknown target returns a real connection object.');
|
||||
$this->assertIdentical($db1, $db3, 'An unknown target opens the default connection.');
|
||||
$this->assertSame($db1, $db3, 'An unknown target opens the default connection.');
|
||||
|
||||
// Try to open that unknown target another time, that should return the same object.
|
||||
$db3b = Database::getConnection($unknown_target, 'default');
|
||||
$this->assertIdentical($db3, $db3b, 'A second call to getConnection() returns the same object.');
|
||||
$this->assertSame($db3, $db3b, 'A second call to getConnection() returns the same object.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,7 +61,7 @@ class ConnectionTest extends DatabaseTestBase {
|
|||
$db1 = Database::getConnection('default', 'default');
|
||||
$db2 = Database::getConnection('replica', 'default');
|
||||
|
||||
$this->assertIdentical($db1, $db2, 'Both targets refer to the same connection.');
|
||||
$this->assertSame($db1, $db2, 'Both targets refer to the same connection.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,7 +131,7 @@ class ConnectionTest extends DatabaseTestBase {
|
|||
try {
|
||||
$db->query('SELECT * FROM {test}; SELECT * FROM {test_people}',
|
||||
[],
|
||||
[ 'allow_delimiter_in_query' => TRUE ]
|
||||
['allow_delimiter_in_query' => TRUE]
|
||||
);
|
||||
$this->fail('No PDO exception thrown for multiple statements.');
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ class ConnectionUnitTest extends KernelTestBase {
|
|||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getConnectionID() {
|
||||
protected function getConnectionId() {
|
||||
return (int) Database::getConnection($this->target, $this->key)->query('SELECT CONNECTION_ID()')->fetchField();
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ class ConnectionUnitTest extends KernelTestBase {
|
|||
/**
|
||||
* Tests Database::closeConnection() without query.
|
||||
*
|
||||
* @todo getConnectionID() executes a query.
|
||||
* @todo getConnectionId() executes a query.
|
||||
*/
|
||||
public function testOpenClose() {
|
||||
if ($this->skipTest) {
|
||||
|
@ -100,7 +100,7 @@ class ConnectionUnitTest extends KernelTestBase {
|
|||
}
|
||||
// Add and open a new connection.
|
||||
$this->addConnection();
|
||||
$id = $this->getConnectionID();
|
||||
$id = $this->getConnectionId();
|
||||
Database::getConnection($this->target, $this->key);
|
||||
|
||||
// Verify that there is a new connection.
|
||||
|
@ -124,7 +124,7 @@ class ConnectionUnitTest extends KernelTestBase {
|
|||
}
|
||||
// Add and open a new connection.
|
||||
$this->addConnection();
|
||||
$id = $this->getConnectionID();
|
||||
$id = $this->getConnectionId();
|
||||
Database::getConnection($this->target, $this->key);
|
||||
|
||||
// Verify that there is a new connection.
|
||||
|
@ -151,7 +151,7 @@ class ConnectionUnitTest extends KernelTestBase {
|
|||
}
|
||||
// Add and open a new connection.
|
||||
$this->addConnection();
|
||||
$id = $this->getConnectionID();
|
||||
$id = $this->getConnectionId();
|
||||
Database::getConnection($this->target, $this->key);
|
||||
|
||||
// Verify that there is a new connection.
|
||||
|
@ -178,7 +178,7 @@ class ConnectionUnitTest extends KernelTestBase {
|
|||
}
|
||||
// Add and open a new connection.
|
||||
$this->addConnection();
|
||||
$id = $this->getConnectionID();
|
||||
$id = $this->getConnectionId();
|
||||
Database::getConnection($this->target, $this->key);
|
||||
|
||||
// Verify that there is a new connection.
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Database;
|
||||
|
||||
/**
|
||||
* Deprecation tests cases for the database layer.
|
||||
*
|
||||
* @group legacy
|
||||
*/
|
||||
class DatabaseLegacyTest extends DatabaseTestBase {
|
||||
|
||||
/**
|
||||
* Tests the db_table_exists() function.
|
||||
*
|
||||
* @expectedDeprecation db_table_exists() is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Use $injected_database->schema()->tableExists($table) instead. See https://www.drupal.org/node/2947929.
|
||||
*/
|
||||
public function testDbTableExists() {
|
||||
$this->assertTrue(db_table_exists('test'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the db_set_active() function.
|
||||
*
|
||||
* @expectedDeprecation db_set_active() is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Database\Database::setActiveConnection() instead. See https://www.drupal.org/node/2944084.
|
||||
*/
|
||||
public function testDbSetActive() {
|
||||
$get_active_db = $this->connection->getKey();
|
||||
$this->assert(db_set_active($get_active_db), 'Database connection is active');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the db_drop_table() function.
|
||||
*
|
||||
* @expectedDeprecation db_drop_table() is deprecated in Drupal 8.0.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\Database\Database::getConnection()->schema()->dropTable() instead. See https://www.drupal.org/node/2987737
|
||||
*/
|
||||
public function testDbDropTable() {
|
||||
$this->assertFalse(db_drop_table('temp_test_table'));
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\KernelTests\Core\Database;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
|
@ -14,8 +15,16 @@ abstract class DatabaseTestBase extends KernelTestBase {
|
|||
|
||||
public static $modules = ['database_test'];
|
||||
|
||||
/**
|
||||
* The database connection for testing.
|
||||
*
|
||||
* @var \Drupal\Core\Database\Connection
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->connection = Database::getConnection();
|
||||
$this->installSchema('database_test', [
|
||||
'test',
|
||||
'test_people',
|
||||
|
@ -35,7 +44,7 @@ abstract class DatabaseTestBase extends KernelTestBase {
|
|||
* Sets up tables for NULL handling.
|
||||
*/
|
||||
public function ensureSampleDataNull() {
|
||||
db_insert('test_null')
|
||||
$this->connection->insert('test_null')
|
||||
->fields(['name', 'age'])
|
||||
->values([
|
||||
'name' => 'Kermit',
|
||||
|
@ -56,8 +65,10 @@ abstract class DatabaseTestBase extends KernelTestBase {
|
|||
* Sets up our sample data.
|
||||
*/
|
||||
public static function addSampleData() {
|
||||
$connection = Database::getConnection();
|
||||
|
||||
// We need the IDs, so we can't use a multi-insert here.
|
||||
$john = db_insert('test')
|
||||
$john = $connection->insert('test')
|
||||
->fields([
|
||||
'name' => 'John',
|
||||
'age' => 25,
|
||||
|
@ -65,7 +76,7 @@ abstract class DatabaseTestBase extends KernelTestBase {
|
|||
])
|
||||
->execute();
|
||||
|
||||
$george = db_insert('test')
|
||||
$george = $connection->insert('test')
|
||||
->fields([
|
||||
'name' => 'George',
|
||||
'age' => 27,
|
||||
|
@ -73,7 +84,7 @@ abstract class DatabaseTestBase extends KernelTestBase {
|
|||
])
|
||||
->execute();
|
||||
|
||||
db_insert('test')
|
||||
$connection->insert('test')
|
||||
->fields([
|
||||
'name' => 'Ringo',
|
||||
'age' => 28,
|
||||
|
@ -81,7 +92,7 @@ abstract class DatabaseTestBase extends KernelTestBase {
|
|||
])
|
||||
->execute();
|
||||
|
||||
$paul = db_insert('test')
|
||||
$paul = $connection->insert('test')
|
||||
->fields([
|
||||
'name' => 'Paul',
|
||||
'age' => 26,
|
||||
|
@ -89,7 +100,7 @@ abstract class DatabaseTestBase extends KernelTestBase {
|
|||
])
|
||||
->execute();
|
||||
|
||||
db_insert('test_people')
|
||||
$connection->insert('test_people')
|
||||
->fields([
|
||||
'name' => 'Meredith',
|
||||
'age' => 30,
|
||||
|
@ -97,7 +108,7 @@ abstract class DatabaseTestBase extends KernelTestBase {
|
|||
])
|
||||
->execute();
|
||||
|
||||
db_insert('test_task')
|
||||
$connection->insert('test_task')
|
||||
->fields(['pid', 'task', 'priority'])
|
||||
->values([
|
||||
'pid' => $john,
|
||||
|
@ -136,10 +147,11 @@ abstract class DatabaseTestBase extends KernelTestBase {
|
|||
])
|
||||
->execute();
|
||||
|
||||
db_insert('test_special_columns')
|
||||
$connection->insert('test_special_columns')
|
||||
->fields([
|
||||
'id' => 1,
|
||||
'offset' => 'Offset value 1',
|
||||
'function' => 'Function value 1',
|
||||
])
|
||||
->execute();
|
||||
}
|
||||
|
|
|
@ -66,6 +66,84 @@ class DeleteTruncateTest extends DatabaseTestBase {
|
|||
$this->assertEqual(0, $num_records_after, 'Truncate really deletes everything.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms that we can truncate a whole table while in transaction.
|
||||
*/
|
||||
public function testTruncateInTransaction() {
|
||||
// This test won't work right if transactions are not supported.
|
||||
if (!$this->connection->supportsTransactions()) {
|
||||
$this->markTestSkipped('The database driver does not support transactions.');
|
||||
}
|
||||
|
||||
$num_records_before = $this->connection->select('test')->countQuery()->execute()->fetchField();
|
||||
$this->assertGreaterThan(0, $num_records_before, 'The table is not empty.');
|
||||
|
||||
$transaction = $this->connection->startTransaction('test_truncate_in_transaction');
|
||||
$this->connection->insert('test')
|
||||
->fields([
|
||||
'name' => 'Freddie',
|
||||
'age' => 45,
|
||||
'job' => 'Great singer',
|
||||
])
|
||||
->execute();
|
||||
$num_records_after_insert = $this->connection->select('test')->countQuery()->execute()->fetchField();
|
||||
$this->assertEquals($num_records_before + 1, $num_records_after_insert);
|
||||
|
||||
$this->connection->truncate('test')->execute();
|
||||
|
||||
// Checks that there are no records left in the table, and transaction is
|
||||
// still active.
|
||||
$this->assertTrue($this->connection->inTransaction());
|
||||
$num_records_after = $this->connection->select('test')->countQuery()->execute()->fetchField();
|
||||
$this->assertEquals(0, $num_records_after);
|
||||
|
||||
// Close the transaction, and check that there are still no records in the
|
||||
// table.
|
||||
$transaction = NULL;
|
||||
$this->assertFalse($this->connection->inTransaction());
|
||||
$num_records_after = $this->connection->select('test')->countQuery()->execute()->fetchField();
|
||||
$this->assertEquals(0, $num_records_after);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms that transaction rollback voids a truncate operation.
|
||||
*/
|
||||
public function testTruncateTransactionRollback() {
|
||||
// This test won't work right if transactions are not supported.
|
||||
if (!$this->connection->supportsTransactions()) {
|
||||
$this->markTestSkipped('The database driver does not support transactions.');
|
||||
}
|
||||
|
||||
$num_records_before = $this->connection->select('test')->countQuery()->execute()->fetchField();
|
||||
$this->assertGreaterThan(0, $num_records_before, 'The table is not empty.');
|
||||
|
||||
$transaction = $this->connection->startTransaction('test_truncate_in_transaction');
|
||||
$this->connection->insert('test')
|
||||
->fields([
|
||||
'name' => 'Freddie',
|
||||
'age' => 45,
|
||||
'job' => 'Great singer',
|
||||
])
|
||||
->execute();
|
||||
$num_records_after_insert = $this->connection->select('test')->countQuery()->execute()->fetchField();
|
||||
$this->assertEquals($num_records_before + 1, $num_records_after_insert);
|
||||
|
||||
$this->connection->truncate('test')->execute();
|
||||
|
||||
// Checks that there are no records left in the table, and transaction is
|
||||
// still active.
|
||||
$this->assertTrue($this->connection->inTransaction());
|
||||
$num_records_after = $this->connection->select('test')->countQuery()->execute()->fetchField();
|
||||
$this->assertEquals(0, $num_records_after);
|
||||
|
||||
// Roll back the transaction, and check that we are back to status before
|
||||
// insert and truncate.
|
||||
$this->connection->rollBack();
|
||||
$this->assertFalse($this->connection->inTransaction());
|
||||
$num_records_after = $this->connection->select('test')->countQuery()->execute()->fetchField();
|
||||
$this->assertEquals($num_records_before, $num_records_after);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms that we can delete a single special column name record successfully.
|
||||
*/
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace Drupal\KernelTests\Core\Database;
|
|||
|
||||
use Drupal\Core\Database\RowCountException;
|
||||
use Drupal\Core\Database\StatementInterface;
|
||||
use Drupal\system\Tests\Database\FakeRecord;
|
||||
use Drupal\Tests\system\Functional\Database\FakeRecord;
|
||||
|
||||
/**
|
||||
* Tests the Database system's various fetch capabilities.
|
||||
|
@ -69,7 +69,7 @@ class FetchTest extends DatabaseTestBase {
|
|||
*/
|
||||
public function testQueryFetchClass() {
|
||||
$records = [];
|
||||
$result = db_query('SELECT name FROM {test} WHERE age = :age', [':age' => 25], ['fetch' => 'Drupal\system\Tests\Database\FakeRecord']);
|
||||
$result = db_query('SELECT name FROM {test} WHERE age = :age', [':age' => 25], ['fetch' => FakeRecord::class]);
|
||||
foreach ($result as $record) {
|
||||
$records[] = $record;
|
||||
if ($this->assertTrue($record instanceof FakeRecord, 'Record is an object of class FakeRecord.')) {
|
||||
|
|
|
@ -40,7 +40,7 @@ class InsertDefaultsTest extends DatabaseTestBase {
|
|||
}
|
||||
|
||||
$num_records_after = (int) db_query('SELECT COUNT(*) FROM {test}')->fetchField();
|
||||
$this->assertIdentical($num_records_before, $num_records_after, 'Do nothing as no fields are specified.');
|
||||
$this->assertSame($num_records_before, $num_records_after, 'Do nothing as no fields are specified.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,7 +26,7 @@ class InsertTest extends DatabaseTestBase {
|
|||
$query->execute();
|
||||
|
||||
$num_records_after = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
|
||||
$this->assertIdentical($num_records_before + 1, (int) $num_records_after, 'Record inserts correctly.');
|
||||
$this->assertSame($num_records_before + 1, (int) $num_records_after, 'Record inserts correctly.');
|
||||
$saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Yoko'])->fetchField();
|
||||
$this->assertIdentical($saved_age, '29', 'Can retrieve after inserting.');
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ class InsertTest extends DatabaseTestBase {
|
|||
$query->execute();
|
||||
|
||||
$num_records_after = (int) db_query('SELECT COUNT(*) FROM {test}')->fetchField();
|
||||
$this->assertIdentical($num_records_before + 3, $num_records_after, 'Record inserts correctly.');
|
||||
$this->assertSame($num_records_before + 3, $num_records_after, 'Record inserts correctly.');
|
||||
$saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Larry'])->fetchField();
|
||||
$this->assertIdentical($saved_age, '30', 'Can retrieve after inserting.');
|
||||
$saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Curly'])->fetchField();
|
||||
|
@ -84,7 +84,8 @@ class InsertTest extends DatabaseTestBase {
|
|||
]);
|
||||
// Check how many records are queued for insertion.
|
||||
$this->assertIdentical($query->count(), 1, 'One record is queued for insertion.');
|
||||
$query->execute(); // This should run the insert, but leave the fields intact.
|
||||
// This should run the insert, but leave the fields intact.
|
||||
$query->execute();
|
||||
|
||||
// We should be able to specify values in any order if named.
|
||||
$query->values([
|
||||
|
@ -103,7 +104,7 @@ class InsertTest extends DatabaseTestBase {
|
|||
$query->execute();
|
||||
|
||||
$num_records_after = db_query('SELECT COUNT(*) FROM {test}')->fetchField();
|
||||
$this->assertIdentical((int) $num_records_before + 3, (int) $num_records_after, 'Record inserts correctly.');
|
||||
$this->assertSame((int) $num_records_before + 3, (int) $num_records_after, 'Record inserts correctly.');
|
||||
$saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Larry'])->fetchField();
|
||||
$this->assertIdentical($saved_age, '30', 'Can retrieve after inserting.');
|
||||
$saved_age = db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Curly'])->fetchField();
|
||||
|
@ -197,14 +198,20 @@ class InsertTest extends DatabaseTestBase {
|
|||
* Tests that we can INSERT INTO a special named column.
|
||||
*/
|
||||
public function testSpecialColumnInsert() {
|
||||
$id = db_insert('test_special_columns')
|
||||
$this->connection->insert('test_special_columns')
|
||||
->fields([
|
||||
'id' => 2,
|
||||
'offset' => 'Offset value 2',
|
||||
'function' => 'foobar',
|
||||
])
|
||||
->execute();
|
||||
$saved_value = db_query('SELECT "offset" FROM {test_special_columns} WHERE id = :id', [':id' => 2])->fetchField();
|
||||
$this->assertIdentical($saved_value, 'Offset value 2', 'Can retrieve special column name value after inserting.');
|
||||
$result = $this->connection->select('test_special_columns')
|
||||
->fields('test_special_columns', ['offset', 'function'])
|
||||
->condition('test_special_columns.function', 'foobar')
|
||||
->execute();
|
||||
$record = $result->fetch();
|
||||
$this->assertSame('Offset value 2', $record->offset);
|
||||
$this->assertSame('foobar', $record->function);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use Drupal\Core\Database\IntegrityConstraintViolationException;
|
|||
* @group Database
|
||||
*/
|
||||
class InvalidDataTest extends DatabaseTestBase {
|
||||
|
||||
/**
|
||||
* Tests aborting of traditional SQL database systems with invalid data.
|
||||
*/
|
||||
|
@ -24,7 +25,8 @@ class InvalidDataTest extends DatabaseTestBase {
|
|||
'age' => 63,
|
||||
'job' => 'Singer',
|
||||
])->values([
|
||||
'name' => 'John', // <-- Duplicate value on unique field.
|
||||
// Duplicate value on unique field.
|
||||
'name' => 'John',
|
||||
'age' => 17,
|
||||
'job' => 'Consultant',
|
||||
])
|
||||
|
@ -66,4 +68,81 @@ class InvalidDataTest extends DatabaseTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests inserting with invalid data from a select query.
|
||||
*/
|
||||
public function testInsertDuplicateDataFromSelect() {
|
||||
// Insert multiple records in 'test_people' where one has bad data
|
||||
// (duplicate key). A 'Meredith' record has already been inserted
|
||||
// in ::setUp.
|
||||
db_insert('test_people')
|
||||
->fields(['name', 'age', 'job'])
|
||||
->values([
|
||||
'name' => 'Elvis',
|
||||
'age' => 63,
|
||||
'job' => 'Singer',
|
||||
])->values([
|
||||
// Duplicate value on unique field 'name' for later INSERT in 'test'
|
||||
// table.
|
||||
'name' => 'John',
|
||||
'age' => 17,
|
||||
'job' => 'Consultant',
|
||||
])
|
||||
->values([
|
||||
'name' => 'Frank',
|
||||
'age' => 75,
|
||||
'job' => 'Bass',
|
||||
])
|
||||
->execute();
|
||||
|
||||
try {
|
||||
// Define the subselect query. Add ORDER BY to ensure we have consistent
|
||||
// order in results. Will return:
|
||||
// 0 => [name] => Elvis, [age] => 63, [job] => Singer
|
||||
// 1 => [name] => Frank, [age] => 75, [job] => Bass
|
||||
// 2 => [name] => John, [age] => 17, [job] => Consultant
|
||||
// 3 => [name] => Meredith, [age] => 30, [job] => Speaker
|
||||
// Records 0 and 1 should pass, record 2 should lead to integrity
|
||||
// constraint violation.
|
||||
$query = db_select('test_people', 'tp')
|
||||
->fields('tp', ['name', 'age', 'job'])
|
||||
->orderBy('name');
|
||||
|
||||
// Try inserting from the subselect.
|
||||
db_insert('test')
|
||||
->from($query)
|
||||
->execute();
|
||||
|
||||
$this->fail('Insert succeeded when it should not have.');
|
||||
}
|
||||
catch (IntegrityConstraintViolationException $e) {
|
||||
// Check if the second record was inserted.
|
||||
$name = db_query('SELECT name FROM {test} WHERE age = :age', [':age' => 75])->fetchField();
|
||||
|
||||
if ($name == 'Frank') {
|
||||
if (!Database::getConnection()->supportsTransactions()) {
|
||||
// This is an expected fail.
|
||||
// Database engines that don't support transactions can leave partial
|
||||
// inserts in place when an error occurs. This is the case for MySQL
|
||||
// when running on a MyISAM table.
|
||||
$this->pass("The whole transaction has not been rolled-back when a duplicate key insert occurs, this is expected because the database doesn't support transactions");
|
||||
}
|
||||
else {
|
||||
$this->fail('The whole transaction is rolled back when a duplicate key insert occurs.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->pass('The whole transaction is rolled back when a duplicate key insert occurs.');
|
||||
}
|
||||
|
||||
// Ensure the values for records 2 and 3 were not inserted.
|
||||
$record = db_select('test')
|
||||
->fields('test', ['name', 'age'])
|
||||
->condition('age', [17, 30], 'IN')
|
||||
->execute()->fetchObject();
|
||||
|
||||
$this->assertFalse($record, 'The rest of the insert aborted as expected.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ class LoggingTest extends DatabaseTestBase {
|
|||
|
||||
db_query('SELECT name FROM {test} WHERE age > :age', [':age' => 25])->fetchCol();
|
||||
|
||||
db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Ringo'], ['target' => 'replica']);//->fetchCol();
|
||||
db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Ringo'], ['target' => 'replica'])->fetchCol();
|
||||
|
||||
$queries1 = Database::getLog('testing1');
|
||||
|
||||
|
@ -113,11 +113,11 @@ class LoggingTest extends DatabaseTestBase {
|
|||
|
||||
db_query('SELECT name FROM {test} WHERE age > :age', [':age' => 25])->fetchCol();
|
||||
|
||||
$old_key = db_set_active('test2');
|
||||
$old_key = Database::setActiveConnection('test2');
|
||||
|
||||
db_query('SELECT age FROM {test} WHERE name = :name', [':name' => 'Ringo'], ['target' => 'replica'])->fetchCol();
|
||||
|
||||
db_set_active($old_key);
|
||||
Database::setActiveConnection($old_key);
|
||||
|
||||
$queries1 = Database::getLog('testing1');
|
||||
$queries2 = Database::getLog('testing1', 'test2');
|
||||
|
|
|
@ -30,7 +30,7 @@ class PrefixInfoTest extends DatabaseTestBase {
|
|||
$db1_schema = $db1_connection->schema();
|
||||
$db2_connection = Database::getConnection('default', 'extra');
|
||||
|
||||
// Get the prefix info for the first databse.
|
||||
// Get the prefix info for the first database.
|
||||
$method = new \ReflectionMethod($db1_schema, 'getPrefixInfo');
|
||||
$method->setAccessible(TRUE);
|
||||
$db1_info = $method->invoke($db1_schema);
|
||||
|
|
|
@ -67,9 +67,15 @@ class QueryTest extends DatabaseTestBase {
|
|||
public function testConditionOperatorArgumentsSQLInjection() {
|
||||
$injection = "IS NOT NULL) ;INSERT INTO {test} (name) VALUES ('test12345678'); -- ";
|
||||
|
||||
// Convert errors to exceptions for testing purposes below.
|
||||
set_error_handler(function ($severity, $message, $filename, $lineno) {
|
||||
throw new \ErrorException($message, 0, $severity, $filename, $lineno);
|
||||
$previous_error_handler = set_error_handler(function ($severity, $message, $filename, $lineno, $context) use (&$previous_error_handler) {
|
||||
// Normalize the filename to use UNIX directory separators.
|
||||
if (preg_match('@core/lib/Drupal/Core/Database/Query/Condition.php$@', str_replace(DIRECTORY_SEPARATOR, '/', $filename))) {
|
||||
// Convert errors to exceptions for testing purposes below.
|
||||
throw new \ErrorException($message, 0, $severity, $filename, $lineno);
|
||||
}
|
||||
if ($previous_error_handler) {
|
||||
return $previous_error_handler($severity, $message, $filename, $lineno, $context);
|
||||
}
|
||||
});
|
||||
try {
|
||||
$result = db_select('test', 't')
|
||||
|
|
|
@ -30,31 +30,31 @@ class RegressionTest extends DatabaseTestBase {
|
|||
])->execute();
|
||||
|
||||
$from_database = db_query('SELECT job FROM {test} WHERE job = :job', [':job' => $job])->fetchField();
|
||||
$this->assertIdentical($job, $from_database, 'The database handles UTF-8 characters cleanly.');
|
||||
$this->assertSame($job, $from_database, 'The database handles UTF-8 characters cleanly.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the db_table_exists() function.
|
||||
*/
|
||||
public function testDBTableExists() {
|
||||
$this->assertIdentical(TRUE, db_table_exists('test'), 'Returns true for existent table.');
|
||||
$this->assertIdentical(FALSE, db_table_exists('nosuchtable'), 'Returns false for nonexistent table.');
|
||||
$this->assertSame(TRUE, $this->connection->schema()->tableExists('test'), 'Returns true for existent table.');
|
||||
$this->assertSame(FALSE, $this->connection->schema()->tableExists('nosuchtable'), 'Returns false for nonexistent table.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the db_field_exists() function.
|
||||
*/
|
||||
public function testDBFieldExists() {
|
||||
$this->assertIdentical(TRUE, db_field_exists('test', 'name'), 'Returns true for existent column.');
|
||||
$this->assertIdentical(FALSE, db_field_exists('test', 'nosuchcolumn'), 'Returns false for nonexistent column.');
|
||||
$this->assertSame(TRUE, db_field_exists('test', 'name'), 'Returns true for existent column.');
|
||||
$this->assertSame(FALSE, db_field_exists('test', 'nosuchcolumn'), 'Returns false for nonexistent column.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the db_index_exists() function.
|
||||
*/
|
||||
public function testDBIndexExists() {
|
||||
$this->assertIdentical(TRUE, db_index_exists('test', 'ages'), 'Returns true for existent index.');
|
||||
$this->assertIdentical(FALSE, db_index_exists('test', 'nosuchindex'), 'Returns false for nonexistent index.');
|
||||
$this->assertSame(TRUE, db_index_exists('test', 'ages'), 'Returns true for existent index.');
|
||||
$this->assertSame(FALSE, db_index_exists('test', 'nosuchindex'), 'Returns false for nonexistent index.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,15 +12,42 @@ use Drupal\Component\Utility\Unicode;
|
|||
/**
|
||||
* Tests table creation and modification via the schema API.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Database\Schema
|
||||
*
|
||||
* @group Database
|
||||
*/
|
||||
class SchemaTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* A global counter for table and field creation.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $counter;
|
||||
|
||||
/**
|
||||
* Connection to the database.
|
||||
*
|
||||
* @var \Drupal\Core\Database\Connection
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* Database schema instance.
|
||||
*
|
||||
* @var \Drupal\Core\Database\Schema
|
||||
*/
|
||||
protected $schema;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->connection = Database::getConnection();
|
||||
$this->schema = $this->connection->schema();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests database interactions.
|
||||
*/
|
||||
|
@ -52,10 +79,10 @@ class SchemaTest extends KernelTestBase {
|
|||
],
|
||||
],
|
||||
];
|
||||
db_create_table('test_table', $table_specification);
|
||||
$this->schema->createTable('test_table', $table_specification);
|
||||
|
||||
// Assert that the table exists.
|
||||
$this->assertTrue(db_table_exists('test_table'), 'The table exists.');
|
||||
$this->assertTrue($this->schema->tableExists('test_table'), 'The table exists.');
|
||||
|
||||
// Assert that the table comment has been set.
|
||||
$this->checkSchemaComment($table_specification['description'], 'test_table');
|
||||
|
@ -63,12 +90,12 @@ class SchemaTest extends KernelTestBase {
|
|||
// Assert that the column comment has been set.
|
||||
$this->checkSchemaComment($table_specification['fields']['test_field']['description'], 'test_table', 'test_field');
|
||||
|
||||
if (Database::getConnection()->databaseType() == 'mysql') {
|
||||
if ($this->connection->databaseType() === 'mysql') {
|
||||
// Make sure that varchar fields have the correct collation.
|
||||
$columns = db_query('SHOW FULL COLUMNS FROM {test_table}');
|
||||
$columns = $this->connection->query('SHOW FULL COLUMNS FROM {test_table}');
|
||||
foreach ($columns as $column) {
|
||||
if ($column->Field == 'test_field_string') {
|
||||
$string_check = ($column->Collation == 'utf8mb4_general_ci');
|
||||
$string_check = ($column->Collation == 'utf8mb4_general_ci' || $column->Collation == 'utf8mb4_0900_ai_ci');
|
||||
}
|
||||
if ($column->Field == 'test_field_string_ascii') {
|
||||
$string_ascii_check = ($column->Collation == 'ascii_general_ci');
|
||||
|
@ -82,91 +109,95 @@ class SchemaTest extends KernelTestBase {
|
|||
$this->assertFalse($this->tryInsert(), 'Insert without a default failed.');
|
||||
|
||||
// Add a default value to the column.
|
||||
db_field_set_default('test_table', 'test_field', 0);
|
||||
$this->schema->fieldSetDefault('test_table', 'test_field', 0);
|
||||
// The insert should now succeed.
|
||||
$this->assertTrue($this->tryInsert(), 'Insert with a default succeeded.');
|
||||
|
||||
// Remove the default.
|
||||
db_field_set_no_default('test_table', 'test_field');
|
||||
$this->schema->fieldSetNoDefault('test_table', 'test_field');
|
||||
// The insert should fail again.
|
||||
$this->assertFalse($this->tryInsert(), 'Insert without a default failed.');
|
||||
|
||||
// Test for fake index and test for the boolean result of indexExists().
|
||||
$index_exists = Database::getConnection()->schema()->indexExists('test_table', 'test_field');
|
||||
$this->assertIdentical($index_exists, FALSE, 'Fake index does not exists');
|
||||
$index_exists = $this->schema->indexExists('test_table', 'test_field');
|
||||
$this->assertIdentical($index_exists, FALSE, 'Fake index does not exist');
|
||||
// Add index.
|
||||
db_add_index('test_table', 'test_field', ['test_field'], $table_specification);
|
||||
$this->schema->addIndex('test_table', 'test_field', ['test_field'], $table_specification);
|
||||
// Test for created index and test for the boolean result of indexExists().
|
||||
$index_exists = Database::getConnection()->schema()->indexExists('test_table', 'test_field');
|
||||
$index_exists = $this->schema->indexExists('test_table', 'test_field');
|
||||
$this->assertIdentical($index_exists, TRUE, 'Index created.');
|
||||
|
||||
// Rename the table.
|
||||
db_rename_table('test_table', 'test_table2');
|
||||
$this->schema->renameTable('test_table', 'test_table2');
|
||||
|
||||
// Index should be renamed.
|
||||
$index_exists = Database::getConnection()->schema()->indexExists('test_table2', 'test_field');
|
||||
$index_exists = $this->schema->indexExists('test_table2', 'test_field');
|
||||
$this->assertTrue($index_exists, 'Index was renamed.');
|
||||
|
||||
// We need the default so that we can insert after the rename.
|
||||
db_field_set_default('test_table2', 'test_field', 0);
|
||||
$this->schema->fieldSetDefault('test_table2', 'test_field', 0);
|
||||
$this->assertFalse($this->tryInsert(), 'Insert into the old table failed.');
|
||||
$this->assertTrue($this->tryInsert('test_table2'), 'Insert into the new table succeeded.');
|
||||
|
||||
// We should have successfully inserted exactly two rows.
|
||||
$count = db_query('SELECT COUNT(*) FROM {test_table2}')->fetchField();
|
||||
$count = $this->connection->query('SELECT COUNT(*) FROM {test_table2}')->fetchField();
|
||||
$this->assertEqual($count, 2, 'Two fields were successfully inserted.');
|
||||
|
||||
// Try to drop the table.
|
||||
db_drop_table('test_table2');
|
||||
$this->assertFalse(db_table_exists('test_table2'), 'The dropped table does not exist.');
|
||||
$this->schema->dropTable('test_table2');
|
||||
$this->assertFalse($this->schema->tableExists('test_table2'), 'The dropped table does not exist.');
|
||||
|
||||
// Recreate the table.
|
||||
db_create_table('test_table', $table_specification);
|
||||
db_field_set_default('test_table', 'test_field', 0);
|
||||
db_add_field('test_table', 'test_serial', ['type' => 'int', 'not null' => TRUE, 'default' => 0, 'description' => 'Added column description.']);
|
||||
$this->schema->createTable('test_table', $table_specification);
|
||||
$this->schema->fieldSetDefault('test_table', 'test_field', 0);
|
||||
$this->schema->addField('test_table', 'test_serial', ['type' => 'int', 'not null' => TRUE, 'default' => 0, 'description' => 'Added column description.']);
|
||||
|
||||
// Assert that the column comment has been set.
|
||||
$this->checkSchemaComment('Added column description.', 'test_table', 'test_serial');
|
||||
|
||||
// Change the new field to a serial column.
|
||||
db_change_field('test_table', 'test_serial', 'test_serial', ['type' => 'serial', 'not null' => TRUE, 'description' => 'Changed column description.'], ['primary key' => ['test_serial']]);
|
||||
$this->schema->changeField('test_table', 'test_serial', 'test_serial', ['type' => 'serial', 'not null' => TRUE, 'description' => 'Changed column description.'], ['primary key' => ['test_serial']]);
|
||||
|
||||
// Assert that the column comment has been set.
|
||||
$this->checkSchemaComment('Changed column description.', 'test_table', 'test_serial');
|
||||
|
||||
$this->assertTrue($this->tryInsert(), 'Insert with a serial succeeded.');
|
||||
$max1 = db_query('SELECT MAX(test_serial) FROM {test_table}')->fetchField();
|
||||
$max1 = $this->connection->query('SELECT MAX(test_serial) FROM {test_table}')->fetchField();
|
||||
$this->assertTrue($this->tryInsert(), 'Insert with a serial succeeded.');
|
||||
$max2 = db_query('SELECT MAX(test_serial) FROM {test_table}')->fetchField();
|
||||
$max2 = $this->connection->query('SELECT MAX(test_serial) FROM {test_table}')->fetchField();
|
||||
$this->assertTrue($max2 > $max1, 'The serial is monotone.');
|
||||
|
||||
$count = db_query('SELECT COUNT(*) FROM {test_table}')->fetchField();
|
||||
$count = $this->connection->query('SELECT COUNT(*) FROM {test_table}')->fetchField();
|
||||
$this->assertEqual($count, 2, 'There were two rows.');
|
||||
|
||||
// Test adding a serial field to an existing table.
|
||||
db_drop_table('test_table');
|
||||
db_create_table('test_table', $table_specification);
|
||||
db_field_set_default('test_table', 'test_field', 0);
|
||||
db_add_field('test_table', 'test_serial', ['type' => 'serial', 'not null' => TRUE], ['primary key' => ['test_serial']]);
|
||||
$this->schema->dropTable('test_table');
|
||||
$this->schema->createTable('test_table', $table_specification);
|
||||
$this->schema->fieldSetDefault('test_table', 'test_field', 0);
|
||||
$this->schema->addField('test_table', 'test_serial', ['type' => 'serial', 'not null' => TRUE], ['primary key' => ['test_serial']]);
|
||||
|
||||
$this->assertPrimaryKeyColumns('test_table', ['test_serial']);
|
||||
// Test the primary key columns.
|
||||
$method = new \ReflectionMethod(get_class($this->schema), 'findPrimaryKeyColumns');
|
||||
$method->setAccessible(TRUE);
|
||||
$this->assertSame(['test_serial'], $method->invoke($this->schema, 'test_table'));
|
||||
|
||||
$this->assertTrue($this->tryInsert(), 'Insert with a serial succeeded.');
|
||||
$max1 = db_query('SELECT MAX(test_serial) FROM {test_table}')->fetchField();
|
||||
$max1 = $this->connection->query('SELECT MAX(test_serial) FROM {test_table}')->fetchField();
|
||||
$this->assertTrue($this->tryInsert(), 'Insert with a serial succeeded.');
|
||||
$max2 = db_query('SELECT MAX(test_serial) FROM {test_table}')->fetchField();
|
||||
$max2 = $this->connection->query('SELECT MAX(test_serial) FROM {test_table}')->fetchField();
|
||||
$this->assertTrue($max2 > $max1, 'The serial is monotone.');
|
||||
|
||||
$count = db_query('SELECT COUNT(*) FROM {test_table}')->fetchField();
|
||||
$count = $this->connection->query('SELECT COUNT(*) FROM {test_table}')->fetchField();
|
||||
$this->assertEqual($count, 2, 'There were two rows.');
|
||||
|
||||
// Test adding a new column and form a composite primary key with it.
|
||||
db_add_field('test_table', 'test_composite_primary_key', ['type' => 'int', 'not null' => TRUE, 'default' => 0], ['primary key' => ['test_serial', 'test_composite_primary_key']]);
|
||||
$this->schema->addField('test_table', 'test_composite_primary_key', ['type' => 'int', 'not null' => TRUE, 'default' => 0], ['primary key' => ['test_serial', 'test_composite_primary_key']]);
|
||||
|
||||
$this->assertPrimaryKeyColumns('test_table', ['test_serial', 'test_composite_primary_key']);
|
||||
// Test the primary key columns.
|
||||
$this->assertSame(['test_serial', 'test_composite_primary_key'], $method->invoke($this->schema, 'test_table'));
|
||||
|
||||
// Test renaming of keys and constraints.
|
||||
db_drop_table('test_table');
|
||||
$this->schema->dropTable('test_table');
|
||||
$table_specification = [
|
||||
'fields' => [
|
||||
'id' => [
|
||||
|
@ -183,46 +214,50 @@ class SchemaTest extends KernelTestBase {
|
|||
'test_field' => ['test_field'],
|
||||
],
|
||||
];
|
||||
db_create_table('test_table', $table_specification);
|
||||
$this->schema->createTable('test_table', $table_specification);
|
||||
|
||||
// Tests for indexes are Database specific.
|
||||
$db_type = Database::getConnection()->databaseType();
|
||||
$db_type = $this->connection->databaseType();
|
||||
|
||||
// Test for existing primary and unique keys.
|
||||
switch ($db_type) {
|
||||
case 'pgsql':
|
||||
$primary_key_exists = Database::getConnection()->schema()->constraintExists('test_table', '__pkey');
|
||||
$unique_key_exists = Database::getConnection()->schema()->constraintExists('test_table', 'test_field' . '__key');
|
||||
$primary_key_exists = $this->schema->constraintExists('test_table', '__pkey');
|
||||
$unique_key_exists = $this->schema->constraintExists('test_table', 'test_field' . '__key');
|
||||
break;
|
||||
|
||||
case 'sqlite':
|
||||
// SQLite does not create a standalone index for primary keys.
|
||||
$primary_key_exists = TRUE;
|
||||
$unique_key_exists = Database::getConnection()->schema()->indexExists('test_table', 'test_field');
|
||||
$unique_key_exists = $this->schema->indexExists('test_table', 'test_field');
|
||||
break;
|
||||
|
||||
default:
|
||||
$primary_key_exists = Database::getConnection()->schema()->indexExists('test_table', 'PRIMARY');
|
||||
$unique_key_exists = Database::getConnection()->schema()->indexExists('test_table', 'test_field');
|
||||
$primary_key_exists = $this->schema->indexExists('test_table', 'PRIMARY');
|
||||
$unique_key_exists = $this->schema->indexExists('test_table', 'test_field');
|
||||
break;
|
||||
}
|
||||
$this->assertIdentical($primary_key_exists, TRUE, 'Primary key created.');
|
||||
$this->assertIdentical($unique_key_exists, TRUE, 'Unique key created.');
|
||||
|
||||
db_rename_table('test_table', 'test_table2');
|
||||
$this->schema->renameTable('test_table', 'test_table2');
|
||||
|
||||
// Test for renamed primary and unique keys.
|
||||
switch ($db_type) {
|
||||
case 'pgsql':
|
||||
$renamed_primary_key_exists = Database::getConnection()->schema()->constraintExists('test_table2', '__pkey');
|
||||
$renamed_unique_key_exists = Database::getConnection()->schema()->constraintExists('test_table2', 'test_field' . '__key');
|
||||
$renamed_primary_key_exists = $this->schema->constraintExists('test_table2', '__pkey');
|
||||
$renamed_unique_key_exists = $this->schema->constraintExists('test_table2', 'test_field' . '__key');
|
||||
break;
|
||||
|
||||
case 'sqlite':
|
||||
// SQLite does not create a standalone index for primary keys.
|
||||
$renamed_primary_key_exists = TRUE;
|
||||
$renamed_unique_key_exists = Database::getConnection()->schema()->indexExists('test_table2', 'test_field');
|
||||
$renamed_unique_key_exists = $this->schema->indexExists('test_table2', 'test_field');
|
||||
break;
|
||||
|
||||
default:
|
||||
$renamed_primary_key_exists = Database::getConnection()->schema()->indexExists('test_table2', 'PRIMARY');
|
||||
$renamed_unique_key_exists = Database::getConnection()->schema()->indexExists('test_table2', 'test_field');
|
||||
$renamed_primary_key_exists = $this->schema->indexExists('test_table2', 'PRIMARY');
|
||||
$renamed_unique_key_exists = $this->schema->indexExists('test_table2', 'test_field');
|
||||
break;
|
||||
}
|
||||
$this->assertIdentical($renamed_primary_key_exists, TRUE, 'Primary key was renamed.');
|
||||
|
@ -231,8 +266,8 @@ class SchemaTest extends KernelTestBase {
|
|||
// For PostgreSQL check in addition that sequence was renamed.
|
||||
if ($db_type == 'pgsql') {
|
||||
// Get information about new table.
|
||||
$info = Database::getConnection()->schema()->queryTableInformation('test_table2');
|
||||
$sequence_name = Database::getConnection()->schema()->prefixNonTable('test_table2', 'id', 'seq');
|
||||
$info = $this->schema->queryTableInformation('test_table2');
|
||||
$sequence_name = $this->schema->prefixNonTable('test_table2', 'id', 'seq');
|
||||
$this->assertEqual($sequence_name, current($info->sequences), 'Sequence was renamed.');
|
||||
}
|
||||
|
||||
|
@ -250,11 +285,11 @@ class SchemaTest extends KernelTestBase {
|
|||
],
|
||||
];
|
||||
try {
|
||||
db_create_table('test_timestamp', $table_specification);
|
||||
$this->schema->createTable('test_timestamp', $table_specification);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
}
|
||||
$this->assertTrue(db_table_exists('test_timestamp'), 'Table with database specific datatype was created.');
|
||||
$this->assertTrue($this->schema->tableExists('test_timestamp'), 'Table with database specific datatype was created.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -263,9 +298,10 @@ class SchemaTest extends KernelTestBase {
|
|||
* @see \Drupal\Core\Database\Driver\mysql\Schema::getNormalizedIndexes()
|
||||
*/
|
||||
public function testIndexLength() {
|
||||
if (Database::getConnection()->databaseType() != 'mysql') {
|
||||
return;
|
||||
if ($this->connection->databaseType() !== 'mysql') {
|
||||
$this->markTestSkipped("The '{$this->connection->databaseType()}' database type does not support setting column length for indexes.");
|
||||
}
|
||||
|
||||
$table_specification = [
|
||||
'fields' => [
|
||||
'id' => [
|
||||
|
@ -312,16 +348,14 @@ class SchemaTest extends KernelTestBase {
|
|||
],
|
||||
],
|
||||
];
|
||||
db_create_table('test_table_index_length', $table_specification);
|
||||
|
||||
$schema_object = Database::getConnection()->schema();
|
||||
$this->schema->createTable('test_table_index_length', $table_specification);
|
||||
|
||||
// Ensure expected exception thrown when adding index with missing info.
|
||||
$expected_exception_message = "MySQL needs the 'test_field_text' field specification in order to normalize the 'test_regular' index";
|
||||
$missing_field_spec = $table_specification;
|
||||
unset($missing_field_spec['fields']['test_field_text']);
|
||||
try {
|
||||
$schema_object->addIndex('test_table_index_length', 'test_separate', [['test_field_text', 200]], $missing_field_spec);
|
||||
$this->schema->addIndex('test_table_index_length', 'test_separate', [['test_field_text', 200]], $missing_field_spec);
|
||||
$this->fail('SchemaException not thrown when adding index with missing information.');
|
||||
}
|
||||
catch (SchemaException $e) {
|
||||
|
@ -329,14 +363,13 @@ class SchemaTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
// Add a separate index.
|
||||
$schema_object->addIndex('test_table_index_length', 'test_separate', [['test_field_text', 200]], $table_specification);
|
||||
$this->schema->addIndex('test_table_index_length', 'test_separate', [['test_field_text', 200]], $table_specification);
|
||||
$table_specification_with_new_index = $table_specification;
|
||||
$table_specification_with_new_index['indexes']['test_separate'] = [['test_field_text', 200]];
|
||||
|
||||
// Ensure that the exceptions of addIndex are thrown as expected.
|
||||
|
||||
try {
|
||||
$schema_object->addIndex('test_table_index_length', 'test_separate', [['test_field_text', 200]], $table_specification);
|
||||
$this->schema->addIndex('test_table_index_length', 'test_separate', [['test_field_text', 200]], $table_specification);
|
||||
$this->fail('\Drupal\Core\Database\SchemaObjectExistsException exception missed.');
|
||||
}
|
||||
catch (SchemaObjectExistsException $e) {
|
||||
|
@ -344,7 +377,7 @@ class SchemaTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
try {
|
||||
$schema_object->addIndex('test_table_non_existing', 'test_separate', [['test_field_text', 200]], $table_specification);
|
||||
$this->schema->addIndex('test_table_non_existing', 'test_separate', [['test_field_text', 200]], $table_specification);
|
||||
$this->fail('\Drupal\Core\Database\SchemaObjectDoesNotExistException exception missed.');
|
||||
}
|
||||
catch (SchemaObjectDoesNotExistException $e) {
|
||||
|
@ -352,7 +385,7 @@ class SchemaTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
// Get index information.
|
||||
$results = db_query('SHOW INDEX FROM {test_table_index_length}');
|
||||
$results = $this->connection->query('SHOW INDEX FROM {test_table_index_length}');
|
||||
$expected_lengths = [
|
||||
'test_regular' => [
|
||||
'test_field_text' => 191,
|
||||
|
@ -395,15 +428,16 @@ class SchemaTest extends KernelTestBase {
|
|||
/**
|
||||
* Tests inserting data into an existing table.
|
||||
*
|
||||
* @param $table
|
||||
* @param string $table
|
||||
* The database table to insert data into.
|
||||
*
|
||||
* @return
|
||||
* @return bool
|
||||
* TRUE if the insert succeeded, FALSE otherwise.
|
||||
*/
|
||||
public function tryInsert($table = 'test_table') {
|
||||
try {
|
||||
db_insert($table)
|
||||
$this->connection
|
||||
->insert($table)
|
||||
->fields(['id' => mt_rand(10, 20)])
|
||||
->execute();
|
||||
return TRUE;
|
||||
|
@ -424,10 +458,10 @@ class SchemaTest extends KernelTestBase {
|
|||
* Optional column to test.
|
||||
*/
|
||||
public function checkSchemaComment($description, $table, $column = NULL) {
|
||||
if (method_exists(Database::getConnection()->schema(), 'getComment')) {
|
||||
$comment = Database::getConnection()->schema()->getComment($table, $column);
|
||||
if (method_exists($this->schema, 'getComment')) {
|
||||
$comment = $this->schema->getComment($table, $column);
|
||||
// The schema comment truncation for mysql is different.
|
||||
if (Database::getConnection()->databaseType() == 'mysql') {
|
||||
if ($this->connection->databaseType() === 'mysql') {
|
||||
$max_length = $column ? 255 : 60;
|
||||
$description = Unicode::truncate($description, $max_length, TRUE, TRUE);
|
||||
}
|
||||
|
@ -445,7 +479,7 @@ class SchemaTest extends KernelTestBase {
|
|||
'fields' => ['serial_column' => ['type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE]],
|
||||
'primary key' => ['serial_column'],
|
||||
];
|
||||
db_create_table($table_name, $table_spec);
|
||||
$this->schema->createTable($table_name, $table_spec);
|
||||
|
||||
// Now set up columns for the other types.
|
||||
$types = ['int', 'float', 'numeric'];
|
||||
|
@ -456,12 +490,12 @@ class SchemaTest extends KernelTestBase {
|
|||
}
|
||||
$column_name = $type . '_column';
|
||||
$table_spec['fields'][$column_name] = $column_spec;
|
||||
db_add_field($table_name, $column_name, $column_spec);
|
||||
$this->schema->addField($table_name, $column_name, $column_spec);
|
||||
}
|
||||
|
||||
// Finally, check each column and try to insert invalid values into them.
|
||||
foreach ($table_spec['fields'] as $column_name => $column_spec) {
|
||||
$this->assertTrue(db_field_exists($table_name, $column_name), format_string('Unsigned @type column was created.', ['@type' => $column_spec['type']]));
|
||||
$this->assertTrue($this->schema->fieldExists($table_name, $column_name), format_string('Unsigned @type column was created.', ['@type' => $column_spec['type']]));
|
||||
$this->assertFalse($this->tryUnsignedInsert($table_name, $column_name), format_string('Unsigned @type column rejected a negative value.', ['@type' => $column_spec['type']]));
|
||||
}
|
||||
}
|
||||
|
@ -469,17 +503,18 @@ class SchemaTest extends KernelTestBase {
|
|||
/**
|
||||
* Tries to insert a negative value into columns defined as unsigned.
|
||||
*
|
||||
* @param $table_name
|
||||
* @param string $table_name
|
||||
* The table to insert.
|
||||
* @param $column_name
|
||||
* @param string $column_name
|
||||
* The column to insert.
|
||||
*
|
||||
* @return
|
||||
* @return bool
|
||||
* TRUE if the insert succeeded, FALSE otherwise.
|
||||
*/
|
||||
public function tryUnsignedInsert($table_name, $column_name) {
|
||||
try {
|
||||
db_insert($table_name)
|
||||
$this->connection
|
||||
->insert($table_name)
|
||||
->fields([$column_name => -1])
|
||||
->execute();
|
||||
return TRUE;
|
||||
|
@ -490,9 +525,9 @@ class SchemaTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tests adding columns to an existing table.
|
||||
* Tests adding columns to an existing table with default and initial value.
|
||||
*/
|
||||
public function testSchemaAddField() {
|
||||
public function testSchemaAddFieldDefaultInitial() {
|
||||
// Test varchar types.
|
||||
foreach ([1, 32, 128, 256, 512] as $length) {
|
||||
$base_field_spec = [
|
||||
|
@ -528,6 +563,11 @@ class SchemaTest extends KernelTestBase {
|
|||
['not null' => TRUE, 'initial' => 1],
|
||||
['not null' => TRUE, 'initial' => 1, 'default' => 7],
|
||||
['not null' => TRUE, 'initial_from_field' => 'serial_column'],
|
||||
[
|
||||
'not null' => TRUE,
|
||||
'initial_from_field' => 'test_nullable_field',
|
||||
'initial' => 100,
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($variations as $variation) {
|
||||
|
@ -581,51 +621,61 @@ class SchemaTest extends KernelTestBase {
|
|||
$table_spec = [
|
||||
'fields' => [
|
||||
'serial_column' => ['type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE],
|
||||
'test_nullable_field' => ['type' => 'int', 'not null' => FALSE],
|
||||
'test_field' => $field_spec,
|
||||
],
|
||||
'primary key' => ['serial_column'],
|
||||
];
|
||||
db_create_table($table_name, $table_spec);
|
||||
$this->schema->createTable($table_name, $table_spec);
|
||||
$this->pass(format_string('Table %table created.', ['%table' => $table_name]));
|
||||
|
||||
// Check the characteristics of the field.
|
||||
$this->assertFieldCharacteristics($table_name, 'test_field', $field_spec);
|
||||
|
||||
// Clean-up.
|
||||
db_drop_table($table_name);
|
||||
$this->schema->dropTable($table_name);
|
||||
|
||||
// Try adding a field to an existing table.
|
||||
$table_name = 'test_table_' . ($this->counter++);
|
||||
$table_spec = [
|
||||
'fields' => [
|
||||
'serial_column' => ['type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE],
|
||||
'test_nullable_field' => ['type' => 'int', 'not null' => FALSE],
|
||||
],
|
||||
'primary key' => ['serial_column'],
|
||||
];
|
||||
db_create_table($table_name, $table_spec);
|
||||
$this->schema->createTable($table_name, $table_spec);
|
||||
$this->pass(format_string('Table %table created.', ['%table' => $table_name]));
|
||||
|
||||
// Insert some rows to the table to test the handling of initial values.
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
db_insert($table_name)
|
||||
$this->connection
|
||||
->insert($table_name)
|
||||
->useDefaults(['serial_column'])
|
||||
->fields(['test_nullable_field' => 100])
|
||||
->execute();
|
||||
}
|
||||
|
||||
db_add_field($table_name, 'test_field', $field_spec);
|
||||
// Add another row with no value for the 'test_nullable_field' column.
|
||||
$this->connection
|
||||
->insert($table_name)
|
||||
->useDefaults(['serial_column'])
|
||||
->execute();
|
||||
|
||||
$this->schema->addField($table_name, 'test_field', $field_spec);
|
||||
$this->pass(format_string('Column %column created.', ['%column' => 'test_field']));
|
||||
|
||||
// Check the characteristics of the field.
|
||||
$this->assertFieldCharacteristics($table_name, 'test_field', $field_spec);
|
||||
|
||||
// Clean-up.
|
||||
db_drop_field($table_name, 'test_field');
|
||||
$this->schema->dropField($table_name, 'test_field');
|
||||
|
||||
// Add back the field and then try to delete a field which is also a primary
|
||||
// key.
|
||||
db_add_field($table_name, 'test_field', $field_spec);
|
||||
db_drop_field($table_name, 'serial_column');
|
||||
db_drop_table($table_name);
|
||||
$this->schema->addField($table_name, 'test_field', $field_spec);
|
||||
$this->schema->dropField($table_name, 'serial_column');
|
||||
$this->schema->dropTable($table_name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -635,7 +685,8 @@ class SchemaTest extends KernelTestBase {
|
|||
// Check that the initial value has been registered.
|
||||
if (isset($field_spec['initial'])) {
|
||||
// There should be no row with a value different then $field_spec['initial'].
|
||||
$count = db_select($table_name)
|
||||
$count = $this->connection
|
||||
->select($table_name)
|
||||
->fields($table_name, ['serial_column'])
|
||||
->condition($field_name, $field_spec['initial'], '<>')
|
||||
->countQuery()
|
||||
|
@ -645,10 +696,11 @@ class SchemaTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
// Check that the initial value from another field has been registered.
|
||||
if (isset($field_spec['initial_from_field'])) {
|
||||
if (isset($field_spec['initial_from_field']) && !isset($field_spec['initial'])) {
|
||||
// There should be no row with a value different than
|
||||
// $field_spec['initial_from_field'].
|
||||
$count = db_select($table_name)
|
||||
$count = $this->connection
|
||||
->select($table_name)
|
||||
->fields($table_name, ['serial_column'])
|
||||
->where($table_name . '.' . $field_spec['initial_from_field'] . ' <> ' . $table_name . '.' . $field_name)
|
||||
->countQuery()
|
||||
|
@ -656,14 +708,27 @@ class SchemaTest extends KernelTestBase {
|
|||
->fetchField();
|
||||
$this->assertEqual($count, 0, 'Initial values from another field filled out.');
|
||||
}
|
||||
elseif (isset($field_spec['initial_from_field']) && isset($field_spec['initial'])) {
|
||||
// There should be no row with a value different than '100'.
|
||||
$count = $this->connection
|
||||
->select($table_name)
|
||||
->fields($table_name, ['serial_column'])
|
||||
->condition($field_name, 100, '<>')
|
||||
->countQuery()
|
||||
->execute()
|
||||
->fetchField();
|
||||
$this->assertEqual($count, 0, 'Initial values from another field or a default value filled out.');
|
||||
}
|
||||
|
||||
// Check that the default value has been registered.
|
||||
if (isset($field_spec['default'])) {
|
||||
// Try inserting a row, and check the resulting value of the new column.
|
||||
$id = db_insert($table_name)
|
||||
$id = $this->connection
|
||||
->insert($table_name)
|
||||
->useDefaults(['serial_column'])
|
||||
->execute();
|
||||
$field_value = db_select($table_name)
|
||||
$field_value = $this->connection
|
||||
->select($table_name)
|
||||
->fields($table_name, [$field_name])
|
||||
->condition('serial_column', $id)
|
||||
->execute()
|
||||
|
@ -673,9 +738,171 @@ class SchemaTest extends KernelTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tests changing columns between types.
|
||||
* Tests various schema changes' effect on the table's primary key.
|
||||
*
|
||||
* @param array $initial_primary_key
|
||||
* The initial primary key of the test table.
|
||||
* @param array $renamed_primary_key
|
||||
* The primary key of the test table after renaming the test field.
|
||||
*
|
||||
* @dataProvider providerTestSchemaCreateTablePrimaryKey
|
||||
*
|
||||
* @covers ::addField
|
||||
* @covers ::changeField
|
||||
* @covers ::dropField
|
||||
* @covers ::findPrimaryKeyColumns
|
||||
*/
|
||||
public function testSchemaChangeField() {
|
||||
public function testSchemaChangePrimaryKey(array $initial_primary_key, array $renamed_primary_key) {
|
||||
$find_primary_key_columns = new \ReflectionMethod(get_class($this->schema), 'findPrimaryKeyColumns');
|
||||
$find_primary_key_columns->setAccessible(TRUE);
|
||||
|
||||
// Test making the field the primary key of the table upon creation.
|
||||
$table_name = 'test_table';
|
||||
$table_spec = [
|
||||
'fields' => [
|
||||
'test_field' => ['type' => 'int', 'not null' => TRUE],
|
||||
'other_test_field' => ['type' => 'int', 'not null' => TRUE],
|
||||
],
|
||||
'primary key' => $initial_primary_key,
|
||||
];
|
||||
$this->schema->createTable($table_name, $table_spec);
|
||||
$this->assertTrue($this->schema->fieldExists($table_name, 'test_field'));
|
||||
$this->assertEquals($initial_primary_key, $find_primary_key_columns->invoke($this->schema, $table_name));
|
||||
|
||||
// Change the field type and make sure the primary key stays in place.
|
||||
$this->schema->changeField($table_name, 'test_field', 'test_field', ['type' => 'varchar', 'length' => 32, 'not null' => TRUE]);
|
||||
$this->assertTrue($this->schema->fieldExists($table_name, 'test_field'));
|
||||
$this->assertEquals($initial_primary_key, $find_primary_key_columns->invoke($this->schema, $table_name));
|
||||
|
||||
// Add some data and change the field type back, to make sure that changing
|
||||
// the type leaves the primary key in place even with existing data.
|
||||
$this->connection
|
||||
->insert($table_name)
|
||||
->fields(['test_field' => 1, 'other_test_field' => 2])
|
||||
->execute();
|
||||
$this->schema->changeField($table_name, 'test_field', 'test_field', ['type' => 'int', 'not null' => TRUE]);
|
||||
$this->assertTrue($this->schema->fieldExists($table_name, 'test_field'));
|
||||
$this->assertEquals($initial_primary_key, $find_primary_key_columns->invoke($this->schema, $table_name));
|
||||
|
||||
// Make sure that adding the primary key can be done as part of changing
|
||||
// a field, as well.
|
||||
$this->schema->dropPrimaryKey($table_name);
|
||||
$this->assertEquals([], $find_primary_key_columns->invoke($this->schema, $table_name));
|
||||
$this->schema->changeField($table_name, 'test_field', 'test_field', ['type' => 'int', 'not null' => TRUE], ['primary key' => $initial_primary_key]);
|
||||
$this->assertTrue($this->schema->fieldExists($table_name, 'test_field'));
|
||||
$this->assertEquals($initial_primary_key, $find_primary_key_columns->invoke($this->schema, $table_name));
|
||||
|
||||
// Rename the field and make sure the primary key was updated.
|
||||
$this->schema->changeField($table_name, 'test_field', 'test_field_renamed', ['type' => 'int', 'not null' => TRUE]);
|
||||
$this->assertTrue($this->schema->fieldExists($table_name, 'test_field_renamed'));
|
||||
$this->assertEquals($renamed_primary_key, $find_primary_key_columns->invoke($this->schema, $table_name));
|
||||
|
||||
// Drop the field and make sure the primary key was dropped, as well.
|
||||
$this->schema->dropField($table_name, 'test_field_renamed');
|
||||
$this->assertFalse($this->schema->fieldExists($table_name, 'test_field_renamed'));
|
||||
$this->assertEquals([], $find_primary_key_columns->invoke($this->schema, $table_name));
|
||||
|
||||
// Add the field again and make sure adding the primary key can be done at
|
||||
// the same time.
|
||||
$this->schema->addField($table_name, 'test_field', ['type' => 'int', 'default' => 0, 'not null' => TRUE], ['primary key' => $initial_primary_key]);
|
||||
$this->assertTrue($this->schema->fieldExists($table_name, 'test_field'));
|
||||
$this->assertEquals($initial_primary_key, $find_primary_key_columns->invoke($this->schema, $table_name));
|
||||
|
||||
// Drop the field again and explicitly add a primary key.
|
||||
$this->schema->dropField($table_name, 'test_field');
|
||||
$this->schema->addPrimaryKey($table_name, ['other_test_field']);
|
||||
$this->assertFalse($this->schema->fieldExists($table_name, 'test_field'));
|
||||
$this->assertEquals(['other_test_field'], $find_primary_key_columns->invoke($this->schema, $table_name));
|
||||
|
||||
// Test that adding a field with a primary key will work even with a
|
||||
// pre-existing primary key.
|
||||
$this->schema->addField($table_name, 'test_field', ['type' => 'int', 'default' => 0, 'not null' => TRUE], ['primary key' => $initial_primary_key]);
|
||||
$this->assertTrue($this->schema->fieldExists($table_name, 'test_field'));
|
||||
$this->assertEquals($initial_primary_key, $find_primary_key_columns->invoke($this->schema, $table_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test cases for SchemaTest::testSchemaCreateTablePrimaryKey().
|
||||
*
|
||||
* @return array
|
||||
* An array of test cases for SchemaTest::testSchemaCreateTablePrimaryKey().
|
||||
*/
|
||||
public function providerTestSchemaCreateTablePrimaryKey() {
|
||||
$tests = [];
|
||||
|
||||
$tests['simple_primary_key'] = [
|
||||
'initial_primary_key' => ['test_field'],
|
||||
'renamed_primary_key' => ['test_field_renamed'],
|
||||
];
|
||||
$tests['composite_primary_key'] = [
|
||||
'initial_primary_key' => ['test_field', 'other_test_field'],
|
||||
'renamed_primary_key' => ['test_field_renamed', 'other_test_field'],
|
||||
];
|
||||
$tests['composite_primary_key_different_order'] = [
|
||||
'initial_primary_key' => ['other_test_field', 'test_field'],
|
||||
'renamed_primary_key' => ['other_test_field', 'test_field_renamed'],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests an invalid field specification as a primary key on table creation.
|
||||
*/
|
||||
public function testInvalidPrimaryKeyOnTableCreation() {
|
||||
// Test making an invalid field the primary key of the table upon creation.
|
||||
$table_name = 'test_table';
|
||||
$table_spec = [
|
||||
'fields' => [
|
||||
'test_field' => ['type' => 'int'],
|
||||
],
|
||||
'primary key' => ['test_field'],
|
||||
];
|
||||
$this->setExpectedException(SchemaException::class, "The 'test_field' field specification does not define 'not null' as TRUE.");
|
||||
$this->schema->createTable($table_name, $table_spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding an invalid field specification as a primary key.
|
||||
*/
|
||||
public function testInvalidPrimaryKeyAddition() {
|
||||
// Test adding a new invalid field to the primary key.
|
||||
$table_name = 'test_table';
|
||||
$table_spec = [
|
||||
'fields' => [
|
||||
'test_field' => ['type' => 'int', 'not null' => TRUE],
|
||||
],
|
||||
'primary key' => ['test_field'],
|
||||
];
|
||||
$this->schema->createTable($table_name, $table_spec);
|
||||
|
||||
$this->setExpectedException(SchemaException::class, "The 'new_test_field' field specification does not define 'not null' as TRUE.");
|
||||
$this->schema->addField($table_name, 'new_test_field', ['type' => 'int'], ['primary key' => ['test_field', 'new_test_field']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests changing the primary key with an invalid field specification.
|
||||
*/
|
||||
public function testInvalidPrimaryKeyChange() {
|
||||
// Test adding a new invalid field to the primary key.
|
||||
$table_name = 'test_table';
|
||||
$table_spec = [
|
||||
'fields' => [
|
||||
'test_field' => ['type' => 'int', 'not null' => TRUE],
|
||||
],
|
||||
'primary key' => ['test_field'],
|
||||
];
|
||||
$this->schema->createTable($table_name, $table_spec);
|
||||
|
||||
$this->setExpectedException(SchemaException::class, "The 'changed_test_field' field specification does not define 'not null' as TRUE.");
|
||||
$this->schema->dropPrimaryKey($table_name);
|
||||
$this->schema->changeField($table_name, 'test_field', 'changed_test_field', ['type' => 'int'], ['primary key' => ['changed_test_field']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests changing columns between types with default and initial values.
|
||||
*/
|
||||
public function testSchemaChangeFieldDefaultInitial() {
|
||||
$field_specs = [
|
||||
['type' => 'int', 'size' => 'normal', 'not null' => FALSE],
|
||||
['type' => 'int', 'size' => 'normal', 'not null' => TRUE, 'initial' => 1, 'default' => 17],
|
||||
|
@ -734,26 +961,28 @@ class SchemaTest extends KernelTestBase {
|
|||
],
|
||||
'primary key' => ['serial_column'],
|
||||
];
|
||||
db_create_table($table_name, $table_spec);
|
||||
$this->schema->createTable($table_name, $table_spec);
|
||||
$this->pass(format_string('Table %table created.', ['%table' => $table_name]));
|
||||
|
||||
// Check the characteristics of the field.
|
||||
$this->assertFieldCharacteristics($table_name, 'test_field', $old_spec);
|
||||
|
||||
// Remove inserted rows.
|
||||
db_truncate($table_name)->execute();
|
||||
$this->connection->truncate($table_name)->execute();
|
||||
|
||||
if ($test_data) {
|
||||
$id = db_insert($table_name)
|
||||
$id = $this->connection
|
||||
->insert($table_name)
|
||||
->fields(['test_field'], [$test_data])
|
||||
->execute();
|
||||
}
|
||||
|
||||
// Change the field.
|
||||
db_change_field($table_name, 'test_field', 'test_field', $new_spec);
|
||||
$this->schema->changeField($table_name, 'test_field', 'test_field', $new_spec);
|
||||
|
||||
if ($test_data) {
|
||||
$field_value = db_select($table_name)
|
||||
$field_value = $this->connection
|
||||
->select($table_name)
|
||||
->fields($table_name, ['test_field'])
|
||||
->condition('serial_column', $id)
|
||||
->execute()
|
||||
|
@ -765,7 +994,142 @@ class SchemaTest extends KernelTestBase {
|
|||
$this->assertFieldCharacteristics($table_name, 'test_field', $new_spec);
|
||||
|
||||
// Clean-up.
|
||||
db_drop_table($table_name);
|
||||
$this->schema->dropTable($table_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::findPrimaryKeyColumns
|
||||
*/
|
||||
public function testFindPrimaryKeyColumns() {
|
||||
$method = new \ReflectionMethod(get_class($this->schema), 'findPrimaryKeyColumns');
|
||||
$method->setAccessible(TRUE);
|
||||
|
||||
// Test with single column primary key.
|
||||
$this->schema->createTable('table_with_pk_0', [
|
||||
'description' => 'Table with primary key.',
|
||||
'fields' => [
|
||||
'id' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'test_field' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
],
|
||||
'primary key' => ['id'],
|
||||
]);
|
||||
$this->assertSame(['id'], $method->invoke($this->schema, 'table_with_pk_0'));
|
||||
|
||||
// Test with multiple column primary key.
|
||||
$this->schema->createTable('table_with_pk_1', [
|
||||
'description' => 'Table with primary key with multiple columns.',
|
||||
'fields' => [
|
||||
'id0' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'id1' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'test_field' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
],
|
||||
'primary key' => ['id0', 'id1'],
|
||||
]);
|
||||
$this->assertSame(['id0', 'id1'], $method->invoke($this->schema, 'table_with_pk_1'));
|
||||
|
||||
// Test with multiple column primary key and not being the first column of
|
||||
// the table definition.
|
||||
$this->schema->createTable('table_with_pk_2', [
|
||||
'description' => 'Table with primary key with multiple columns at the end and in reverted sequence.',
|
||||
'fields' => [
|
||||
'test_field_1' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'test_field_2' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'id3' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'id4' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
],
|
||||
'primary key' => ['id4', 'id3'],
|
||||
]);
|
||||
$this->assertSame(['id4', 'id3'], $method->invoke($this->schema, 'table_with_pk_2'));
|
||||
|
||||
// Test with multiple column primary key in a different order. For the
|
||||
// PostgreSQL and the SQLite drivers is sorting used to get the primary key
|
||||
// columns in the right order.
|
||||
$this->schema->createTable('table_with_pk_3', [
|
||||
'description' => 'Table with primary key with multiple columns at the end and in reverted sequence.',
|
||||
'fields' => [
|
||||
'test_field_1' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'test_field_2' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'id3' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'id4' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
],
|
||||
'primary key' => ['id3', 'test_field_2', 'id4'],
|
||||
]);
|
||||
$this->assertSame(['id3', 'test_field_2', 'id4'], $method->invoke($this->schema, 'table_with_pk_3'));
|
||||
|
||||
// Test with table without a primary key.
|
||||
$this->schema->createTable('table_without_pk_1', [
|
||||
'description' => 'Table without primary key.',
|
||||
'fields' => [
|
||||
'id' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'test_field' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->assertSame([], $method->invoke($this->schema, 'table_without_pk_1'));
|
||||
|
||||
// Test with table with an empty primary key.
|
||||
$this->schema->createTable('table_without_pk_2', [
|
||||
'description' => 'Table without primary key.',
|
||||
'fields' => [
|
||||
'id' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
'test_field' => [
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
],
|
||||
],
|
||||
'primary key' => [],
|
||||
]);
|
||||
$this->assertSame([], $method->invoke($this->schema, 'table_without_pk_2'));
|
||||
|
||||
// Test with non existing table.
|
||||
$this->assertFalse($method->invoke($this->schema, 'non_existing_table'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -774,7 +1138,6 @@ class SchemaTest extends KernelTestBase {
|
|||
public function testFindTables() {
|
||||
// We will be testing with three tables, two of them using the default
|
||||
// prefix and the third one with an individually specified prefix.
|
||||
|
||||
// Set up a new connection with different connection info.
|
||||
$connection_info = Database::getConnectionInfo();
|
||||
|
||||
|
@ -782,8 +1145,8 @@ class SchemaTest extends KernelTestBase {
|
|||
$new_connection_info = $connection_info['default'];
|
||||
$new_connection_info['prefix']['test_2_table'] = $new_connection_info['prefix']['default'] . '_shared_';
|
||||
Database::addConnectionInfo('test', 'default', $new_connection_info);
|
||||
|
||||
Database::setActiveConnection('test');
|
||||
$test_schema = Database::getConnection()->schema();
|
||||
|
||||
// Create the tables.
|
||||
$table_specification = [
|
||||
|
@ -795,12 +1158,12 @@ class SchemaTest extends KernelTestBase {
|
|||
],
|
||||
],
|
||||
];
|
||||
Database::getConnection()->schema()->createTable('test_1_table', $table_specification);
|
||||
Database::getConnection()->schema()->createTable('test_2_table', $table_specification);
|
||||
Database::getConnection()->schema()->createTable('the_third_table', $table_specification);
|
||||
$test_schema->createTable('test_1_table', $table_specification);
|
||||
$test_schema->createTable('test_2_table', $table_specification);
|
||||
$test_schema->createTable('the_third_table', $table_specification);
|
||||
|
||||
// Check the "all tables" syntax.
|
||||
$tables = Database::getConnection()->schema()->findTables('%');
|
||||
$tables = $test_schema->findTables('%');
|
||||
sort($tables);
|
||||
$expected = [
|
||||
// The 'config' table is added by
|
||||
|
@ -814,7 +1177,7 @@ class SchemaTest extends KernelTestBase {
|
|||
$this->assertEqual($tables, $expected, 'All tables were found.');
|
||||
|
||||
// Check the restrictive syntax.
|
||||
$tables = Database::getConnection()->schema()->findTables('test_%');
|
||||
$tables = $test_schema->findTables('test_%');
|
||||
sort($tables);
|
||||
$expected = [
|
||||
'test_1_table',
|
||||
|
@ -826,46 +1189,4 @@ class SchemaTest extends KernelTestBase {
|
|||
Database::setActiveConnection('default');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the primary keys of a table.
|
||||
*
|
||||
* @param string $table_name
|
||||
* The name of the table to check.
|
||||
* @param array $primary_key
|
||||
* The expected key column specifier for a table's primary key.
|
||||
*/
|
||||
protected function assertPrimaryKeyColumns($table_name, array $primary_key = []) {
|
||||
$db_type = Database::getConnection()->databaseType();
|
||||
|
||||
switch ($db_type) {
|
||||
case 'mysql':
|
||||
$result = Database::getConnection()->query("SHOW KEYS FROM {" . $table_name . "} WHERE Key_name = 'PRIMARY'")->fetchAllAssoc('Column_name');
|
||||
$this->assertSame($primary_key, array_keys($result));
|
||||
|
||||
break;
|
||||
case 'pgsql':
|
||||
$result = Database::getConnection()->query("SELECT a.attname, format_type(a.atttypid, a.atttypmod) AS data_type
|
||||
FROM pg_index i
|
||||
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
|
||||
WHERE i.indrelid = '{" . $table_name . "}'::regclass AND i.indisprimary")
|
||||
->fetchAllAssoc('attname');
|
||||
$this->assertSame($primary_key, array_keys($result));
|
||||
|
||||
break;
|
||||
case 'sqlite':
|
||||
// For SQLite we need access to the protected
|
||||
// \Drupal\Core\Database\Driver\sqlite\Schema::introspectSchema() method
|
||||
// because we have no other way of getting the table prefixes needed for
|
||||
// running a straight PRAGMA query.
|
||||
$schema_object = Database::getConnection()->schema();
|
||||
$reflection = new \ReflectionMethod($schema_object, 'introspectSchema');
|
||||
$reflection->setAccessible(TRUE);
|
||||
|
||||
$table_info = $reflection->invoke($schema_object, $table_name);
|
||||
$this->assertSame($primary_key, $table_info['primary key']);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,10 @@ class SelectCloneTest extends DatabaseTestBase {
|
|||
$query->condition('id', $subquery, 'IN');
|
||||
|
||||
$clone = clone $query;
|
||||
|
||||
// Cloned query should have a different unique identifier.
|
||||
$this->assertNotEquals($query->uniqueIdentifier(), $clone->uniqueIdentifier());
|
||||
|
||||
// Cloned query should not be altered by the following modification
|
||||
// happening on original query.
|
||||
$subquery->condition('age', 25, '>');
|
||||
|
@ -34,4 +38,31 @@ class SelectCloneTest extends DatabaseTestBase {
|
|||
$this->assertEqual(2, $query_result, 'The query returns the expected number of rows');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that nested SELECT queries are cloned properly.
|
||||
*/
|
||||
public function testNestedQueryCloning() {
|
||||
$sub_query = $this->connection->select('test', 't');
|
||||
$sub_query->addField('t', 'id', 'id');
|
||||
$sub_query->condition('age', 28, '<');
|
||||
|
||||
$query = $this->connection->select($sub_query, 't');
|
||||
|
||||
$clone = clone $query;
|
||||
|
||||
// Cloned query should have a different unique identifier.
|
||||
$this->assertNotEquals($query->uniqueIdentifier(), $clone->uniqueIdentifier());
|
||||
|
||||
// Cloned query should not be altered by the following modification
|
||||
// happening on original query.
|
||||
$sub_query->condition('age', 25, '>');
|
||||
|
||||
$clone_result = $clone->countQuery()->execute()->fetchField();
|
||||
$query_result = $query->countQuery()->execute()->fetchField();
|
||||
|
||||
// Make sure the cloned query has not been modified.
|
||||
$this->assertEquals(3, $clone_result, 'The cloned query returns the expected number of rows');
|
||||
$this->assertEquals(2, $query_result, 'The query returns the expected number of rows');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\KernelTests\Core\Database;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Database\Query\Condition;
|
||||
use Drupal\Core\Database\RowCountException;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
|
@ -244,7 +245,6 @@ class SelectComplexTest extends DatabaseTestBase {
|
|||
$this->assertEqual($count, 4, 'Counted the correct number of records.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that countQuery properly removes fields and expressions.
|
||||
*/
|
||||
|
@ -312,7 +312,7 @@ class SelectComplexTest extends DatabaseTestBase {
|
|||
$query = db_select('test');
|
||||
$query->addField('test', 'job');
|
||||
$query->condition('name', 'Paul');
|
||||
$query->condition(db_or()->condition('age', 26)->condition('age', 27));
|
||||
$query->condition((new Condition('OR'))->condition('age', 26)->condition('age', 27));
|
||||
|
||||
$job = $query->execute()->fetchField();
|
||||
$this->assertEqual($job, 'Songwriter', 'Correct data retrieved.');
|
||||
|
@ -395,7 +395,7 @@ class SelectComplexTest extends DatabaseTestBase {
|
|||
public function testJoinConditionObject() {
|
||||
// Same test as testDefaultJoin, but with a Condition object.
|
||||
$query = db_select('test_task', 't');
|
||||
$join_cond = db_and()->where('t.pid = p.id');
|
||||
$join_cond = (new Condition('AND'))->where('t.pid = p.id');
|
||||
$people_alias = $query->join('test', 'p', $join_cond);
|
||||
$name_field = $query->addField($people_alias, 'name', 'name');
|
||||
$query->addField('t', 'task', 'task');
|
||||
|
@ -418,7 +418,7 @@ class SelectComplexTest extends DatabaseTestBase {
|
|||
// Test a condition object that creates placeholders.
|
||||
$t1_name = 'John';
|
||||
$t2_name = 'George';
|
||||
$join_cond = db_and()
|
||||
$join_cond = (new Condition('AND'))
|
||||
->condition('t1.name', $t1_name)
|
||||
->condition('t2.name', $t2_name);
|
||||
$query = db_select('test', 't1');
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Database;
|
||||
|
||||
use Drupal\Core\Database\InvalidQueryException;
|
||||
use Drupal\Core\Database\Database;
|
||||
|
||||
|
@ -53,7 +54,7 @@ class SelectTest extends DatabaseTestBase {
|
|||
$records = $result->fetchAll();
|
||||
|
||||
$query = (string) $query;
|
||||
$expected = "/* Testing query comments * / SELECT nid FROM {node}. -- */ SELECT test.name AS name, test.age AS age\nFROM \n{test} test";
|
||||
$expected = "/* Testing query comments * / SELECT nid FROM {node}. -- */ SELECT test.name AS name, test.age AS age\nFROM\n{test} test";
|
||||
|
||||
$this->assertEqual(count($records), 4, 'Returned the correct number of rows.');
|
||||
$this->assertNotIdentical(FALSE, strpos($query, $expected), 'The flattened query contains the sanitised comment string.');
|
||||
|
@ -466,7 +467,6 @@ class SelectTest extends DatabaseTestBase {
|
|||
],
|
||||
];
|
||||
|
||||
|
||||
$database = $this->container->get('database');
|
||||
foreach ($test_groups as $test_group) {
|
||||
$query = $database->select('test', 't');
|
||||
|
@ -496,8 +496,7 @@ class SelectTest extends DatabaseTestBase {
|
|||
];
|
||||
$test_groups[] = [
|
||||
'regex' => '#Singer',
|
||||
'expected' => [
|
||||
],
|
||||
'expected' => [],
|
||||
];
|
||||
|
||||
foreach ($test_groups as $test_group) {
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace Drupal\KernelTests\Core\Database;
|
|||
* @group Database
|
||||
*/
|
||||
class SerializeQueryTest extends DatabaseTestBase {
|
||||
|
||||
/**
|
||||
* Confirms that a query can be serialized and unserialized.
|
||||
*/
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Drupal\KernelTests\Core\Database;
|
||||
|
||||
use Drupal\Core\Database\Query\Condition;
|
||||
|
||||
/**
|
||||
* Tests the Update query builder, complex queries.
|
||||
*
|
||||
|
@ -15,7 +17,7 @@ class UpdateComplexTest extends DatabaseTestBase {
|
|||
public function testOrConditionUpdate() {
|
||||
$update = db_update('test')
|
||||
->fields(['job' => 'Musician'])
|
||||
->condition(db_or()
|
||||
->condition((new Condition('OR'))
|
||||
->condition('name', 'John')
|
||||
->condition('name', 'Paul')
|
||||
);
|
||||
|
|
|
@ -53,4 +53,40 @@ class UpsertTest extends DatabaseTestBase {
|
|||
$this->assertEqual($person->name, 'Meredith', 'Name was not changed.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we can upsert records with a special named column.
|
||||
*/
|
||||
public function testSpecialColumnUpsert() {
|
||||
$num_records_before = $this->connection->query('SELECT COUNT(*) FROM {test_special_columns}')->fetchField();
|
||||
$upsert = $this->connection->upsert('test_special_columns')
|
||||
->key('id')
|
||||
->fields(['id', 'offset', 'function']);
|
||||
|
||||
// Add a new row.
|
||||
$upsert->values([
|
||||
'id' => 2,
|
||||
'offset' => 'Offset 2',
|
||||
'function' => 'Function 2',
|
||||
]);
|
||||
|
||||
// Update an existing row.
|
||||
$upsert->values([
|
||||
'id' => 1,
|
||||
'offset' => 'Offset 1 updated',
|
||||
'function' => 'Function 1 updated',
|
||||
]);
|
||||
|
||||
$upsert->execute();
|
||||
$num_records_after = $this->connection->query('SELECT COUNT(*) FROM {test_special_columns}')->fetchField();
|
||||
$this->assertEquals($num_records_before + 1, $num_records_after, 'Rows were inserted and updated properly.');
|
||||
|
||||
$record = $this->connection->query('SELECT * FROM {test_special_columns} WHERE id = :id', [':id' => 1])->fetch();
|
||||
$this->assertEquals($record->offset, 'Offset 1 updated');
|
||||
$this->assertEquals($record->function, 'Function 1 updated');
|
||||
|
||||
$record = $this->connection->query('SELECT * FROM {test_special_columns} WHERE id = :id', [':id' => 2])->fetch();
|
||||
$this->assertEquals($record->offset, 'Offset 2');
|
||||
$this->assertEquals($record->function, 'Function 2');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Datetime;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests timestamp schema.
|
||||
*
|
||||
* @group Common
|
||||
*/
|
||||
class TimestampSchemaTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['entity_test', 'field', 'field_timestamp_test'];
|
||||
|
||||
/**
|
||||
* Tests if the timestamp field schema is validated.
|
||||
*/
|
||||
public function testTimestampSchema() {
|
||||
$this->installConfig(['field_timestamp_test']);
|
||||
// Make at least an assertion.
|
||||
$this->assertTrue(TRUE);
|
||||
}
|
||||
|
||||
}
|
|
@ -137,7 +137,7 @@ class DrupalKernelTest extends KernelTestBase {
|
|||
// Check that the container itself is not among the persist IDs because it
|
||||
// does not make sense to persist the container itself.
|
||||
$persist_ids = $container->getParameter('persist_ids');
|
||||
$this->assertIdentical(FALSE, array_search('service_container', $persist_ids));
|
||||
$this->assertSame(FALSE, array_search('service_container', $persist_ids));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,6 +184,11 @@ class DrupalKernelTest extends KernelTestBase {
|
|||
$pass = TRUE;
|
||||
}
|
||||
$this->assertTrue($pass, 'Throws LogicException if DrupalKernel::setSitePath() is called after boot');
|
||||
|
||||
// Ensure no LogicException if DrupalKernel::setSitePath() is called with
|
||||
// identical path after boot.
|
||||
$path = $kernel->getSitePath();
|
||||
$kernel->setSitePath($path);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Config\Schema\Mapping;
|
||||
use Drupal\Core\Entity\Plugin\DataType\ConfigEntityAdapter;
|
||||
use Drupal\Core\TypedData\Plugin\DataType\BooleanData;
|
||||
use Drupal\Core\TypedData\Plugin\DataType\IntegerData;
|
||||
use Drupal\Core\TypedData\Plugin\DataType\StringData;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests entity adapter for configuration entities.
|
||||
*
|
||||
* @see \Drupal\Core\Entity\Plugin\DataType\ConfigEntityAdapter
|
||||
*
|
||||
* @group Entity
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Entity\Plugin\DataType\ConfigEntityAdapter
|
||||
*/
|
||||
class ConfigEntityAdapterTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['config_test'];
|
||||
|
||||
/**
|
||||
* The config entity.
|
||||
*
|
||||
* @var \Drupal\config_test\Entity\ConfigTest
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(static::$modules);
|
||||
|
||||
// ConfigTest::create doesn't work with the following exception:
|
||||
// "Multiple entity types found for Drupal\config_test\Entity\ConfigTest."
|
||||
$this->entity = \Drupal::entityTypeManager()->getStorage('config_test')->create([
|
||||
'id' => 'system',
|
||||
'label' => 'foobar',
|
||||
'weight' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Entity\Plugin\DataType\Deriver\EntityDeriver::getDerivativeDefinitions
|
||||
*/
|
||||
public function testEntityDeriver() {
|
||||
$definition = \Drupal::typedDataManager()->getDefinition('entity:config_test');
|
||||
$this->assertEquals(ConfigEntityAdapter::class, $definition['class']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::validate
|
||||
*/
|
||||
public function testValidate() {
|
||||
$adapter = ConfigEntityAdapter::createFromEntity($this->entity);
|
||||
$violations = $adapter->validate();
|
||||
$this->assertEmpty($violations);
|
||||
$this->entity = \Drupal::entityTypeManager()->getStorage('config_test')->create([
|
||||
'id' => 'system',
|
||||
'label' => 'foobar',
|
||||
// Set weight to be a string which should not validate.
|
||||
'weight' => 'very heavy',
|
||||
]);
|
||||
$adapter = ConfigEntityAdapter::createFromEntity($this->entity);
|
||||
$violations = $adapter->validate();
|
||||
$this->assertCount(1, $violations);
|
||||
$violation = $violations->get(0);
|
||||
$this->assertEquals('This value should be of the correct primitive type.', $violation->getMessage());
|
||||
$this->assertEquals('weight', $violation->getPropertyPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getProperties
|
||||
*/
|
||||
public function testGetProperties() {
|
||||
$expected_properties = [
|
||||
'uuid' => StringData::class,
|
||||
'langcode' => StringData::class,
|
||||
'status' => BooleanData::class,
|
||||
'dependencies' => Mapping::class,
|
||||
'id' => StringData::class,
|
||||
'label' => StringData::class,
|
||||
'weight' => IntegerData::class,
|
||||
'style' => StringData::class,
|
||||
'size' => StringData::class,
|
||||
'size_value' => StringData::class,
|
||||
'protected_property' => StringData::class,
|
||||
];
|
||||
$properties = ConfigEntityAdapter::createFromEntity($this->entity)->getProperties();
|
||||
$keys = [];
|
||||
foreach ($properties as $key => $property) {
|
||||
$keys[] = $key;
|
||||
$this->assertInstanceOf($expected_properties[$key], $property);
|
||||
}
|
||||
$this->assertSame(array_keys($expected_properties), $keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getValue
|
||||
*/
|
||||
public function testGetValue() {
|
||||
$adapter = ConfigEntityAdapter::createFromEntity($this->entity);
|
||||
$this->assertEquals($this->entity->weight, $adapter->get('weight')->getValue());
|
||||
$this->assertEquals($this->entity->id(), $adapter->get('id')->getValue());
|
||||
$this->assertEquals($this->entity->label, $adapter->get('label')->getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::set
|
||||
*/
|
||||
public function testSet() {
|
||||
$adapter = ConfigEntityAdapter::createFromEntity($this->entity);
|
||||
// Get the value via typed data to ensure that the typed representation is
|
||||
// updated correctly when the value is set.
|
||||
$this->assertEquals(1, $adapter->get('weight')->getValue());
|
||||
|
||||
$return = $adapter->set('weight', 2);
|
||||
$this->assertSame($adapter, $return);
|
||||
$this->assertEquals(2, $this->entity->weight);
|
||||
// Ensure the typed data is updated via the set too.
|
||||
$this->assertEquals(2, $adapter->get('weight')->getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getString
|
||||
*/
|
||||
public function testGetString() {
|
||||
$adapter = ConfigEntityAdapter::createFromEntity($this->entity);
|
||||
$this->assertEquals('foobar', $adapter->getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::applyDefaultValue
|
||||
*/
|
||||
public function testApplyDefaultValue() {
|
||||
$this->setExpectedException(\BadMethodCallException::class, 'Method not supported');
|
||||
$adapter = ConfigEntityAdapter::createFromEntity($this->entity);
|
||||
$adapter->applyDefaultValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getIterator
|
||||
*/
|
||||
public function testGetIterator() {
|
||||
$adapter = ConfigEntityAdapter::createFromEntity($this->entity);
|
||||
$iterator = $adapter->getIterator();
|
||||
$fields = iterator_to_array($iterator);
|
||||
$expected_fields = [
|
||||
'uuid',
|
||||
'langcode',
|
||||
'status',
|
||||
'dependencies',
|
||||
'id',
|
||||
'label',
|
||||
'weight',
|
||||
'style',
|
||||
'size',
|
||||
'size_value',
|
||||
'protected_property',
|
||||
];
|
||||
$this->assertEquals($expected_fields, array_keys($fields));
|
||||
$this->assertEquals($this->entity->id(), $fields['id']->getValue());
|
||||
|
||||
$adapter->setValue(NULL);
|
||||
$this->assertEquals(new \ArrayIterator([]), $adapter->getIterator());
|
||||
}
|
||||
|
||||
}
|
|
@ -31,10 +31,17 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
/**
|
||||
* The query factory used to construct all queries in the test.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\Query\QueryFactory
|
||||
* @var \Drupal\Core\Config\Entity\Query\QueryFactory
|
||||
*/
|
||||
protected $factory;
|
||||
|
||||
/**
|
||||
* The entity storage used for testing.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $entityStorage;
|
||||
|
||||
/**
|
||||
* Stores all config entities created for the test.
|
||||
*
|
||||
|
@ -46,7 +53,7 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
parent::setUp();
|
||||
|
||||
$this->entities = [];
|
||||
$this->factory = $this->container->get('entity.query');
|
||||
$this->entityStorage = $this->container->get('entity_type.manager')->getStorage('config_query_test');
|
||||
|
||||
// These two are here to make sure that matchArray needs to go over several
|
||||
// non-matches on every levels.
|
||||
|
@ -114,82 +121,82 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
*/
|
||||
public function testConfigEntityQuery() {
|
||||
// Run a test without any condition.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->execute();
|
||||
$this->assertResults(['1', '2', '3', '4', '5']);
|
||||
// No conditions, OR.
|
||||
$this->queryResults = $this->factory->get('config_query_test', 'OR')
|
||||
$this->queryResults = $this->entityStorage->getQuery('OR')
|
||||
->execute();
|
||||
$this->assertResults(['1', '2', '3', '4', '5']);
|
||||
|
||||
// Filter by ID with equality.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', '3')
|
||||
->execute();
|
||||
$this->assertResults(['3']);
|
||||
|
||||
// Filter by label with a known prefix.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('label', 'test_prefix', 'STARTS_WITH')
|
||||
->execute();
|
||||
$this->assertResults(['3']);
|
||||
|
||||
// Filter by label with a known suffix.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('label', 'test_suffix', 'ENDS_WITH')
|
||||
->execute();
|
||||
$this->assertResults(['4']);
|
||||
|
||||
// Filter by label with a known containing word.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('label', 'test_contains', 'CONTAINS')
|
||||
->execute();
|
||||
$this->assertResults(['5']);
|
||||
|
||||
// Filter by ID with the IN operator.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', ['2', '3'], 'IN')
|
||||
->execute();
|
||||
$this->assertResults(['2', '3']);
|
||||
|
||||
// Filter by ID with the implicit IN operator.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', ['2', '3'])
|
||||
->execute();
|
||||
$this->assertResults(['2', '3']);
|
||||
|
||||
// Filter by ID with the > operator.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', '3', '>')
|
||||
->execute();
|
||||
$this->assertResults(['4', '5']);
|
||||
|
||||
// Filter by ID with the >= operator.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', '3', '>=')
|
||||
->execute();
|
||||
$this->assertResults(['3', '4', '5']);
|
||||
|
||||
// Filter by ID with the <> operator.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', '3', '<>')
|
||||
->execute();
|
||||
$this->assertResults(['1', '2', '4', '5']);
|
||||
|
||||
// Filter by ID with the < operator.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', '3', '<')
|
||||
->execute();
|
||||
$this->assertResults(['1', '2']);
|
||||
|
||||
// Filter by ID with the <= operator.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', '3', '<=')
|
||||
->execute();
|
||||
$this->assertResults(['1', '2', '3']);
|
||||
|
||||
// Filter by two conditions on the same field.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('label', 'test_pref', 'STARTS_WITH')
|
||||
->condition('label', 'test_prefix', 'STARTS_WITH')
|
||||
->execute();
|
||||
|
@ -197,7 +204,7 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
|
||||
// Filter by two conditions on different fields. The first query matches for
|
||||
// a different ID, so the result is empty.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('label', 'test_prefix', 'STARTS_WITH')
|
||||
->condition('id', '5')
|
||||
->execute();
|
||||
|
@ -205,7 +212,7 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
|
||||
// Filter by two different conditions on different fields. This time the
|
||||
// first condition matches on one item, but the second one does as well.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('label', 'test_prefix', 'STARTS_WITH')
|
||||
->condition('id', '3')
|
||||
->execute();
|
||||
|
@ -214,7 +221,7 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
// Filter by two different conditions, of which the first one matches for
|
||||
// every entry, the second one as well, but just the third one filters so
|
||||
// that just two are left.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', '1', '>=')
|
||||
->condition('number', 10, '>=')
|
||||
->condition('number', 50, '>=')
|
||||
|
@ -222,30 +229,30 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
$this->assertResults(['3', '5']);
|
||||
|
||||
// Filter with an OR condition group.
|
||||
$this->queryResults = $this->factory->get('config_query_test', 'OR')
|
||||
$this->queryResults = $this->entityStorage->getQuery('OR')
|
||||
->condition('id', 1)
|
||||
->condition('id', '2')
|
||||
->execute();
|
||||
$this->assertResults(['1', '2']);
|
||||
|
||||
// Simplify it with IN.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', ['1', '2'])
|
||||
->execute();
|
||||
$this->assertResults(['1', '2']);
|
||||
// Try explicit IN.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', ['1', '2'], 'IN')
|
||||
->execute();
|
||||
$this->assertResults(['1', '2']);
|
||||
// Try not IN.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', ['1', '2'], 'NOT IN')
|
||||
->execute();
|
||||
$this->assertResults(['3', '4', '5']);
|
||||
|
||||
// Filter with an OR condition group on different fields.
|
||||
$this->queryResults = $this->factory->get('config_query_test', 'OR')
|
||||
$this->queryResults = $this->entityStorage->getQuery('OR')
|
||||
->condition('id', 1)
|
||||
->condition('number', 41)
|
||||
->execute();
|
||||
|
@ -253,14 +260,14 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
|
||||
// Filter with an OR condition group on different fields but matching on the
|
||||
// same entity.
|
||||
$this->queryResults = $this->factory->get('config_query_test', 'OR')
|
||||
$this->queryResults = $this->entityStorage->getQuery('OR')
|
||||
->condition('id', 1)
|
||||
->condition('number', 31)
|
||||
->execute();
|
||||
$this->assertResults(['1']);
|
||||
|
||||
// NO simple conditions, YES complex conditions, 'AND'.
|
||||
$query = $this->factory->get('config_query_test', 'AND');
|
||||
$query = $this->entityStorage->getQuery('AND');
|
||||
$and_condition_1 = $query->orConditionGroup()
|
||||
->condition('id', '2')
|
||||
->condition('label', $this->entities[0]->label);
|
||||
|
@ -274,7 +281,7 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
$this->assertResults(['1']);
|
||||
|
||||
// NO simple conditions, YES complex conditions, 'OR'.
|
||||
$query = $this->factory->get('config_query_test', 'OR');
|
||||
$query = $this->entityStorage->getQuery('OR');
|
||||
$and_condition_1 = $query->andConditionGroup()
|
||||
->condition('id', 1)
|
||||
->condition('label', $this->entities[0]->label);
|
||||
|
@ -288,7 +295,7 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
$this->assertResults(['1', '2']);
|
||||
|
||||
// YES simple conditions, YES complex conditions, 'AND'.
|
||||
$query = $this->factory->get('config_query_test', 'AND');
|
||||
$query = $this->entityStorage->getQuery('AND');
|
||||
$and_condition_1 = $query->orConditionGroup()
|
||||
->condition('id', '2')
|
||||
->condition('label', $this->entities[0]->label);
|
||||
|
@ -303,7 +310,7 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
$this->assertResults(['1']);
|
||||
|
||||
// YES simple conditions, YES complex conditions, 'OR'.
|
||||
$query = $this->factory->get('config_query_test', 'OR');
|
||||
$query = $this->entityStorage->getQuery('OR');
|
||||
$and_condition_1 = $query->orConditionGroup()
|
||||
->condition('id', '2')
|
||||
->condition('label', $this->entities[0]->label);
|
||||
|
@ -318,22 +325,22 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
$this->assertResults(['1', '2', '4', '5']);
|
||||
|
||||
// Test the exists and notExists conditions.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->exists('id')
|
||||
->execute();
|
||||
$this->assertResults(['1', '2', '3', '4', '5']);
|
||||
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->exists('non-existent')
|
||||
->execute();
|
||||
$this->assertResults([]);
|
||||
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->notExists('id')
|
||||
->execute();
|
||||
$this->assertResults([]);
|
||||
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->notExists('non-existent')
|
||||
->execute();
|
||||
$this->assertResults(['1', '2', '3', '4', '5']);
|
||||
|
@ -353,43 +360,43 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
$entity->save();
|
||||
|
||||
// Test 'STARTS_WITH' condition.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', 'foo.bar', 'STARTS_WITH')
|
||||
->execute();
|
||||
$this->assertResults(['foo.bar']);
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', 'f', 'STARTS_WITH')
|
||||
->execute();
|
||||
$this->assertResults(['foo.bar']);
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', 'miss', 'STARTS_WITH')
|
||||
->execute();
|
||||
$this->assertResults([]);
|
||||
|
||||
// Test 'CONTAINS' condition.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', 'foo.bar', 'CONTAINS')
|
||||
->execute();
|
||||
$this->assertResults(['foo.bar']);
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', 'oo.ba', 'CONTAINS')
|
||||
->execute();
|
||||
$this->assertResults(['foo.bar']);
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', 'miss', 'CONTAINS')
|
||||
->execute();
|
||||
$this->assertResults([]);
|
||||
|
||||
// Test 'ENDS_WITH' condition.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', 'foo.bar', 'ENDS_WITH')
|
||||
->execute();
|
||||
$this->assertResults(['foo.bar']);
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', 'r', 'ENDS_WITH')
|
||||
->execute();
|
||||
$this->assertResults(['foo.bar']);
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', 'miss', 'ENDS_WITH')
|
||||
->execute();
|
||||
$this->assertResults([]);
|
||||
|
@ -400,13 +407,13 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
*/
|
||||
public function testCount() {
|
||||
// Test count on no conditions.
|
||||
$count = $this->factory->get('config_query_test')
|
||||
$count = $this->entityStorage->getQuery()
|
||||
->count()
|
||||
->execute();
|
||||
$this->assertIdentical($count, count($this->entities));
|
||||
|
||||
// Test count on a complex query.
|
||||
$query = $this->factory->get('config_query_test', 'OR');
|
||||
$query = $this->entityStorage->getQuery('OR');
|
||||
$and_condition_1 = $query->andConditionGroup()
|
||||
->condition('id', 1)
|
||||
->condition('label', $this->entities[0]->label);
|
||||
|
@ -426,51 +433,51 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
*/
|
||||
public function testSortRange() {
|
||||
// Sort by simple ascending/descending.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->sort('number', 'DESC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['3', '5', '2', '1', '4']);
|
||||
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->sort('number', 'ASC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['4', '1', '2', '5', '3']);
|
||||
|
||||
// Apply some filters and sort.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', '3', '>')
|
||||
->sort('number', 'DESC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['5', '4']);
|
||||
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('id', '3', '>')
|
||||
->sort('number', 'ASC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['4', '5']);
|
||||
|
||||
// Apply a pager and sort.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->sort('number', 'DESC')
|
||||
->range('2', '2')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['2', '1']);
|
||||
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->sort('number', 'ASC')
|
||||
->range('2', '2')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['2', '5']);
|
||||
|
||||
// Add a range to a query without a start parameter.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->range(0, '3')
|
||||
->sort('id', 'ASC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['1', '2', '3']);
|
||||
|
||||
// Apply a pager with limit 4.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->pager('4', 0)
|
||||
->sort('id', 'ASC')
|
||||
->execute();
|
||||
|
@ -488,28 +495,28 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
|
||||
// Sort key: id
|
||||
// Sorting with 'DESC' upper case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->tableSort($header)
|
||||
->sort('id', 'DESC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['5', '4', '3', '2', '1']);
|
||||
|
||||
// Sorting with 'ASC' upper case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->tableSort($header)
|
||||
->sort('id', 'ASC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['1', '2', '3', '4', '5']);
|
||||
|
||||
// Sorting with 'desc' lower case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->tableSort($header)
|
||||
->sort('id', 'desc')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['5', '4', '3', '2', '1']);
|
||||
|
||||
// Sorting with 'asc' lower case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->tableSort($header)
|
||||
->sort('id', 'asc')
|
||||
->execute();
|
||||
|
@ -517,28 +524,28 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
|
||||
// Sort key: number
|
||||
// Sorting with 'DeSc' mixed upper and lower case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->tableSort($header)
|
||||
->sort('number', 'DeSc')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['3', '5', '2', '1', '4']);
|
||||
|
||||
// Sorting with 'AsC' mixed upper and lower case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->tableSort($header)
|
||||
->sort('number', 'AsC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['4', '1', '2', '5', '3']);
|
||||
|
||||
// Sorting with 'dEsC' mixed upper and lower case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->tableSort($header)
|
||||
->sort('number', 'dEsC')
|
||||
->execute();
|
||||
$this->assertIdentical(array_values($this->queryResults), ['3', '5', '2', '1', '4']);
|
||||
|
||||
// Sorting with 'aSc' mixed upper and lower case
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->tableSort($header)
|
||||
->sort('number', 'aSc')
|
||||
->execute();
|
||||
|
@ -549,29 +556,56 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
* Tests dotted path matching.
|
||||
*/
|
||||
public function testDotted() {
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('array.level1.*', 1)
|
||||
->execute();
|
||||
$this->assertResults(['1', '3']);
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('*.level1.level2', 2)
|
||||
->execute();
|
||||
$this->assertResults(['2', '4']);
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('array.level1.*', 3)
|
||||
->execute();
|
||||
$this->assertResults(['5']);
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('array.level1.level2', 3)
|
||||
->execute();
|
||||
$this->assertResults(['5']);
|
||||
// Make sure that values on the wildcard level do not match if there are
|
||||
// sub-keys defined. This must not find anything even if entity 2 has a
|
||||
// top-level key number with value 41.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('*.level1.level2', 41)
|
||||
->execute();
|
||||
$this->assertResults([]);
|
||||
// Make sure that "IS NULL" and "IS NOT NULL" work correctly with
|
||||
// array-valued fields/keys.
|
||||
$all = ['1', '2', '3', '4', '5'];
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->exists('array.level1.level2')
|
||||
->execute();
|
||||
$this->assertResults($all);
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->exists('array.level1')
|
||||
->execute();
|
||||
$this->assertResults($all);
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->exists('array')
|
||||
->execute();
|
||||
$this->assertResults($all);
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->notExists('array.level1.level2')
|
||||
->execute();
|
||||
$this->assertResults([]);
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->notExists('array.level1')
|
||||
->execute();
|
||||
$this->assertResults([]);
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->notExists('array')
|
||||
->execute();
|
||||
$this->assertResults([]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -579,12 +613,12 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
*/
|
||||
public function testCaseSensitivity() {
|
||||
// Filter by label with a known containing case-sensitive word.
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('label', 'TEST', 'CONTAINS')
|
||||
->execute();
|
||||
$this->assertResults(['3', '4', '5']);
|
||||
|
||||
$this->queryResults = $this->factory->get('config_query_test')
|
||||
$this->queryResults = $this->entityStorage->getQuery()
|
||||
->condition('label', 'test', 'CONTAINS')
|
||||
->execute();
|
||||
$this->assertResults(['3', '4', '5']);
|
||||
|
@ -599,7 +633,8 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
$key_value = $this->container->get('keyvalue')->get(QueryFactory::CONFIG_LOOKUP_PREFIX . 'config_test');
|
||||
|
||||
$test_entities = [];
|
||||
$entity = entity_create('config_test', [
|
||||
$storage = \Drupal::entityTypeManager()->getStorage('config_test');
|
||||
$entity = $storage->create([
|
||||
'label' => $this->randomMachineName(),
|
||||
'id' => '1',
|
||||
'style' => 'test',
|
||||
|
@ -608,11 +643,10 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
$entity->enforceIsNew();
|
||||
$entity->save();
|
||||
|
||||
|
||||
$expected[] = $entity->getConfigDependencyName();
|
||||
$this->assertEqual($expected, $key_value->get('style:test'));
|
||||
|
||||
$entity = entity_create('config_test', [
|
||||
$entity = $storage->create([
|
||||
'label' => $this->randomMachineName(),
|
||||
'id' => '2',
|
||||
'style' => 'test',
|
||||
|
@ -623,7 +657,7 @@ class ConfigEntityQueryTest extends KernelTestBase {
|
|||
$expected[] = $entity->getConfigDependencyName();
|
||||
$this->assertEqual($expected, $key_value->get('style:test'));
|
||||
|
||||
$entity = entity_create('config_test', [
|
||||
$entity = $storage->create([
|
||||
'label' => $this->randomMachineName(),
|
||||
'id' => '3',
|
||||
'style' => 'blah',
|
||||
|
|
|
@ -74,7 +74,7 @@ class ContentEntityChangedTest extends EntityKernelTestBase {
|
|||
|
||||
// We can't assert equality here because the created time is set to the
|
||||
// request time, while instances of ChangedTestItem use the current
|
||||
// timestamp every time. Therefor we check if the changed timestamp is
|
||||
// timestamp every time. Therefore we check if the changed timestamp is
|
||||
// between the created time and now.
|
||||
$this->assertTrue(
|
||||
($entity->getChangedTime() >= $entity->get('created')->value) &&
|
||||
|
|
|
@ -131,7 +131,6 @@ class ContentEntityCloneTest extends EntityKernelTestBase {
|
|||
}
|
||||
$this->assertTrue($different_references, 'The entity object and the cloned entity object reference different field item list objects.');
|
||||
|
||||
|
||||
// Reload the entity, initialize one translation, clone it and check that
|
||||
// both entity objects reference different field instances.
|
||||
$entity = $this->reloadEntity($entity);
|
||||
|
@ -298,7 +297,7 @@ class ContentEntityCloneTest extends EntityKernelTestBase {
|
|||
// Retrieve the entity properties.
|
||||
$reflection = new \ReflectionClass($entity);
|
||||
$properties = $reflection->getProperties(~\ReflectionProperty::IS_STATIC);
|
||||
$translation_unique_properties = ['activeLangcode', 'translationInitialize', 'fieldDefinitions', 'languages', 'langcodeKey', 'defaultLangcode', 'defaultLangcodeKey', 'validated', 'validationRequired', 'entityTypeId', 'typedData', 'cacheContexts', 'cacheTags', 'cacheMaxAge', '_serviceIds'];
|
||||
$translation_unique_properties = ['activeLangcode', 'translationInitialize', 'fieldDefinitions', 'languages', 'langcodeKey', 'defaultLangcode', 'defaultLangcodeKey', 'revisionTranslationAffectedKey', 'validated', 'validationRequired', 'entityTypeId', 'typedData', 'cacheContexts', 'cacheTags', 'cacheMaxAge', '_serviceIds', '_entityStorages'];
|
||||
|
||||
foreach ($properties as $property) {
|
||||
// Modify each entity property on the clone and assert that the change is
|
||||
|
@ -307,9 +306,17 @@ class ContentEntityCloneTest extends EntityKernelTestBase {
|
|||
$property->setValue($entity, 'default-value');
|
||||
$property->setValue($translation, 'default-value');
|
||||
$property->setValue($clone, 'test-entity-cloning');
|
||||
$this->assertEquals('default-value', $property->getValue($entity), (string) new FormattableMarkup('Entity property %property_name is not cloned properly.', ['%property_name' => $property->getName()]));
|
||||
$this->assertEquals('default-value', $property->getValue($translation), (string) new FormattableMarkup('Entity property %property_name is not cloned properly.', ['%property_name' => $property->getName()]));
|
||||
$this->assertEquals('test-entity-cloning', $property->getValue($clone), (string) new FormattableMarkup('Entity property %property_name is not cloned properly.', ['%property_name' => $property->getName()]));
|
||||
// Static properties remain the same across all instances of the class.
|
||||
if ($property->isStatic()) {
|
||||
$this->assertEquals('test-entity-cloning', $property->getValue($entity), (string) new FormattableMarkup('Entity property %property_name is not cloned properly.', ['%property_name' => $property->getName()]));
|
||||
$this->assertEquals('test-entity-cloning', $property->getValue($translation), (string) new FormattableMarkup('Entity property %property_name is not cloned properly.', ['%property_name' => $property->getName()]));
|
||||
$this->assertEquals('test-entity-cloning', $property->getValue($clone), (string) new FormattableMarkup('Entity property %property_name is not cloned properly.', ['%property_name' => $property->getName()]));
|
||||
}
|
||||
else {
|
||||
$this->assertEquals('default-value', $property->getValue($entity), (string) new FormattableMarkup('Entity property %property_name is not cloned properly.', ['%property_name' => $property->getName()]));
|
||||
$this->assertEquals('default-value', $property->getValue($translation), (string) new FormattableMarkup('Entity property %property_name is not cloned properly.', ['%property_name' => $property->getName()]));
|
||||
$this->assertEquals('test-entity-cloning', $property->getValue($clone), (string) new FormattableMarkup('Entity property %property_name is not cloned properly.', ['%property_name' => $property->getName()]));
|
||||
}
|
||||
|
||||
// Modify each entity property on the translation entity object and assert
|
||||
// that the change is propagated to the default translation entity object
|
||||
|
|
|
@ -30,10 +30,10 @@ class ContentEntityNullStorageTest extends KernelTestBase {
|
|||
* @see \Drupal\Core\Entity\Query\Null\Query
|
||||
*/
|
||||
public function testEntityQuery() {
|
||||
$this->assertIdentical(0, \Drupal::entityQuery('contact_message')->count()->execute(), 'Counting a null storage returns 0.');
|
||||
$this->assertIdentical([], \Drupal::entityQuery('contact_message')->execute(), 'Querying a null storage returns an empty array.');
|
||||
$this->assertIdentical([], \Drupal::entityQuery('contact_message')->condition('contact_form', 'test')->execute(), 'Querying a null storage returns an empty array and conditions are ignored.');
|
||||
$this->assertIdentical([], \Drupal::entityQueryAggregate('contact_message')->aggregate('name', 'AVG')->execute(), 'Aggregate querying a null storage returns an empty array');
|
||||
$this->assertSame(0, \Drupal::entityQuery('contact_message')->count()->execute(), 'Counting a null storage returns 0.');
|
||||
$this->assertSame([], \Drupal::entityQuery('contact_message')->execute(), 'Querying a null storage returns an empty array.');
|
||||
$this->assertSame([], \Drupal::entityQuery('contact_message')->condition('contact_form', 'test')->execute(), 'Querying a null storage returns an empty array and conditions are ignored.');
|
||||
$this->assertSame([], \Drupal::entityQueryAggregate('contact_message')->aggregate('name', 'AVG')->execute(), 'Aggregate querying a null storage returns an empty array');
|
||||
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ class ContentEntityNullStorageTest extends KernelTestBase {
|
|||
* @see \Drupal\Core\Entity\Event\BundleConfigImportValidate
|
||||
*/
|
||||
public function testDeleteThroughImport() {
|
||||
$this->installConfig(['system']);
|
||||
$contact_form = ContactForm::create(['id' => 'test']);
|
||||
$contact_form->save();
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
|
||||
/**
|
||||
* Tests the ContentEntityStorageBase::createWithSampleValues method.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Entity\ContentEntityStorageBase
|
||||
* @group Entity
|
||||
*/
|
||||
class CreateSampleEntityTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['system', 'field', 'filter', 'text', 'file', 'user', 'node', 'comment', 'taxonomy'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setup();
|
||||
|
||||
$this->installEntitySchema('file');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('node_type');
|
||||
$this->installEntitySchema('file');
|
||||
$this->installEntitySchema('comment');
|
||||
$this->installEntitySchema('comment_type');
|
||||
$this->installEntitySchema('taxonomy_vocabulary');
|
||||
$this->installEntitySchema('taxonomy_term');
|
||||
$this->entityTypeManager = $this->container->get('entity_type.manager');
|
||||
NodeType::create(['type' => 'article', 'name' => 'Article'])->save();
|
||||
NodeType::create(['type' => 'page', 'name' => 'Page'])->save();
|
||||
Vocabulary::create(['name' => 'Tags', 'vid' => 'tags'])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests sample value content entity creation of all types.
|
||||
*
|
||||
* @covers ::createWithSampleValues
|
||||
*/
|
||||
public function testSampleValueContentEntity() {
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $definition) {
|
||||
if ($definition->entityClassImplements(FieldableEntityInterface::class)) {
|
||||
$label = $definition->getKey('label');
|
||||
$values = [];
|
||||
if ($label) {
|
||||
$title = $this->randomString();
|
||||
$values[$label] = $title;
|
||||
}
|
||||
// Create sample entities with bundles.
|
||||
if ($bundle_type = $definition->getBundleEntityType()) {
|
||||
foreach ($this->entityTypeManager->getStorage($bundle_type)->loadMultiple() as $bundle) {
|
||||
$entity = $this->entityTypeManager->getStorage($entity_type_id)->createWithSampleValues($bundle->id(), $values);
|
||||
$violations = $entity->validate();
|
||||
$this->assertCount(0, $violations);
|
||||
if ($label) {
|
||||
$this->assertEquals($title, $entity->label());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create sample entities without bundles.
|
||||
else {
|
||||
$entity = $this->entityTypeManager->getStorage($entity_type_id)->createWithSampleValues(FALSE, $values);
|
||||
$violations = $entity->validate();
|
||||
$this->assertCount(0, $violations);
|
||||
if ($label) {
|
||||
$this->assertEquals($title, $entity->label());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -19,7 +19,7 @@ class DefaultTableMappingIntegrationTest extends EntityKernelTestBase {
|
|||
/**
|
||||
* The table mapping for the tested entity type.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\Sql\TableMappingInterface
|
||||
* @var \Drupal\Core\Entity\Sql\DefaultTableMapping
|
||||
*/
|
||||
protected $tableMapping;
|
||||
|
||||
|
@ -39,11 +39,18 @@ class DefaultTableMappingIntegrationTest extends EntityKernelTestBase {
|
|||
->setName('multivalued_base_field')
|
||||
->setTargetEntityTypeId('entity_test_mulrev')
|
||||
->setTargetBundle('entity_test_mulrev')
|
||||
->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
|
||||
->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
|
||||
// Base fields are non-translatable and non-revisionable by default, but
|
||||
// we explicitly set these values here for extra clarity.
|
||||
->setTranslatable(FALSE)
|
||||
->setRevisionable(FALSE);
|
||||
$this->state->set('entity_test_mulrev.additional_base_field_definitions', $definitions);
|
||||
|
||||
$this->entityManager->clearCachedDefinitions();
|
||||
$this->tableMapping = $this->entityManager->getStorage('entity_test_mulrev')->getTableMapping();
|
||||
|
||||
// Ensure that the tables for the new field are created.
|
||||
\Drupal::entityDefinitionUpdateManager()->applyUpdates();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,4 +75,33 @@ class DefaultTableMappingIntegrationTest extends EntityKernelTestBase {
|
|||
$this->assertEquals($this->tableMapping->getFieldTableName('multivalued_base_field'), $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests DefaultTableMapping::getTableNames().
|
||||
*
|
||||
* @covers ::getTableNames
|
||||
*/
|
||||
public function testGetTableNames() {
|
||||
$storage_definitions = $this->entityManager->getFieldStorageDefinitions('entity_test_mulrev');
|
||||
$dedicated_data_table = $this->tableMapping->getDedicatedDataTableName($storage_definitions['multivalued_base_field']);
|
||||
$dedicated_revision_table = $this->tableMapping->getDedicatedRevisionTableName($storage_definitions['multivalued_base_field']);
|
||||
|
||||
// Check that both the data and the revision tables exist for a multi-valued
|
||||
// base field.
|
||||
$database_schema = \Drupal::database()->schema();
|
||||
$this->assertTrue($database_schema->tableExists($dedicated_data_table));
|
||||
$this->assertTrue($database_schema->tableExists($dedicated_revision_table));
|
||||
|
||||
// Check that the table mapping contains both the data and the revision
|
||||
// tables exist for a multi-valued base field.
|
||||
$expected = [
|
||||
'entity_test_mulrev',
|
||||
'entity_test_mulrev_property_data',
|
||||
'entity_test_mulrev_revision',
|
||||
'entity_test_mulrev_property_revision',
|
||||
$dedicated_data_table,
|
||||
$dedicated_revision_table,
|
||||
];
|
||||
$this->assertEquals($expected, $this->tableMapping->getTableNames());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ class EntityAutocompleteElementFormTest extends EntityKernelTestBase implements
|
|||
|
||||
for ($i = 1; $i < 3; $i++) {
|
||||
$entity = EntityTest::create([
|
||||
'name' => $this->randomMachineName()
|
||||
'name' => $this->randomMachineName(),
|
||||
]);
|
||||
$entity->save();
|
||||
$this->referencedEntities[] = $entity;
|
||||
|
@ -179,12 +179,12 @@ class EntityAutocompleteElementFormTest extends EntityKernelTestBase implements
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) { }
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) { }
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* Tests valid entries in the EntityAutocomplete Form API element.
|
||||
|
@ -297,7 +297,7 @@ class EntityAutocompleteElementFormTest extends EntityKernelTestBase implements
|
|||
$form_state = (new FormState())
|
||||
->setValues([
|
||||
'single_no_validate' => 'single - non-existent label',
|
||||
'single_autocreate_no_validate' => 'single - autocreate non-existent label'
|
||||
'single_autocreate_no_validate' => 'single - autocreate non-existent label',
|
||||
]);
|
||||
$form_builder->submitForm($this, $form_state);
|
||||
|
||||
|
@ -309,7 +309,7 @@ class EntityAutocompleteElementFormTest extends EntityKernelTestBase implements
|
|||
$form_state = (new FormState())
|
||||
->setValues([
|
||||
'single_no_validate' => 'single - non-existent label (42)',
|
||||
'single_autocreate_no_validate' => 'single - autocreate non-existent label (43)'
|
||||
'single_autocreate_no_validate' => 'single - autocreate non-existent label (43)',
|
||||
]);
|
||||
$form_builder->submitForm($this, $form_state);
|
||||
|
||||
|
@ -353,7 +353,7 @@ class EntityAutocompleteElementFormTest extends EntityKernelTestBase implements
|
|||
public function testEntityAutocompleteIdInput() {
|
||||
/** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */
|
||||
$form_builder = $this->container->get('form_builder');
|
||||
//$form = $form_builder->getForm($this);
|
||||
// $form = $form_builder->getForm($this);
|
||||
$form_state = (new FormState())
|
||||
->setMethod('GET')
|
||||
->setValues([
|
||||
|
|
|
@ -8,18 +8,33 @@ use Drupal\Core\Access\AccessibleInterface;
|
|||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Session\AnonymousUserSession;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\entity_test\Entity\EntityTestStringId;
|
||||
use Drupal\entity_test\Entity\EntityTestDefaultAccess;
|
||||
use Drupal\entity_test\Entity\EntityTestNoUuid;
|
||||
use Drupal\entity_test\Entity\EntityTestLabel;
|
||||
use Drupal\entity_test\Entity\EntityTestRev;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Tests the entity access control handler.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Entity\EntityAccessControlHandler
|
||||
* @group Entity
|
||||
*/
|
||||
class EntityAccessControlHandlerTest extends EntityLanguageTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('entity_test_no_uuid');
|
||||
$this->installEntitySchema('entity_test_rev');
|
||||
$this->installEntitySchema('entity_test_string_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts entity access correctly grants or denies access.
|
||||
*/
|
||||
|
@ -199,6 +214,64 @@ class EntityAccessControlHandlerTest extends EntityLanguageTestBase {
|
|||
], $translation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the static access cache works correctly in the absence of an UUID.
|
||||
*
|
||||
* @see entity_test_entity_access()
|
||||
*/
|
||||
public function testEntityWithoutUuidAccessCache() {
|
||||
$account = $this->createUser();
|
||||
|
||||
$entity1 = EntityTestNoUuid::create([
|
||||
'name' => 'Accessible',
|
||||
]);
|
||||
$entity1->save();
|
||||
|
||||
$entity2 = EntityTestNoUuid::create([
|
||||
'name' => 'Inaccessible',
|
||||
]);
|
||||
$entity2->save();
|
||||
|
||||
$this->assertTrue($entity1->access('delete', $account), 'Entity 1 can be deleted.');
|
||||
$this->assertFalse($entity2->access('delete', $account), 'Entity 2 CANNOT be deleted.');
|
||||
|
||||
$entity1
|
||||
->setName('Inaccessible')
|
||||
->setNewRevision();
|
||||
$entity1->save();
|
||||
|
||||
$this->assertFalse($entity1->access('delete', $account), 'Entity 1 revision 2 CANNOT be deleted.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the static access cache works correctly with a UUID and revisions.
|
||||
*
|
||||
* @see entity_test_entity_access()
|
||||
*/
|
||||
public function testEntityWithUuidAccessCache() {
|
||||
$account = $this->createUser();
|
||||
|
||||
$entity1 = EntityTestRev::create([
|
||||
'name' => 'Accessible',
|
||||
]);
|
||||
$entity1->save();
|
||||
|
||||
$entity2 = EntityTestRev::create([
|
||||
'name' => 'Inaccessible',
|
||||
]);
|
||||
$entity2->save();
|
||||
|
||||
$this->assertTrue($entity1->access('delete', $account), 'Entity 1 can be deleted.');
|
||||
$this->assertFalse($entity2->access('delete', $account), 'Entity 2 CANNOT be deleted.');
|
||||
|
||||
$entity1
|
||||
->setName('Inaccessible')
|
||||
->setNewRevision();
|
||||
$entity1->save();
|
||||
|
||||
$this->assertFalse($entity1->access('delete', $account), 'Entity 1 revision 2 CANNOT be deleted.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests hook invocations.
|
||||
*/
|
||||
|
@ -223,4 +296,73 @@ class EntityAccessControlHandlerTest extends EntityLanguageTestBase {
|
|||
$this->assertEqual($state->get('entity_test_entity_test_access'), TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the default access handling for the ID and UUID fields.
|
||||
*
|
||||
* @covers ::fieldAccess
|
||||
* @dataProvider providerTestFieldAccess
|
||||
*/
|
||||
public function testFieldAccess($entity_class, array $entity_create_values, $expected_id_create_access) {
|
||||
// Set up a non-admin user that is allowed to create and update test
|
||||
// entities.
|
||||
\Drupal::currentUser()->setAccount($this->createUser(['uid' => 2], ['administer entity_test content']));
|
||||
|
||||
// Create the entity to test field access with.
|
||||
$entity = $entity_class::create($entity_create_values);
|
||||
|
||||
// On newly-created entities, field access must allow setting the UUID
|
||||
// field.
|
||||
$this->assertTrue($entity->get('uuid')->access('edit'));
|
||||
$this->assertTrue($entity->get('uuid')->access('edit', NULL, TRUE)->isAllowed());
|
||||
// On newly-created entities, field access will not allow setting the ID
|
||||
// field if the ID is of type serial. It will allow access if it is of type
|
||||
// string.
|
||||
$this->assertEquals($expected_id_create_access, $entity->get('id')->access('edit'));
|
||||
$this->assertEquals($expected_id_create_access, $entity->get('id')->access('edit', NULL, TRUE)->isAllowed());
|
||||
|
||||
// Save the entity and check that we can not update the ID or UUID fields
|
||||
// anymore.
|
||||
$entity->save();
|
||||
|
||||
// If the ID has been set as part of the create ensure it has been set
|
||||
// correctly.
|
||||
if (isset($entity_create_values['id'])) {
|
||||
$this->assertSame($entity_create_values['id'], $entity->id());
|
||||
}
|
||||
// The UUID is hard-coded by the data provider.
|
||||
$this->assertSame('60e3a179-79ed-4653-ad52-5e614c8e8fbe', $entity->uuid());
|
||||
$this->assertFalse($entity->get('uuid')->access('edit'));
|
||||
$access_result = $entity->get('uuid')->access('edit', NULL, TRUE);
|
||||
$this->assertTrue($access_result->isForbidden());
|
||||
$this->assertEquals('The entity UUID cannot be changed.', $access_result->getReason());
|
||||
|
||||
// Ensure the ID is still not allowed to be edited.
|
||||
$this->assertFalse($entity->get('id')->access('edit'));
|
||||
$access_result = $entity->get('id')->access('edit', NULL, TRUE);
|
||||
$this->assertTrue($access_result->isForbidden());
|
||||
$this->assertEquals('The entity ID cannot be changed.', $access_result->getReason());
|
||||
}
|
||||
|
||||
public function providerTestFieldAccess() {
|
||||
return [
|
||||
'serial ID entity' => [
|
||||
EntityTest::class,
|
||||
[
|
||||
'name' => 'A test entity',
|
||||
'uuid' => '60e3a179-79ed-4653-ad52-5e614c8e8fbe',
|
||||
],
|
||||
FALSE,
|
||||
],
|
||||
'string ID entity' => [
|
||||
EntityTestStringId::class,
|
||||
[
|
||||
'id' => 'a_test_entity',
|
||||
'name' => 'A test entity',
|
||||
'uuid' => '60e3a179-79ed-4653-ad52-5e614c8e8fbe',
|
||||
],
|
||||
TRUE,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ class EntityBundleFieldTest extends EntityKernelTestBase {
|
|||
$entity->save();
|
||||
entity_test_delete_bundle('custom');
|
||||
|
||||
$table = $table_mapping->getDedicatedDataTableName($entity->getFieldDefinition('custom_bundle_field'));
|
||||
$table = $table_mapping->getDedicatedDataTableName($entity->getFieldDefinition('custom_bundle_field'), TRUE);
|
||||
$result = $this->database->select($table, 'f')
|
||||
->condition('f.entity_id', $entity->id())
|
||||
->condition('deleted', 1)
|
||||
|
@ -105,9 +105,10 @@ class EntityBundleFieldTest extends EntityKernelTestBase {
|
|||
$field_map = \Drupal::entityManager()->getFieldMap();
|
||||
$this->assertFalse(isset($field_map['entity_test']['custom_bundle_field']));
|
||||
|
||||
// @todo Test field purge and table deletion once supported. See
|
||||
// https://www.drupal.org/node/2282119.
|
||||
// $this->assertFalse($this->database->schema()->tableExists($table), 'Custom field table was deleted');
|
||||
// Purge field data, and check that the storage definition has been
|
||||
// completely removed once the data is purged.
|
||||
field_purge_batch(10);
|
||||
$this->assertFalse($this->database->schema()->tableExists($table), 'Custom field table was deleted');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Entity\EntityBundleListener
|
||||
*
|
||||
* @group Entity
|
||||
*/
|
||||
class EntityBundleListenerTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* @covers ::onBundleCreate
|
||||
*
|
||||
* Note: Installing the entity_schema_test module will mask the bug this test
|
||||
* was written to cover, as the field map cache is cleared manually by
|
||||
* \Drupal\Core\Field\FieldDefinitionListener::onFieldDefinitionCreate().
|
||||
*/
|
||||
public function testOnBundleCreate() {
|
||||
$field_map = $this->container->get('entity_field.manager')->getFieldMap();
|
||||
$expected = [
|
||||
'entity_test' => 'entity_test',
|
||||
];
|
||||
$this->assertEquals($expected, $field_map['entity_test']['id']['bundles']);
|
||||
|
||||
entity_test_create_bundle('custom');
|
||||
$field_map = $this->container->get('entity_field.manager')->getFieldMap();
|
||||
$expected = [
|
||||
'entity_test' => 'entity_test',
|
||||
'custom' => 'custom',
|
||||
];
|
||||
$this->assertSame($expected, $field_map['entity_test']['id']['bundles']);
|
||||
}
|
||||
|
||||
}
|
|
@ -57,7 +57,7 @@ class EntityCrudHookTest extends EntityKernelTestBase {
|
|||
/**
|
||||
* Checks the order of CRUD hook execution messages.
|
||||
*
|
||||
* entity_crud_hook_test.module implements all core entity CRUD hooks and
|
||||
* Module entity_crud_hook_test implements all core entity CRUD hooks and
|
||||
* stores a message for each in $GLOBALS['entity_crud_hook_test'].
|
||||
*
|
||||
* @param $messages
|
||||
|
|
|
@ -0,0 +1,645 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRev;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Test decoupled translation revisions.
|
||||
*
|
||||
* @group entity
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Entity\ContentEntityStorageBase
|
||||
*/
|
||||
class EntityDecoupledTranslationRevisionsTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'system',
|
||||
'entity_test',
|
||||
'language',
|
||||
];
|
||||
|
||||
/**
|
||||
* The entity type bundle info service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
|
||||
*/
|
||||
protected $bundleInfo;
|
||||
|
||||
/**
|
||||
* The entity storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\ContentEntityStorageInterface
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* The translations of the test entity.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\ContentEntityInterface[]
|
||||
*/
|
||||
protected $translations;
|
||||
|
||||
/**
|
||||
* The previous revision identifiers for the various revision translations.
|
||||
*
|
||||
* @var int[]
|
||||
*/
|
||||
protected $previousRevisionId = [];
|
||||
|
||||
/**
|
||||
* The previous untranslatable field value.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $previousUntranslatableFieldValue;
|
||||
|
||||
/**
|
||||
* The current edit sequence step index.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $stepIndex;
|
||||
|
||||
/**
|
||||
* The current edit sequence step info.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $stepInfo;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$entity_type_id = 'entity_test_mulrev';
|
||||
$this->installEntitySchema($entity_type_id);
|
||||
$this->storage = $this->container->get('entity_type.manager')
|
||||
->getStorage($entity_type_id);
|
||||
|
||||
$this->installConfig(['language']);
|
||||
$langcodes = ['it', 'fr'];
|
||||
foreach ($langcodes as $langcode) {
|
||||
ConfigurableLanguage::createFromLangcode($langcode)->save();
|
||||
}
|
||||
|
||||
$values = [
|
||||
'name' => $this->randomString(),
|
||||
'status' => 1,
|
||||
];
|
||||
User::create($values)->save();
|
||||
|
||||
// Make sure entity bundles are translatable.
|
||||
$this->state->set('entity_test.translation', TRUE);
|
||||
$this->bundleInfo = \Drupal::service('entity_type.bundle.info');
|
||||
$this->bundleInfo->clearCachedBundles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for ::testDecoupledDefaultRevisions.
|
||||
*/
|
||||
public function dataTestDecoupledPendingRevisions() {
|
||||
$sets = [];
|
||||
|
||||
$sets['Intermixed languages - No initial default translation'][] = [
|
||||
['en', TRUE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
];
|
||||
|
||||
$sets['Intermixed languages - With initial default translation'][] = [
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
];
|
||||
|
||||
$sets['Alternate languages - No initial default translation'][] = [
|
||||
['en', TRUE],
|
||||
['en', FALSE],
|
||||
['en', FALSE],
|
||||
['en', TRUE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['it', FALSE],
|
||||
['it', FALSE],
|
||||
['it', TRUE],
|
||||
];
|
||||
|
||||
$sets['Alternate languages - With initial default translation'][] = [
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
['en', TRUE],
|
||||
['en', FALSE],
|
||||
['en', FALSE],
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
['it', FALSE],
|
||||
['it', FALSE],
|
||||
['it', TRUE],
|
||||
];
|
||||
|
||||
$sets['Multiple languages - No initial default translation'][] = [
|
||||
['en', TRUE],
|
||||
['it', FALSE],
|
||||
['fr', FALSE],
|
||||
['en', FALSE],
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
['fr', FALSE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['fr', TRUE],
|
||||
['it', TRUE],
|
||||
['fr', TRUE],
|
||||
];
|
||||
|
||||
$sets['Multiple languages - With initial default translation'][] = [
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
['fr', TRUE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
['fr', FALSE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['fr', TRUE],
|
||||
['it', TRUE],
|
||||
['fr', TRUE],
|
||||
];
|
||||
|
||||
return $sets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test decoupled default revisions.
|
||||
*
|
||||
* @param array[] $sequence
|
||||
* An array with arrays of arguments for the ::doSaveNewRevision() method as
|
||||
* values. Every child array corresponds to a method invocation.
|
||||
*
|
||||
* @covers ::createRevision
|
||||
*
|
||||
* @dataProvider dataTestDecoupledPendingRevisions
|
||||
*/
|
||||
public function testDecoupledPendingRevisions($sequence) {
|
||||
$revision_id = $this->doTestEditSequence($sequence);
|
||||
$this->assertEquals(count($sequence), $revision_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for ::testUntranslatableFields.
|
||||
*/
|
||||
public function dataTestUntranslatableFields() {
|
||||
$sets = [];
|
||||
|
||||
$sets['Default behavior - Untranslatable fields affect all revisions'] = [
|
||||
[
|
||||
['en', TRUE, TRUE],
|
||||
['it', FALSE, TRUE, FALSE],
|
||||
['en', FALSE, TRUE, FALSE],
|
||||
['en', TRUE, TRUE],
|
||||
['it', TRUE, TRUE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
],
|
||||
FALSE,
|
||||
];
|
||||
|
||||
$sets['Alternative behavior - Untranslatable fields affect only default translation'] = [
|
||||
[
|
||||
['en', TRUE, TRUE],
|
||||
['it', FALSE, TRUE, FALSE],
|
||||
['en', FALSE, TRUE],
|
||||
['it', TRUE, TRUE, FALSE],
|
||||
['it', FALSE],
|
||||
['it', TRUE],
|
||||
['en', TRUE, TRUE],
|
||||
['it', FALSE],
|
||||
['en', FALSE],
|
||||
['it', TRUE],
|
||||
['en', TRUE, TRUE],
|
||||
],
|
||||
TRUE,
|
||||
];
|
||||
|
||||
return $sets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that untranslatable fields are handled correctly.
|
||||
*
|
||||
* @param array[] $sequence
|
||||
* An array with arrays of arguments for the ::doSaveNewRevision() method as
|
||||
* values. Every child array corresponds to a method invocation.
|
||||
*
|
||||
* @param bool $default_translation_affected
|
||||
* Whether untranslatable field changes affect all revisions or only the
|
||||
* default revision.
|
||||
*
|
||||
* @covers ::createRevision
|
||||
* @covers \Drupal\Core\Entity\Plugin\Validation\Constraint\EntityUntranslatableFieldsConstraintValidator::validate
|
||||
*
|
||||
* @dataProvider dataTestUntranslatableFields
|
||||
*/
|
||||
public function testUntranslatableFields($sequence, $default_translation_affected) {
|
||||
// Configure the untranslatable fields edit mode.
|
||||
$this->state->set('entity_test.untranslatable_fields.default_translation_affected', $default_translation_affected);
|
||||
$this->bundleInfo->clearCachedBundles();
|
||||
|
||||
// Test that a new entity is always valid.
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->set('non_mul_field', 0);
|
||||
$violations = $entity->validate();
|
||||
$this->assertEmpty($violations);
|
||||
|
||||
// Test the specified sequence.
|
||||
$this->doTestEditSequence($sequence);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually tests an edit step sequence.
|
||||
*
|
||||
* @param array[] $sequence
|
||||
* An array of sequence steps.
|
||||
*
|
||||
* @return int
|
||||
* The latest saved revision id.
|
||||
*/
|
||||
protected function doTestEditSequence($sequence) {
|
||||
$revision_id = NULL;
|
||||
foreach ($sequence as $index => $step) {
|
||||
$this->stepIndex = $index;
|
||||
$revision_id = call_user_func_array([$this, 'doEditStep'], $step);
|
||||
}
|
||||
return $revision_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a new revision of the test entity.
|
||||
*
|
||||
* @param string $active_langcode
|
||||
* The language of the translation for which a new revision will be saved.
|
||||
* @param bool $default_revision
|
||||
* Whether the revision should be flagged as the default revision.
|
||||
* @param bool $untranslatable_update
|
||||
* (optional) Whether an untranslatable field update should be performed.
|
||||
* Defaults to FALSE.
|
||||
* @param bool $valid
|
||||
* (optional) Whether entity validation is expected to succeed. Defaults to
|
||||
* TRUE.
|
||||
*
|
||||
* @return int
|
||||
* The new revision identifier.
|
||||
*
|
||||
* @throws \Drupal\Core\Entity\EntityStorageException
|
||||
*/
|
||||
protected function doEditStep($active_langcode, $default_revision, $untranslatable_update = FALSE, $valid = TRUE) {
|
||||
$this->stepInfo = [$active_langcode, $default_revision, $untranslatable_update, $valid];
|
||||
|
||||
// If changes to untranslatable fields affect only the default translation,
|
||||
// we can different values for untranslatable fields in the various
|
||||
// revision translations, so we need to track their previous value per
|
||||
// language.
|
||||
$all_translations_affected = !$this->state->get('entity_test.untranslatable_fields.default_translation_affected');
|
||||
$previous_untranslatable_field_langcode = $all_translations_affected ? LanguageInterface::LANGCODE_DEFAULT : $active_langcode;
|
||||
|
||||
// Initialize previous data tracking.
|
||||
if (!isset($this->translations)) {
|
||||
$this->translations[$active_langcode] = EntityTestMulRev::create();
|
||||
$this->previousRevisionId[$active_langcode] = 0;
|
||||
$this->previousUntranslatableFieldValue[$previous_untranslatable_field_langcode] = NULL;
|
||||
}
|
||||
if (!isset($this->translations[$active_langcode])) {
|
||||
$this->translations[$active_langcode] = reset($this->translations)->addTranslation($active_langcode);
|
||||
$this->previousRevisionId[$active_langcode] = 0;
|
||||
$this->previousUntranslatableFieldValue[$active_langcode] = NULL;
|
||||
}
|
||||
|
||||
// We want to update previous data only if we expect a valid result,
|
||||
// otherwise we would be just polluting it with invalid values.
|
||||
if ($valid) {
|
||||
$entity = &$this->translations[$active_langcode];
|
||||
$previous_revision_id = &$this->previousRevisionId[$active_langcode];
|
||||
$previous_untranslatable_field_value = &$this->previousUntranslatableFieldValue[$previous_untranslatable_field_langcode];
|
||||
}
|
||||
else {
|
||||
$entity = clone $this->translations[$active_langcode];
|
||||
$previous_revision_id = $this->previousRevisionId[$active_langcode];
|
||||
$previous_untranslatable_field_value = $this->previousUntranslatableFieldValue[$previous_untranslatable_field_langcode];
|
||||
}
|
||||
|
||||
// Check that after instantiating a new revision for the specified
|
||||
// translation, we are resuming work from where we left the last time. If
|
||||
// that is the case, the label generated for the previous revision should
|
||||
// match the stored one.
|
||||
if (!$entity->isNew()) {
|
||||
$previous_label = NULL;
|
||||
if (!$entity->isNewTranslation()) {
|
||||
$previous_label = $this->generateNewEntityLabel($entity, $previous_revision_id);
|
||||
$latest_affected_revision_id = $this->storage->getLatestTranslationAffectedRevisionId($entity->id(), $entity->language()->getId());
|
||||
}
|
||||
else {
|
||||
// Normally it would make sense to load the default revision in this
|
||||
// case, however that would mean simulating here the logic that we need
|
||||
// to test, thus "masking" possible flaws. To avoid that, we simply
|
||||
// pretend we are starting from an earlier non translated revision.
|
||||
// This ensures that the we can check that the merging logic is applied
|
||||
// also when adding a new translation.
|
||||
$latest_affected_revision_id = 1;
|
||||
}
|
||||
$previous_revision_id = (int) $entity->getLoadedRevisionId();
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $latest_affected_revision */
|
||||
$latest_affected_revision = $this->storage->loadRevision($latest_affected_revision_id);
|
||||
$translation = $latest_affected_revision->hasTranslation($active_langcode) ?
|
||||
$latest_affected_revision->getTranslation($active_langcode) : $latest_affected_revision->addTranslation($active_langcode);
|
||||
$entity = $this->storage->createRevision($translation, $default_revision);
|
||||
$this->assertEquals($default_revision, $entity->isDefaultRevision());
|
||||
$this->assertEquals($translation->getLoadedRevisionId(), $entity->getLoadedRevisionId());
|
||||
$this->assertEquals($previous_label, $entity->label(), $this->formatMessage('Loaded translatable field value does not match the previous one.'));
|
||||
}
|
||||
|
||||
// Check that the previous untranslatable field value is loaded in the new
|
||||
// revision as expected. When we are dealing with a non default translation
|
||||
// the expected value is always the one stored in the default revision, as
|
||||
// untranslatable fields can only be changed in the default translation or
|
||||
// in the default revision, depending on the configured mode.
|
||||
$value = $entity->get('non_mul_field')->value;
|
||||
if (isset($previous_untranslatable_field_value)) {
|
||||
$this->assertEquals($previous_untranslatable_field_value, $value, $this->formatMessage('Loaded untranslatable field value does not match the previous one.'));
|
||||
}
|
||||
elseif (!$entity->isDefaultTranslation()) {
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $default_revision */
|
||||
$default_revision = $this->storage->loadUnchanged($entity->id());
|
||||
$expected_value = $default_revision->get('non_mul_field')->value;
|
||||
$this->assertEquals($expected_value, $value, $this->formatMessage('Loaded untranslatable field value does not match the previous one.'));
|
||||
}
|
||||
|
||||
// Perform a change and store it.
|
||||
$label = $this->generateNewEntityLabel($entity, $previous_revision_id, TRUE);
|
||||
$entity->set('name', $label);
|
||||
if ($untranslatable_update) {
|
||||
// Store the revision ID of the previous untranslatable fields update in
|
||||
// the new value, besides the upcoming revision ID. Useful to analyze test
|
||||
// failures.
|
||||
$prev = 0;
|
||||
if (isset($previous_untranslatable_field_value)) {
|
||||
preg_match('/^\d+ -> (\d+)$/', $previous_untranslatable_field_value, $matches);
|
||||
$prev = $matches[1];
|
||||
}
|
||||
$value = $prev . ' -> ' . ($entity->getLoadedRevisionId() + 1);
|
||||
$entity->set('non_mul_field', $value);
|
||||
$previous_untranslatable_field_value = $value;
|
||||
}
|
||||
|
||||
$violations = $entity->validate();
|
||||
$messages = [];
|
||||
foreach ($violations as $violation) {
|
||||
/** \Symfony\Component\Validator\ConstraintViolationInterface */
|
||||
$messages[] = $violation->getMessage();
|
||||
}
|
||||
$this->assertEquals($valid, !$violations->count(), $this->formatMessage('Validation does not match the expected result: %s', implode(', ', $messages)));
|
||||
|
||||
if ($valid) {
|
||||
$entity->save();
|
||||
|
||||
// Reload the current revision translation and the default revision to
|
||||
// make sure data was stored correctly.
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $this->storage->loadRevision($entity->getRevisionId());
|
||||
$entity = $entity->getTranslation($active_langcode);
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $default_entity */
|
||||
$default_entity = $this->storage->loadUnchanged($entity->id());
|
||||
|
||||
// Verify that the values for the current revision translation match the
|
||||
// expected ones, while for the other translations they match the default
|
||||
// revision. We also need to verify that only the current revision
|
||||
// translation was marked as affected.
|
||||
foreach ($entity->getTranslationLanguages() as $langcode => $language) {
|
||||
$translation = $entity->getTranslation($langcode);
|
||||
$rta_expected = $langcode == $active_langcode || ($untranslatable_update && $all_translations_affected);
|
||||
$this->assertEquals($rta_expected, $translation->isRevisionTranslationAffected(), $this->formatMessage("'$langcode' translation incorrectly affected"));
|
||||
$label_expected = $label;
|
||||
if ($langcode !== $active_langcode) {
|
||||
$default_translation = $default_entity->hasTranslation($langcode) ? $default_entity->getTranslation($langcode) : $default_entity;
|
||||
$label_expected = $default_translation->label();
|
||||
}
|
||||
$this->assertEquals($label_expected, $translation->label(), $this->formatMessage("Incorrect '$langcode' translation label"));
|
||||
}
|
||||
}
|
||||
|
||||
return $entity->getRevisionId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new label for the specified revision.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\ContentEntityInterface $revision
|
||||
* An entity object.
|
||||
* @param int $previous_revision_id
|
||||
* The previous revision identifier for this revision translation.
|
||||
* @param bool $next
|
||||
* (optional) Whether the label describes the current revision or the one
|
||||
* to be created. Defaults to FALSE.
|
||||
*
|
||||
* @return string
|
||||
* A revision label.
|
||||
*/
|
||||
protected function generateNewEntityLabel(ContentEntityInterface $revision, $previous_revision_id, $next = FALSE) {
|
||||
$language_label = $revision->language()->getName();
|
||||
$revision_type = $revision->isDefaultRevision() ? 'Default' : 'Pending';
|
||||
$revision_id = $next ? $this->storage->getLatestRevisionId($revision->id()) + 1 : $revision->getLoadedRevisionId();
|
||||
return sprintf('%s (%s %d -> %d)', $language_label, $revision_type, $previous_revision_id, $revision_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an assertion message.
|
||||
*
|
||||
* @param string $message
|
||||
* The human-readable message.
|
||||
*
|
||||
* @return string
|
||||
* The formatted message.
|
||||
*/
|
||||
protected function formatMessage($message) {
|
||||
$args = func_get_args();
|
||||
array_shift($args);
|
||||
$params = array_merge($args, $this->stepInfo);
|
||||
array_unshift($params, $this->stepIndex + 1);
|
||||
array_unshift($params, '[Step %d] ' . $message . ' (langcode: %s, default_revision: %d, untranslatable_update: %d, valid: %d)');
|
||||
return call_user_func_array('sprintf', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that changes to multiple translations are handled correctly.
|
||||
*
|
||||
* @covers ::createRevision
|
||||
* @covers \Drupal\Core\Entity\Plugin\Validation\Constraint\EntityUntranslatableFieldsConstraintValidator::validate
|
||||
*/
|
||||
public function testMultipleTranslationChanges() {
|
||||
// Configure the untranslatable fields edit mode.
|
||||
$this->state->set('entity_test.untranslatable_fields.default_translation_affected', TRUE);
|
||||
$this->bundleInfo->clearCachedBundles();
|
||||
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->get('name')->value = 'Test 1.1 EN';
|
||||
$entity->get('non_mul_field')->value = 'Test 1.1';
|
||||
$this->storage->save($entity);
|
||||
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $revision */
|
||||
$revision = $this->storage->createRevision($entity->addTranslation('it'));
|
||||
$revision->get('name')->value = 'Test 1.2 IT';
|
||||
$this->storage->save($revision);
|
||||
|
||||
$revision = $this->storage->createRevision($revision->getTranslation('en'), FALSE);
|
||||
$revision->get('non_mul_field')->value = 'Test 1.3';
|
||||
$revision->getTranslation('it')->get('name')->value = 'Test 1.3 IT';
|
||||
$violations = $revision->validate();
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertEquals('Non-translatable fields can only be changed when updating the original language.', $violations[0]->getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that internal properties are preserved while creating a new revision.
|
||||
*/
|
||||
public function testInternalProperties() {
|
||||
$entity = EntityTestMulRev::create();
|
||||
$this->doTestInternalProperties($entity);
|
||||
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->save();
|
||||
$this->doTestInternalProperties($entity);
|
||||
|
||||
/** @var \Drupal\entity_test\Entity\EntityTestMulRev $translation */
|
||||
$translation = EntityTestMulRev::create()->addTranslation('it');
|
||||
$translation->save();
|
||||
$this->doTestInternalProperties($translation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that internal properties are preserved for the specified entity.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
|
||||
* An entity object.
|
||||
*/
|
||||
protected function doTestInternalProperties(ContentEntityInterface $entity) {
|
||||
$this->assertFalse($entity->isValidationRequired());
|
||||
$entity->setValidationRequired(TRUE);
|
||||
$this->assertTrue($entity->isValidationRequired());
|
||||
$new_revision = $this->storage->createRevision($entity);
|
||||
$this->assertTrue($new_revision->isValidationRequired());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that deleted translations are not accidentally restored.
|
||||
*
|
||||
* @covers ::createRevision
|
||||
*/
|
||||
public function testRemovedTranslations() {
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = EntityTestMulRev::create(['name' => 'Test 1.1 EN']);
|
||||
$this->storage->save($entity);
|
||||
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $it_revision */
|
||||
$it_revision = $this->storage->createRevision($entity->addTranslation('it'));
|
||||
$it_revision->set('name', 'Test 1.2 IT');
|
||||
$this->storage->save($it_revision);
|
||||
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $en_revision */
|
||||
$en_revision = $this->storage->createRevision($it_revision->getUntranslated(), FALSE);
|
||||
$en_revision->set('name', 'Test 1.3 EN');
|
||||
$this->storage->save($en_revision);
|
||||
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $en_revision */
|
||||
$it_revision = $this->storage->createRevision($it_revision);
|
||||
$en_revision = $it_revision->getUntranslated();
|
||||
$en_revision->removeTranslation('it');
|
||||
$this->storage->save($en_revision);
|
||||
|
||||
$revision_id = $this->storage->getLatestTranslationAffectedRevisionId($entity->id(), 'en');
|
||||
$en_revision = $this->storage->loadRevision($revision_id);
|
||||
$en_revision = $this->storage->createRevision($en_revision);
|
||||
$en_revision->set('name', 'Test 1.5 EN');
|
||||
$this->storage->save($en_revision);
|
||||
$en_revision = $this->storage->loadRevision($en_revision->getRevisionId());
|
||||
$this->assertFalse($en_revision->hasTranslation('it'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the revision create hook works as expected.
|
||||
*
|
||||
* @covers ::createRevision
|
||||
*/
|
||||
public function testCreateRevisionHook() {
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->get('name')->value = 'revision_create_test_en';
|
||||
$this->storage->save($entity);
|
||||
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $translation */
|
||||
$translation = $entity->addTranslation('it');
|
||||
$translation->set('name', 'revision_create_test_it');
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $revision */
|
||||
$revision = $this->storage->createRevision($translation, FALSE, TRUE);
|
||||
|
||||
// Assert that the alter hook can alter the new revision.
|
||||
$this->assertEquals('revision_create_test_it_altered', $revision->get('name')->value);
|
||||
|
||||
// Assert the data passed to the hook.
|
||||
$data = $this->state->get('entity_test.hooks');
|
||||
$this->assertEquals('revision_create_test_it', $data['entity_test_mulrev_revision_create']['entity']->get('name')->value);
|
||||
$this->assertEquals('revision_create_test_it_altered', $data['entity_test_mulrev_revision_create']['new_revision']->get('name')->value);
|
||||
$this->assertFalse($data['entity_test_mulrev_revision_create']['entity']->isNewRevision());
|
||||
$this->assertTrue($data['entity_test_mulrev_revision_create']['new_revision']->isNewRevision());
|
||||
$this->assertTrue($data['entity_test_mulrev_revision_create']['entity']->isDefaultRevision());
|
||||
$this->assertFalse($data['entity_test_mulrev_revision_create']['new_revision']->isDefaultRevision());
|
||||
$this->assertTrue($data['entity_test_mulrev_revision_create']['keep_untranslatable_fields']);
|
||||
|
||||
$this->assertEquals('revision_create_test_it', $data['entity_revision_create']['entity']->get('name')->value);
|
||||
$this->assertEquals('revision_create_test_it_altered', $data['entity_revision_create']['new_revision']->get('name')->value);
|
||||
$this->assertFalse($data['entity_revision_create']['entity']->isNewRevision());
|
||||
$this->assertTrue($data['entity_revision_create']['new_revision']->isNewRevision());
|
||||
$this->assertTrue($data['entity_revision_create']['entity']->isDefaultRevision());
|
||||
$this->assertFalse($data['entity_revision_create']['new_revision']->isDefaultRevision());
|
||||
$this->assertTrue($data['entity_revision_create']['keep_untranslatable_fields']);
|
||||
|
||||
// Test again with different arguments.
|
||||
$translation->isDefaultRevision(FALSE);
|
||||
$this->storage->createRevision($translation);
|
||||
$data = $this->state->get('entity_test.hooks');
|
||||
$this->assertFalse($data['entity_revision_create']['entity']->isNewRevision());
|
||||
$this->assertTrue($data['entity_revision_create']['new_revision']->isNewRevision());
|
||||
$this->assertFalse($data['entity_revision_create']['entity']->isDefaultRevision());
|
||||
$this->assertTrue($data['entity_revision_create']['new_revision']->isDefaultRevision());
|
||||
$this->assertNull($data['entity_revision_create']['keep_untranslatable_fields']);
|
||||
|
||||
$this->assertFalse($data['entity_test_mulrev_revision_create']['entity']->isNewRevision());
|
||||
$this->assertTrue($data['entity_test_mulrev_revision_create']['new_revision']->isNewRevision());
|
||||
$this->assertFalse($data['entity_test_mulrev_revision_create']['entity']->isDefaultRevision());
|
||||
$this->assertTrue($data['entity_test_mulrev_revision_create']['new_revision']->isDefaultRevision());
|
||||
$this->assertNull($data['entity_test_mulrev_revision_create']['keep_untranslatable_fields']);
|
||||
}
|
||||
|
||||
}
|
|
@ -11,14 +11,17 @@ use Drupal\Core\Entity\EntityStorageException;
|
|||
use Drupal\Core\Entity\EntityTypeEvents;
|
||||
use Drupal\Core\Entity\Exception\FieldStorageDefinitionUpdateForbiddenException;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\Field\FieldException;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionEvents;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\entity_test_update\Entity\EntityTestUpdate;
|
||||
use Drupal\system\Tests\Entity\EntityDefinitionTestTrait;
|
||||
use Drupal\Tests\system\Functional\Entity\Traits\EntityDefinitionTestTrait;
|
||||
|
||||
/**
|
||||
* Tests EntityDefinitionUpdateManager functionality.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Entity\EntityDefinitionUpdateManager
|
||||
*
|
||||
* @group Entity
|
||||
*/
|
||||
class EntityDefinitionUpdateTest extends EntityKernelTestBase {
|
||||
|
@ -112,9 +115,10 @@ class EntityDefinitionUpdateTest extends EntityKernelTestBase {
|
|||
// The revision key is now defined, so the revision field needs to be
|
||||
// created.
|
||||
t('The %field_name field needs to be installed.', ['%field_name' => 'Revision ID']),
|
||||
t('The %field_name field needs to be installed.', ['%field_name' => 'Default revision']),
|
||||
],
|
||||
];
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected); //, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
|
||||
// Run the update and ensure the revision table is created.
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
|
@ -388,53 +392,247 @@ class EntityDefinitionUpdateTest extends EntityKernelTestBase {
|
|||
|
||||
/**
|
||||
* Tests deleting a base field when it has existing data.
|
||||
*
|
||||
* @dataProvider baseFieldDeleteWithExistingDataTestCases
|
||||
*/
|
||||
public function testBaseFieldDeleteWithExistingData() {
|
||||
public function testBaseFieldDeleteWithExistingData($entity_type_id, $create_entity_revision, $base_field_revisionable) {
|
||||
/** @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage */
|
||||
$storage = $this->entityManager->getStorage($entity_type_id);
|
||||
$schema_handler = $this->database->schema();
|
||||
|
||||
// Create an entity without the base field, to ensure NULL values are not
|
||||
// added to the dedicated table storage to be purged.
|
||||
$entity = $storage->create();
|
||||
$entity->save();
|
||||
|
||||
// Add the base field and run the update.
|
||||
$this->addBaseField();
|
||||
$this->addBaseField('string', $entity_type_id, $base_field_revisionable);
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
|
||||
// Save an entity with the base field populated.
|
||||
$this->entityManager->getStorage('entity_test_update')->create(['new_base_field' => 'foo'])->save();
|
||||
/** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
|
||||
$table_mapping = $storage->getTableMapping();
|
||||
$storage_definition = $this->entityManager->getLastInstalledFieldStorageDefinitions($entity_type_id)['new_base_field'];
|
||||
|
||||
// Remove the base field and apply updates. It's expected to throw an
|
||||
// exception.
|
||||
// @todo Revisit that expectation once purging is implemented for
|
||||
// all fields: https://www.drupal.org/node/2282119.
|
||||
$this->removeBaseField();
|
||||
try {
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->fail('FieldStorageDefinitionUpdateForbiddenException thrown when trying to apply an update that deletes a non-purgeable field with data.');
|
||||
// Save an entity with the base field populated.
|
||||
$entity = $storage->create(['new_base_field' => 'foo']);
|
||||
$entity->save();
|
||||
|
||||
if ($create_entity_revision) {
|
||||
$entity->setNewRevision(TRUE);
|
||||
$entity->new_base_field = 'bar';
|
||||
$entity->save();
|
||||
}
|
||||
catch (FieldStorageDefinitionUpdateForbiddenException $e) {
|
||||
$this->pass('FieldStorageDefinitionUpdateForbiddenException thrown when trying to apply an update that deletes a non-purgeable field with data.');
|
||||
|
||||
// Remove the base field and apply updates.
|
||||
$this->removeBaseField($entity_type_id);
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
|
||||
// Check that the base field's column is deleted.
|
||||
$this->assertFalse($schema_handler->fieldExists($entity_type_id, 'new_base_field'), 'Column deleted from shared table for new_base_field.');
|
||||
|
||||
// Check that a dedicated 'deleted' table was created for the deleted base
|
||||
// field.
|
||||
$dedicated_deleted_table_name = $table_mapping->getDedicatedDataTableName($storage_definition, TRUE);
|
||||
$this->assertTrue($schema_handler->tableExists($dedicated_deleted_table_name), 'A dedicated table was created for the deleted new_base_field.');
|
||||
|
||||
// Check that the deleted field's data is preserved in the dedicated
|
||||
// 'deleted' table.
|
||||
$result = $this->database->select($dedicated_deleted_table_name, 't')
|
||||
->fields('t')
|
||||
->execute()
|
||||
->fetchAll();
|
||||
$this->assertCount(1, $result);
|
||||
|
||||
$expected = [
|
||||
'bundle' => $entity->bundle(),
|
||||
'deleted' => '1',
|
||||
'entity_id' => $entity->id(),
|
||||
'revision_id' => $create_entity_revision ? $entity->getRevisionId() : $entity->id(),
|
||||
'langcode' => $entity->language()->getId(),
|
||||
'delta' => '0',
|
||||
'new_base_field_value' => $entity->new_base_field->value,
|
||||
];
|
||||
// Use assertEquals and not assertSame here to prevent that a different
|
||||
// sequence of the columns in the table will affect the check.
|
||||
$this->assertEquals($expected, (array) $result[0]);
|
||||
|
||||
if ($create_entity_revision) {
|
||||
$dedicated_deleted_revision_table_name = $table_mapping->getDedicatedRevisionTableName($storage_definition, TRUE);
|
||||
$this->assertTrue($schema_handler->tableExists($dedicated_deleted_revision_table_name), 'A dedicated revision table was created for the deleted new_base_field.');
|
||||
|
||||
$result = $this->database->select($dedicated_deleted_revision_table_name, 't')
|
||||
->fields('t')
|
||||
->orderBy('revision_id', 'DESC')
|
||||
->execute()
|
||||
->fetchAll();
|
||||
// Only one row will be created for non-revisionable base fields.
|
||||
$this->assertCount($base_field_revisionable ? 2 : 1, $result);
|
||||
|
||||
// Use assertEquals and not assertSame here to prevent that a different
|
||||
// sequence of the columns in the table will affect the check.
|
||||
$this->assertEquals([
|
||||
'bundle' => $entity->bundle(),
|
||||
'deleted' => '1',
|
||||
'entity_id' => $entity->id(),
|
||||
'revision_id' => '3',
|
||||
'langcode' => $entity->language()->getId(),
|
||||
'delta' => '0',
|
||||
'new_base_field_value' => 'bar',
|
||||
], (array) $result[0]);
|
||||
|
||||
// Two rows only exist if the base field is revisionable.
|
||||
if ($base_field_revisionable) {
|
||||
// Use assertEquals and not assertSame here to prevent that a different
|
||||
// sequence of the columns in the table will affect the check.
|
||||
$this->assertEquals([
|
||||
'bundle' => $entity->bundle(),
|
||||
'deleted' => '1',
|
||||
'entity_id' => $entity->id(),
|
||||
'revision_id' => '2',
|
||||
'langcode' => $entity->language()->getId(),
|
||||
'delta' => '0',
|
||||
'new_base_field_value' => 'foo',
|
||||
], (array) $result[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the field storage definition is marked for purging.
|
||||
$deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
|
||||
$this->assertArrayHasKey($storage_definition->getUniqueStorageIdentifier(), $deleted_storage_definitions, 'The base field is marked for purging.');
|
||||
|
||||
// Purge field data, and check that the storage definition has been
|
||||
// completely removed once the data is purged.
|
||||
field_purge_batch(10);
|
||||
$deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
|
||||
$this->assertEmpty($deleted_storage_definitions, 'The base field has been deleted.');
|
||||
$this->assertFalse($schema_handler->tableExists($dedicated_deleted_table_name), 'A dedicated field table was deleted after new_base_field was purged.');
|
||||
|
||||
if (isset($dedicated_deleted_revision_table_name)) {
|
||||
$this->assertFalse($schema_handler->tableExists($dedicated_deleted_revision_table_name), 'A dedicated field revision table was deleted after new_base_field was purged.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cases for ::testBaseFieldDeleteWithExistingData.
|
||||
*/
|
||||
public function baseFieldDeleteWithExistingDataTestCases() {
|
||||
return [
|
||||
'Non-revisionable entity type' => [
|
||||
'entity_test_update',
|
||||
FALSE,
|
||||
FALSE,
|
||||
],
|
||||
'Non-revisionable custom data table' => [
|
||||
'entity_test_mul',
|
||||
FALSE,
|
||||
FALSE,
|
||||
],
|
||||
'Non-revisionable entity type, revisionable base field' => [
|
||||
'entity_test_update',
|
||||
FALSE,
|
||||
TRUE,
|
||||
],
|
||||
'Non-revisionable custom data table, revisionable base field' => [
|
||||
'entity_test_mul',
|
||||
FALSE,
|
||||
TRUE,
|
||||
],
|
||||
'Revisionable entity type, non revisionable base field' => [
|
||||
'entity_test_mulrev',
|
||||
TRUE,
|
||||
FALSE,
|
||||
],
|
||||
'Revisionable entity type, revisionable base field' => [
|
||||
'entity_test_mulrev',
|
||||
TRUE,
|
||||
TRUE,
|
||||
],
|
||||
'Non-translatable revisionable entity type, revisionable base field' => [
|
||||
'entity_test_rev',
|
||||
TRUE,
|
||||
TRUE,
|
||||
],
|
||||
'Non-translatable revisionable entity type, non-revisionable base field' => [
|
||||
'entity_test_rev',
|
||||
TRUE,
|
||||
FALSE,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deleting a bundle field when it has existing data.
|
||||
*/
|
||||
public function testBundleFieldDeleteWithExistingData() {
|
||||
/** @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage */
|
||||
$storage = $this->entityManager->getStorage('entity_test_update');
|
||||
$schema_handler = $this->database->schema();
|
||||
|
||||
// Add the bundle field and run the update.
|
||||
$this->addBundleField();
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
|
||||
/** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
|
||||
$table_mapping = $storage->getTableMapping();
|
||||
$storage_definition = $this->entityManager->getLastInstalledFieldStorageDefinitions('entity_test_update')['new_bundle_field'];
|
||||
|
||||
// Check that the bundle field has a dedicated table.
|
||||
$dedicated_table_name = $table_mapping->getDedicatedDataTableName($storage_definition);
|
||||
$this->assertTrue($schema_handler->tableExists($dedicated_table_name), 'The bundle field uses a dedicated table.');
|
||||
|
||||
// Save an entity with the bundle field populated.
|
||||
entity_test_create_bundle('custom');
|
||||
$this->entityManager->getStorage('entity_test_update')->create(['type' => 'test_bundle', 'new_bundle_field' => 'foo'])->save();
|
||||
$entity = $storage->create(['type' => 'test_bundle', 'new_bundle_field' => 'foo']);
|
||||
$entity->save();
|
||||
|
||||
// Remove the bundle field and apply updates. It's expected to throw an
|
||||
// exception.
|
||||
// @todo Revisit that expectation once purging is implemented for
|
||||
// all fields: https://www.drupal.org/node/2282119.
|
||||
// Remove the bundle field and apply updates.
|
||||
$this->removeBundleField();
|
||||
try {
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->fail('FieldStorageDefinitionUpdateForbiddenException thrown when trying to apply an update that deletes a non-purgeable field with data.');
|
||||
}
|
||||
catch (FieldStorageDefinitionUpdateForbiddenException $e) {
|
||||
$this->pass('FieldStorageDefinitionUpdateForbiddenException thrown when trying to apply an update that deletes a non-purgeable field with data.');
|
||||
}
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
|
||||
// Check that the table of the bundle field has been renamed to use a
|
||||
// 'deleted' table name.
|
||||
$this->assertFalse($schema_handler->tableExists($dedicated_table_name), 'The dedicated table of the bundle field no longer exists.');
|
||||
|
||||
$dedicated_deleted_table_name = $table_mapping->getDedicatedDataTableName($storage_definition, TRUE);
|
||||
$this->assertTrue($schema_handler->tableExists($dedicated_deleted_table_name), 'The dedicated table of the bundle fields has been renamed to use the "deleted" name.');
|
||||
|
||||
// Check that the deleted field's data is preserved in the dedicated
|
||||
// 'deleted' table.
|
||||
$result = $this->database->select($dedicated_deleted_table_name, 't')
|
||||
->fields('t')
|
||||
->execute()
|
||||
->fetchAll();
|
||||
$this->assertCount(1, $result);
|
||||
|
||||
$expected = [
|
||||
'bundle' => $entity->bundle(),
|
||||
'deleted' => '1',
|
||||
'entity_id' => $entity->id(),
|
||||
'revision_id' => $entity->id(),
|
||||
'langcode' => $entity->language()->getId(),
|
||||
'delta' => '0',
|
||||
'new_bundle_field_value' => $entity->new_bundle_field->value,
|
||||
];
|
||||
// Use assertEquals and not assertSame here to prevent that a different
|
||||
// sequence of the columns in the table will affect the check.
|
||||
$this->assertEquals($expected, (array) $result[0]);
|
||||
|
||||
// Check that the field definition is marked for purging.
|
||||
$deleted_field_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldDefinitions();
|
||||
$this->assertArrayHasKey($storage_definition->getUniqueIdentifier(), $deleted_field_definitions, 'The bundle field is marked for purging.');
|
||||
|
||||
// Check that the field storage definition is marked for purging.
|
||||
$deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
|
||||
$this->assertArrayHasKey($storage_definition->getUniqueStorageIdentifier(), $deleted_storage_definitions, 'The bundle field storage is marked for purging.');
|
||||
|
||||
// Purge field data, and check that the storage definition has been
|
||||
// completely removed once the data is purged.
|
||||
field_purge_batch(10);
|
||||
$deleted_field_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldDefinitions();
|
||||
$this->assertEmpty($deleted_field_definitions, 'The bundle field has been deleted.');
|
||||
$deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
|
||||
$this->assertEmpty($deleted_storage_definitions, 'The bundle field storage has been deleted.');
|
||||
$this->assertFalse($schema_handler->tableExists($dedicated_deleted_table_name), 'The dedicated table of the bundle field has been removed.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -776,6 +974,11 @@ class EntityDefinitionUpdateTest extends EntityKernelTestBase {
|
|||
// of a NOT NULL constraint.
|
||||
$this->makeBaseFieldEntityKey();
|
||||
|
||||
// Field storage CRUD operations use the last installed entity type
|
||||
// definition so we need to update it before doing any other field storage
|
||||
// updates.
|
||||
$this->entityDefinitionUpdateManager->updateEntityType($this->state->get('entity_test_update.entity_type'));
|
||||
|
||||
// Try to apply the update and verify they fail since we have a NULL value.
|
||||
$message = 'An error occurs when trying to enabling NOT NULL constraints with NULL data.';
|
||||
try {
|
||||
|
@ -817,4 +1020,180 @@ class EntityDefinitionUpdateTest extends EntityKernelTestBase {
|
|||
$this->assertFalse($this->entityDefinitionUpdateManager->needsUpdates(), 'Entity and field schema data are correctly detected.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding a base field with initial values.
|
||||
*/
|
||||
public function testInitialValue() {
|
||||
$storage = \Drupal::entityTypeManager()->getStorage('entity_test_update');
|
||||
$db_schema = $this->database->schema();
|
||||
|
||||
// Create two entities before adding the base field.
|
||||
/** @var \Drupal\entity_test\Entity\EntityTestUpdate $entity */
|
||||
$storage->create()->save();
|
||||
$storage->create()->save();
|
||||
|
||||
// Add a base field with an initial value.
|
||||
$this->addBaseField();
|
||||
$storage_definition = BaseFieldDefinition::create('string')
|
||||
->setLabel(t('A new base field'))
|
||||
->setInitialValue('test value');
|
||||
|
||||
$this->assertFalse($db_schema->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' does not exist before applying the update.");
|
||||
$this->entityDefinitionUpdateManager->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $storage_definition);
|
||||
$this->assertTrue($db_schema->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' has been created on the 'entity_test_update' table.");
|
||||
|
||||
// Check that the initial values have been applied.
|
||||
$storage = \Drupal::entityTypeManager()->getStorage('entity_test_update');
|
||||
$entities = $storage->loadMultiple();
|
||||
$this->assertEquals('test value', $entities[1]->get('new_base_field')->value);
|
||||
$this->assertEquals('test value', $entities[2]->get('new_base_field')->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding a base field with initial values inherited from another field.
|
||||
*
|
||||
* @dataProvider initialValueFromFieldTestCases
|
||||
*/
|
||||
public function testInitialValueFromField($default_initial_value, $expected_value) {
|
||||
$storage = \Drupal::entityTypeManager()->getStorage('entity_test_update');
|
||||
$db_schema = $this->database->schema();
|
||||
|
||||
// Create two entities before adding the base field.
|
||||
/** @var \Drupal\entity_test_update\Entity\EntityTestUpdate $entity */
|
||||
$storage->create([
|
||||
'name' => 'First entity',
|
||||
'test_single_property' => 'test existing value',
|
||||
])->save();
|
||||
|
||||
// The second entity does not have any value for the 'test_single_property'
|
||||
// field, allowing us to test the 'default_value' parameter of
|
||||
// \Drupal\Core\Field\BaseFieldDefinition::setInitialValueFromField().
|
||||
$storage->create([
|
||||
'name' => 'Second entity',
|
||||
])->save();
|
||||
|
||||
// Add a base field with an initial value inherited from another field.
|
||||
$definitions['new_base_field'] = BaseFieldDefinition::create('string')
|
||||
->setName('new_base_field')
|
||||
->setLabel('A new base field')
|
||||
->setInitialValueFromField('name');
|
||||
$definitions['another_base_field'] = BaseFieldDefinition::create('string')
|
||||
->setName('another_base_field')
|
||||
->setLabel('Another base field')
|
||||
->setInitialValueFromField('test_single_property', $default_initial_value);
|
||||
|
||||
$this->state->set('entity_test_update.additional_base_field_definitions', $definitions);
|
||||
|
||||
$this->assertFalse($db_schema->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' does not exist before applying the update.");
|
||||
$this->assertFalse($db_schema->fieldExists('entity_test_update', 'another_base_field'), "New field 'another_base_field' does not exist before applying the update.");
|
||||
$this->entityDefinitionUpdateManager->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $definitions['new_base_field']);
|
||||
$this->entityDefinitionUpdateManager->installFieldStorageDefinition('another_base_field', 'entity_test_update', 'entity_test', $definitions['another_base_field']);
|
||||
$this->assertTrue($db_schema->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' has been created on the 'entity_test_update' table.");
|
||||
$this->assertTrue($db_schema->fieldExists('entity_test_update', 'another_base_field'), "New field 'another_base_field' has been created on the 'entity_test_update' table.");
|
||||
|
||||
// Check that the initial values have been applied.
|
||||
$storage = \Drupal::entityTypeManager()->getStorage('entity_test_update');
|
||||
$entities = $storage->loadMultiple();
|
||||
$this->assertEquals('First entity', $entities[1]->get('new_base_field')->value);
|
||||
$this->assertEquals('Second entity', $entities[2]->get('new_base_field')->value);
|
||||
|
||||
$this->assertEquals('test existing value', $entities[1]->get('another_base_field')->value);
|
||||
$this->assertEquals($expected_value, $entities[2]->get('another_base_field')->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cases for ::testInitialValueFromField.
|
||||
*/
|
||||
public function initialValueFromFieldTestCases() {
|
||||
return [
|
||||
'literal value' => [
|
||||
'test initial value',
|
||||
'test initial value',
|
||||
],
|
||||
'indexed array' => [
|
||||
['value' => 'test initial value'],
|
||||
'test initial value',
|
||||
],
|
||||
'empty array' => [
|
||||
[],
|
||||
NULL,
|
||||
],
|
||||
'null' => [
|
||||
NULL,
|
||||
NULL,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the error handling when using initial values from another field.
|
||||
*/
|
||||
public function testInitialValueFromFieldErrorHandling() {
|
||||
// Check that setting invalid values for 'initial value from field' doesn't
|
||||
// work.
|
||||
try {
|
||||
$this->addBaseField();
|
||||
$storage_definition = BaseFieldDefinition::create('string')
|
||||
->setLabel(t('A new base field'))
|
||||
->setInitialValueFromField('field_that_does_not_exist');
|
||||
$this->entityDefinitionUpdateManager->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $storage_definition);
|
||||
$this->fail('Using a non-existent field as initial value does not work.');
|
||||
}
|
||||
catch (FieldException $e) {
|
||||
$this->assertEquals('Illegal initial value definition on new_base_field: The field field_that_does_not_exist does not exist.', $e->getMessage());
|
||||
$this->pass('Using a non-existent field as initial value does not work.');
|
||||
}
|
||||
|
||||
try {
|
||||
$this->addBaseField();
|
||||
$storage_definition = BaseFieldDefinition::create('integer')
|
||||
->setLabel(t('A new base field'))
|
||||
->setInitialValueFromField('name');
|
||||
$this->entityDefinitionUpdateManager->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $storage_definition);
|
||||
$this->fail('Using a field of a different type as initial value does not work.');
|
||||
}
|
||||
catch (FieldException $e) {
|
||||
$this->assertEquals('Illegal initial value definition on new_base_field: The field types do not match.', $e->getMessage());
|
||||
$this->pass('Using a field of a different type as initial value does not work.');
|
||||
}
|
||||
|
||||
try {
|
||||
// Add a base field that will not be stored in the shared tables.
|
||||
$initial_field = BaseFieldDefinition::create('string')
|
||||
->setName('initial_field')
|
||||
->setLabel(t('An initial field'))
|
||||
->setCardinality(2);
|
||||
$this->state->set('entity_test_update.additional_base_field_definitions', ['initial_field' => $initial_field]);
|
||||
$this->entityDefinitionUpdateManager->installFieldStorageDefinition('initial_field', 'entity_test_update', 'entity_test', $initial_field);
|
||||
|
||||
// Now add the base field which will try to use the previously added field
|
||||
// as the source of its initial values.
|
||||
$new_base_field = BaseFieldDefinition::create('string')
|
||||
->setName('new_base_field')
|
||||
->setLabel(t('A new base field'))
|
||||
->setInitialValueFromField('initial_field');
|
||||
$this->state->set('entity_test_update.additional_base_field_definitions', ['initial_field' => $initial_field, 'new_base_field' => $new_base_field]);
|
||||
$this->entityDefinitionUpdateManager->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $new_base_field);
|
||||
$this->fail('Using a field that is not stored in the shared tables as initial value does not work.');
|
||||
}
|
||||
catch (FieldException $e) {
|
||||
$this->assertEquals('Illegal initial value definition on new_base_field: Both fields have to be stored in the shared entity tables.', $e->getMessage());
|
||||
$this->pass('Using a field that is not stored in the shared tables as initial value does not work.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getEntityTypes
|
||||
*/
|
||||
public function testGetEntityTypes() {
|
||||
$entity_type_definitions = $this->entityDefinitionUpdateManager->getEntityTypes();
|
||||
|
||||
// Ensure that we have at least one entity type to check below.
|
||||
$this->assertGreaterThanOrEqual(1, count($entity_type_definitions));
|
||||
|
||||
foreach ($entity_type_definitions as $entity_type_id => $entity_type) {
|
||||
$this->assertEquals($this->entityDefinitionUpdateManager->getEntityType($entity_type_id), $entity_type);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -63,7 +63,6 @@ class EntityDisplayFormBaseTest extends KernelTestBase {
|
|||
])
|
||||
->shouldBeCalled();
|
||||
|
||||
|
||||
// An initially visible field, with a submitted region change.
|
||||
$entity->getComponent('field_start_visible_change_region')
|
||||
->willReturn([
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Component\Uuid\Uuid;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
|
||||
/**
|
||||
* Tests default values for entity fields.
|
||||
|
@ -47,8 +47,8 @@ class EntityFieldDefaultValueTest extends EntityKernelTestBase {
|
|||
->create();
|
||||
$definition = $this->entityManager->getDefinition($entity_type_id);
|
||||
$langcode_key = $definition->getKey('langcode');
|
||||
$this->assertEqual($entity->{$langcode_key}->value, 'en', SafeMarkup::format('%entity_type: Default language', ['%entity_type' => $entity_type_id]));
|
||||
$this->assertTrue(Uuid::isValid($entity->uuid->value), SafeMarkup::format('%entity_type: Default UUID', ['%entity_type' => $entity_type_id]));
|
||||
$this->assertEqual($entity->{$langcode_key}->value, 'en', new FormattableMarkup('%entity_type: Default language', ['%entity_type' => $entity_type_id]));
|
||||
$this->assertTrue(Uuid::isValid($entity->uuid->value), new FormattableMarkup('%entity_type: Default UUID', ['%entity_type' => $entity_type_id]));
|
||||
$this->assertEqual($entity->name->getValue(), [], 'Field has one empty value by default.');
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ use Drupal\Core\TypedData\DataDefinitionInterface;
|
|||
use Drupal\Core\TypedData\ListInterface;
|
||||
use Drupal\Core\TypedData\Type\StringInterface;
|
||||
use Drupal\Core\TypedData\TypedDataInterface;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\entity_test\Entity\EntityTestComputedField;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
|
||||
|
@ -471,30 +473,30 @@ class EntityFieldTest extends EntityKernelTestBase {
|
|||
|
||||
// Make sure provided contextual information is right.
|
||||
$entity_adapter = $entity->getTypedData();
|
||||
$this->assertIdentical($entity_adapter->getRoot(), $entity_adapter, 'Entity is root object.');
|
||||
$this->assertSame($entity_adapter->getRoot(), $entity_adapter, 'Entity is root object.');
|
||||
$this->assertEqual($entity_adapter->getPropertyPath(), '');
|
||||
$this->assertEqual($entity_adapter->getName(), '');
|
||||
$this->assertEqual($entity_adapter->getParent(), NULL);
|
||||
|
||||
$field = $entity->user_id;
|
||||
$this->assertIdentical($field->getRoot()->getValue(), $entity, 'Entity is root object.');
|
||||
$this->assertIdentical($field->getEntity(), $entity, 'getEntity() returns the entity.');
|
||||
$this->assertSame($field->getRoot()->getValue(), $entity, 'Entity is root object.');
|
||||
$this->assertSame($field->getEntity(), $entity, 'getEntity() returns the entity.');
|
||||
$this->assertEqual($field->getPropertyPath(), 'user_id');
|
||||
$this->assertEqual($field->getName(), 'user_id');
|
||||
$this->assertIdentical($field->getParent()->getValue(), $entity, 'Parent object matches.');
|
||||
$this->assertSame($field->getParent()->getValue(), $entity, 'Parent object matches.');
|
||||
|
||||
$field_item = $field[0];
|
||||
$this->assertIdentical($field_item->getRoot()->getValue(), $entity, 'Entity is root object.');
|
||||
$this->assertIdentical($field_item->getEntity(), $entity, 'getEntity() returns the entity.');
|
||||
$this->assertSame($field_item->getRoot()->getValue(), $entity, 'Entity is root object.');
|
||||
$this->assertSame($field_item->getEntity(), $entity, 'getEntity() returns the entity.');
|
||||
$this->assertEqual($field_item->getPropertyPath(), 'user_id.0');
|
||||
$this->assertEqual($field_item->getName(), '0');
|
||||
$this->assertIdentical($field_item->getParent(), $field, 'Parent object matches.');
|
||||
$this->assertSame($field_item->getParent(), $field, 'Parent object matches.');
|
||||
|
||||
$item_value = $field_item->get('entity');
|
||||
$this->assertIdentical($item_value->getRoot()->getValue(), $entity, 'Entity is root object.');
|
||||
$this->assertSame($item_value->getRoot()->getValue(), $entity, 'Entity is root object.');
|
||||
$this->assertEqual($item_value->getPropertyPath(), 'user_id.0.entity');
|
||||
$this->assertEqual($item_value->getName(), 'entity');
|
||||
$this->assertIdentical($item_value->getParent(), $field_item, 'Parent object matches.');
|
||||
$this->assertSame($item_value->getParent(), $field_item, 'Parent object matches.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -737,6 +739,164 @@ class EntityFieldTest extends EntityKernelTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests all the interaction points of a computed field.
|
||||
*/
|
||||
public function testComputedFields() {
|
||||
$this->installEntitySchema('entity_test_computed_field');
|
||||
|
||||
\Drupal::state()->set('entity_test_computed_field_item_list_value', ['foo computed']);
|
||||
|
||||
// Check that the values are not computed unnecessarily during the lifecycle
|
||||
// of an entity when the field is not interacted with directly.
|
||||
\Drupal::state()->set('computed_test_field_execution', 0);
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$this->assertSame(0, \Drupal::state()->get('computed_test_field_execution', 0));
|
||||
|
||||
$entity->name->value = $this->randomString();
|
||||
$this->assertSame(0, \Drupal::state()->get('computed_test_field_execution', 0));
|
||||
|
||||
$entity->save();
|
||||
$this->assertSame(0, \Drupal::state()->get('computed_test_field_execution', 0));
|
||||
|
||||
// Test \Drupal\Core\TypedData\ComputedItemListTrait::getValue().
|
||||
\Drupal::state()->set('computed_test_field_execution', 0);
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$this->assertSame([['value' => 'foo computed']], $entity->computed_string_field->getValue());
|
||||
|
||||
// Check that the values are only computed once.
|
||||
$this->assertSame(1, \Drupal::state()->get('computed_test_field_execution', 0));
|
||||
|
||||
// Test \Drupal\Core\TypedData\ComputedItemListTrait::setValue(). This also
|
||||
// checks that a subsequent getter does not try to re-compute the value.
|
||||
\Drupal::state()->set('computed_test_field_execution', 0);
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$entity->computed_string_field->setValue([
|
||||
['value' => 'foo computed 1'],
|
||||
['value' => 'foo computed 2'],
|
||||
]);
|
||||
$this->assertSame([['value' => 'foo computed 1'], ['value' => 'foo computed 2']], $entity->computed_string_field->getValue());
|
||||
|
||||
// Check that the values have not been computed when they were explicitly
|
||||
// set.
|
||||
$this->assertSame(0, \Drupal::state()->get('computed_test_field_execution', 0));
|
||||
|
||||
// Test \Drupal\Core\TypedData\ComputedItemListTrait::getString().
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$this->assertSame('foo computed', $entity->computed_string_field->getString());
|
||||
|
||||
// Test \Drupal\Core\TypedData\ComputedItemListTrait::get().
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$this->assertSame('foo computed', $entity->computed_string_field->get(0)->value);
|
||||
$this->assertEmpty($entity->computed_string_field->get(1));
|
||||
|
||||
// Test \Drupal\Core\TypedData\ComputedItemListTrait::set().
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$entity->computed_string_field->set(1, 'foo computed 1');
|
||||
$this->assertSame('foo computed', $entity->computed_string_field[0]->value);
|
||||
$this->assertSame('foo computed 1', $entity->computed_string_field[1]->value);
|
||||
$entity->computed_string_field->set(0, 'foo computed 0');
|
||||
$this->assertSame('foo computed 0', $entity->computed_string_field[0]->value);
|
||||
$this->assertSame('foo computed 1', $entity->computed_string_field[1]->value);
|
||||
|
||||
// Test \Drupal\Core\TypedData\ComputedItemListTrait::appendItem().
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$entity->computed_string_field->appendItem('foo computed 1');
|
||||
$this->assertSame('foo computed', $entity->computed_string_field[0]->value);
|
||||
$this->assertSame('foo computed 1', $entity->computed_string_field[1]->value);
|
||||
|
||||
// Test \Drupal\Core\TypedData\ComputedItemListTrait::removeItem().
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$entity->computed_string_field->removeItem(0);
|
||||
$this->assertTrue($entity->computed_string_field->isEmpty());
|
||||
|
||||
// Test \Drupal\Core\TypedData\ComputedItemListTrait::isEmpty().
|
||||
\Drupal::state()->set('entity_test_computed_field_item_list_value', []);
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$this->assertTrue($entity->computed_string_field->isEmpty());
|
||||
|
||||
\Drupal::state()->set('entity_test_computed_field_item_list_value', ['foo computed']);
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$this->assertFalse($entity->computed_string_field->isEmpty());
|
||||
|
||||
// Test \Drupal\Core\TypedData\ComputedItemListTrait::filter().
|
||||
$filter_callback = function ($item) {
|
||||
return !$item->isEmpty();
|
||||
};
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$entity->computed_string_field->filter($filter_callback);
|
||||
$this->assertCount(1, $entity->computed_string_field);
|
||||
|
||||
// Add an empty item to the list and check that it is filtered out.
|
||||
$entity->computed_string_field->appendItem();
|
||||
$entity->computed_string_field->filter($filter_callback);
|
||||
$this->assertCount(1, $entity->computed_string_field);
|
||||
|
||||
// Add a non-empty item to the list and check that it is not filtered out.
|
||||
$entity->computed_string_field->appendItem('foo computed 1');
|
||||
$entity->computed_string_field->filter($filter_callback);
|
||||
$this->assertCount(2, $entity->computed_string_field);
|
||||
|
||||
// Test \Drupal\Core\TypedData\ComputedItemListTrait::offsetExists().
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$this->assertTrue($entity->computed_string_field->offsetExists(0));
|
||||
$this->assertFalse($entity->computed_string_field->offsetExists(1));
|
||||
|
||||
// Test \Drupal\Core\TypedData\ComputedItemListTrait::getIterator().
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
foreach ($entity->computed_string_field as $delta => $item) {
|
||||
$this->assertSame('foo computed', $item->value);
|
||||
}
|
||||
|
||||
// Test \Drupal\Core\TypedData\ComputedItemListTrait::count().
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$this->assertCount(1, $entity->computed_string_field);
|
||||
|
||||
// Check that computed items are not auto-created when they have no values.
|
||||
\Drupal::state()->set('entity_test_computed_field_item_list_value', []);
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$this->assertCount(0, $entity->computed_string_field);
|
||||
|
||||
// Test \Drupal\Core\Field\FieldItemList::equals() for a computed field.
|
||||
\Drupal::state()->set('entity_test_computed_field_item_list_value', ['foo computed']);
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$computed_item_list1 = $entity->computed_string_field;
|
||||
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$computed_item_list2 = $entity->computed_string_field;
|
||||
|
||||
$this->assertTrue($computed_item_list1->equals($computed_item_list2));
|
||||
|
||||
$computed_item_list2->value = 'foo computed 2';
|
||||
$this->assertFalse($computed_item_list1->equals($computed_item_list2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests an entity reference computed field.
|
||||
*/
|
||||
public function testEntityReferenceComputedField() {
|
||||
$this->installEntitySchema('entity_test_computed_field');
|
||||
|
||||
// Create 2 entities to be referenced.
|
||||
$ref1 = EntityTest::create(['name' => 'foo', 'type' => 'bar']);
|
||||
$ref1->save();
|
||||
$ref2 = EntityTest::create(['name' => 'baz', 'type' => 'bar']);
|
||||
$ref2->save();
|
||||
\Drupal::state()->set('entity_test_reference_computed_target_ids', [$ref1->id(), $ref2->id()]);
|
||||
|
||||
$entity = EntityTestComputedField::create([]);
|
||||
$entity->save();
|
||||
|
||||
/** @var \Drupal\entity_test\Plugin\Field\ComputedReferenceTestFieldItemList $field */
|
||||
$field = $entity->get('computed_reference_field');
|
||||
/** @var \Drupal\Core\Entity\EntityInterface[] $referenced_entities */
|
||||
$referenced_entities = $field->referencedEntities();
|
||||
|
||||
// Check that ::referencedEntities() is working with computed fields.
|
||||
$this->assertEquals($ref1->id(), $referenced_entities[0]->id());
|
||||
$this->assertEquals($ref2->id(), $referenced_entities[1]->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the computed properties tests for the given entity type.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Entity\Plugin\Validation\Constraint\EntityHasFieldConstraintValidator
|
||||
*
|
||||
* @group Entity
|
||||
*/
|
||||
class EntityHasFieldConstraintValidatorTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['entity_test_constraints'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('entity_test_constraints');
|
||||
$this->createUser();
|
||||
}
|
||||
|
||||
public function testValidation() {
|
||||
$this->state->set('entity_test_constraints.build', [
|
||||
'EntityHasField' => 'body',
|
||||
]);
|
||||
|
||||
/** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */
|
||||
$entity_type_manager = $this->container->get('entity_type.manager');
|
||||
$entity_type_manager->clearCachedDefinitions();
|
||||
|
||||
// Clear the typed data cache so that the entity has the correct constraints
|
||||
// during validation.
|
||||
$this->container->get('typed_data_manager')->clearCachedDefinitions();
|
||||
|
||||
$storage = $entity_type_manager->getStorage('entity_test_constraints');
|
||||
|
||||
/** @var \Drupal\entity_test\Entity\EntityTestConstraints $entity */
|
||||
$entity = $storage->create();
|
||||
// We should get a violation if we try to validate the entity before the
|
||||
// field has been created.
|
||||
$violations = $entity->validate();
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertEquals($violations[0]->getMessage(), 'The entity must have the <em class="placeholder">body</em> field.');
|
||||
$storage->save($entity);
|
||||
|
||||
// Create the field.
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'type' => 'string',
|
||||
'entity_type' => $entity->getEntityTypeId(),
|
||||
'field_name' => 'body',
|
||||
]);
|
||||
$field_storage->save();
|
||||
|
||||
FieldConfig::create([
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => $entity->bundle(),
|
||||
])->save();
|
||||
|
||||
// Now that the field has been created, there should be no violations.
|
||||
$this->assertCount(0, $storage->loadUnchanged(1)->validate());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
|
||||
/**
|
||||
* Test the behavior of entity keys.
|
||||
*
|
||||
* @group entity
|
||||
*/
|
||||
class EntityKeysTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* Test the cache when multiple keys reference a single field.
|
||||
*
|
||||
* @dataProvider multipleKeysCacheTestCases
|
||||
*/
|
||||
public function testMultipleKeysCache($translatable) {
|
||||
$this->state->set('entity_test.additional_base_field_definitions', [
|
||||
'test_field' => BaseFieldDefinition::create('string')->setTranslatable($translatable),
|
||||
]);
|
||||
$this->state->set('entity_test.entity_keys', [
|
||||
'key_1' => 'test_field',
|
||||
'key_2' => 'test_field',
|
||||
]);
|
||||
drupal_flush_all_caches();
|
||||
$this->installEntitySchema('entity_test');
|
||||
|
||||
$entity = EntityTest::create([]);
|
||||
|
||||
$entity->set('test_field', 'foo');
|
||||
$this->assertEquals('foo', $entity->getEntityKey('key_1'));
|
||||
$this->assertEquals('foo', $entity->getEntityKey('key_2'));
|
||||
|
||||
$entity->set('test_field', 'bar');
|
||||
$this->assertEquals('bar', $entity->getEntityKey('key_1'));
|
||||
$this->assertEquals('bar', $entity->getEntityKey('key_2'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for ::testMultipleKeysCache.
|
||||
*/
|
||||
public function multipleKeysCacheTestCases() {
|
||||
return [
|
||||
'translatable Entity Key' => [
|
||||
TRUE,
|
||||
],
|
||||
'Non-translatable entity key' => [
|
||||
FALSE,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
|
@ -64,10 +63,10 @@ abstract class EntityLanguageTestBase extends EntityKernelTestBase {
|
|||
$this->state->set('entity_test.translation', TRUE);
|
||||
|
||||
// Create a translatable test field.
|
||||
$this->fieldName = Unicode::strtolower($this->randomMachineName() . '_field_name');
|
||||
$this->fieldName = mb_strtolower($this->randomMachineName() . '_field_name');
|
||||
|
||||
// Create an untranslatable test field.
|
||||
$this->untranslatableFieldName = Unicode::strtolower($this->randomMachineName() . '_field_name');
|
||||
$this->untranslatableFieldName = mb_strtolower($this->randomMachineName() . '_field_name');
|
||||
|
||||
// Create field fields in all entity variations.
|
||||
foreach (entity_test_entity_types() as $entity_type) {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests loading entities by UUID.
|
||||
*
|
||||
* @group entity
|
||||
*/
|
||||
class EntityLoadByUuidTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['entity_test', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('entity_test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that ::loadEntityByUuid() doesn't apply access checking.
|
||||
*/
|
||||
public function testLoadEntityByUuidAccessChecking() {
|
||||
\Drupal::state()->set('entity_test_query_access', TRUE);
|
||||
// Create two test entities.
|
||||
$entity_0 = EntityTest::create([
|
||||
'type' => 'entity_test',
|
||||
'name' => 'published entity',
|
||||
]);
|
||||
$entity_0->save();
|
||||
$entity_1 = EntityTest::create([
|
||||
'type' => 'entity_test',
|
||||
'name' => 'unpublished entity',
|
||||
]);
|
||||
$entity_1->save();
|
||||
|
||||
/** @var \Drupal\Core\Entity\EntityRepositoryInterface $repository */
|
||||
$repository = \Drupal::service('entity.repository');
|
||||
$this->assertEquals($entity_0->id(), $repository->loadEntityByUuid('entity_test', $entity_0->uuid())->id());
|
||||
$this->assertEquals($entity_1->id(), $repository->loadEntityByUuid('entity_test', $entity_1->uuid())->id());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTestMulRev;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
/**
|
||||
* The entity_test storage to create the test entities.
|
||||
*
|
||||
* @var \Drupal\entity_test\EntityTestStorage
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $entityStorage;
|
||||
|
||||
|
@ -34,18 +34,10 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
*/
|
||||
protected $queryResult;
|
||||
|
||||
/**
|
||||
* The query factory to create entity queries.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\Query\QueryFactory
|
||||
*/
|
||||
public $factory;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->entityStorage = $this->entityManager->getStorage('entity_test');
|
||||
$this->factory = $this->container->get('entity.query');
|
||||
|
||||
// Add some fieldapi fields to be used in the test.
|
||||
for ($i = 1; $i <= 2; $i++) {
|
||||
|
@ -120,7 +112,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
*/
|
||||
public function testAggregation() {
|
||||
// Apply a simple groupby.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->groupBy('user_id')
|
||||
->execute();
|
||||
|
||||
|
@ -139,14 +131,14 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Apply a simple aggregation for different aggregation functions.
|
||||
foreach ($function_expected as $aggregation_function => $expected) {
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('id', $aggregation_function)
|
||||
->execute();
|
||||
$this->assertEqual($this->queryResult, $expected);
|
||||
}
|
||||
|
||||
// Apply aggregation and groupby on the same query.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('id', 'COUNT')
|
||||
->groupBy('user_id')
|
||||
->execute();
|
||||
|
@ -157,7 +149,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
]);
|
||||
|
||||
// Apply aggregation and a condition which matches.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('id', 'COUNT')
|
||||
->groupBy('id')
|
||||
->conditionAggregate('id', 'COUNT', 8)
|
||||
|
@ -165,14 +157,14 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
$this->assertResults([]);
|
||||
|
||||
// Don't call aggregate to test the implicit aggregate call.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->groupBy('id')
|
||||
->conditionAggregate('id', 'COUNT', 8)
|
||||
->execute();
|
||||
$this->assertResults([]);
|
||||
|
||||
// Apply aggregation and a condition which matches.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('id', 'count')
|
||||
->groupBy('id')
|
||||
->conditionAggregate('id', 'COUNT', 6)
|
||||
|
@ -181,7 +173,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Apply aggregation, a groupby and a condition which matches partially via
|
||||
// the operator '='.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('id', 'count')
|
||||
->conditionAggregate('id', 'count', 2)
|
||||
->groupBy('user_id')
|
||||
|
@ -190,7 +182,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Apply aggregation, a groupby and a condition which matches partially via
|
||||
// the operator '>'.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('id', 'count')
|
||||
->conditionAggregate('id', 'COUNT', 1, '>')
|
||||
->groupBy('user_id')
|
||||
|
@ -202,20 +194,20 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Apply aggregation and a sort. This might not be useful, but have a proper
|
||||
// test coverage.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('id', 'COUNT')
|
||||
->sortAggregate('id', 'COUNT')
|
||||
->execute();
|
||||
$this->assertSortedResults([['id_count' => 6]]);
|
||||
|
||||
// Don't call aggregate to test the implicit aggregate call.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->sortAggregate('id', 'COUNT')
|
||||
->execute();
|
||||
$this->assertSortedResults([['id_count' => 6]]);
|
||||
|
||||
// Apply aggregation, groupby and a sort descending.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('id', 'COUNT')
|
||||
->groupBy('user_id')
|
||||
->sortAggregate('id', 'COUNT', 'DESC')
|
||||
|
@ -227,7 +219,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
]);
|
||||
|
||||
// Apply aggregation, groupby and a sort ascending.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('id', 'COUNT')
|
||||
->groupBy('user_id')
|
||||
->sortAggregate('id', 'COUNT', 'ASC')
|
||||
|
@ -240,7 +232,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Apply aggregation, groupby, an aggregation condition and a sort with the
|
||||
// operator '='.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('id', 'COUNT')
|
||||
->groupBy('user_id')
|
||||
->sortAggregate('id', 'COUNT')
|
||||
|
@ -250,7 +242,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Apply aggregation, groupby, an aggregation condition and a sort with the
|
||||
// operator '<' and order ASC.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('id', 'COUNT')
|
||||
->groupBy('user_id')
|
||||
->sortAggregate('id', 'COUNT', 'ASC')
|
||||
|
@ -263,7 +255,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Apply aggregation, groupby, an aggregation condition and a sort with the
|
||||
// operator '<' and order DESC.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('id', 'COUNT')
|
||||
->groupBy('user_id')
|
||||
->sortAggregate('id', 'COUNT', 'DESC')
|
||||
|
@ -277,7 +269,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
// Test aggregation/groupby support for fieldapi fields.
|
||||
|
||||
// Just group by a fieldapi field.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->groupBy('field_test_1')
|
||||
->execute();
|
||||
$this->assertResults([
|
||||
|
@ -287,7 +279,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
]);
|
||||
|
||||
// Group by a fieldapi field and aggregate a normal property.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('user_id', 'COUNT')
|
||||
->groupBy('field_test_1')
|
||||
->execute();
|
||||
|
@ -299,7 +291,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
]);
|
||||
|
||||
// Group by a normal property and aggregate a fieldapi field.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('field_test_1', 'COUNT')
|
||||
->groupBy('user_id')
|
||||
->execute();
|
||||
|
@ -310,7 +302,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
['user_id' => 3, 'field_test_1_count' => 2],
|
||||
]);
|
||||
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('field_test_1', 'SUM')
|
||||
->groupBy('user_id')
|
||||
->execute();
|
||||
|
@ -321,7 +313,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
]);
|
||||
|
||||
// Aggregate by two different fieldapi fields.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('field_test_1', 'SUM')
|
||||
->aggregate('field_test_2', 'SUM')
|
||||
->groupBy('user_id')
|
||||
|
@ -333,7 +325,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
]);
|
||||
|
||||
// This time aggregate the same field twice.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('field_test_1', 'SUM')
|
||||
->aggregate('field_test_1', 'COUNT')
|
||||
->groupBy('user_id')
|
||||
|
@ -345,7 +337,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
]);
|
||||
|
||||
// Group by and aggregate by a fieldapi field.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->groupBy('field_test_1')
|
||||
->aggregate('field_test_2', 'COUNT')
|
||||
->execute();
|
||||
|
@ -357,7 +349,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Group by and aggregate by a fieldapi field and use multiple aggregate
|
||||
// functions.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->groupBy('field_test_1')
|
||||
->aggregate('field_test_2', 'COUNT')
|
||||
->aggregate('field_test_2', 'SUM')
|
||||
|
@ -370,7 +362,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Apply an aggregate condition for a fieldapi field and group by a simple
|
||||
// property.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->conditionAggregate('field_test_1', 'COUNT', 3)
|
||||
->groupBy('user_id')
|
||||
->execute();
|
||||
|
@ -379,7 +371,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
['user_id' => 3, 'field_test_1_count' => 2],
|
||||
]);
|
||||
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('field_test_1', 'SUM')
|
||||
->conditionAggregate('field_test_1', 'COUNT', 2, '>')
|
||||
->groupBy('user_id')
|
||||
|
@ -391,7 +383,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Apply an aggregate condition for a simple property and a group by a
|
||||
// fieldapi field.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->conditionAggregate('user_id', 'COUNT', 2)
|
||||
->groupBy('field_test_1')
|
||||
->execute();
|
||||
|
@ -399,7 +391,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
['field_test_1' => 1, 'user_id_count' => 2],
|
||||
]);
|
||||
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->conditionAggregate('user_id', 'COUNT', 2, '>')
|
||||
->groupBy('field_test_1')
|
||||
->execute();
|
||||
|
@ -409,14 +401,14 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
]);
|
||||
|
||||
// Apply an aggregate condition and a group by fieldapi fields.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->groupBy('field_test_1')
|
||||
->conditionAggregate('field_test_2', 'COUNT', 2)
|
||||
->execute();
|
||||
$this->assertResults([
|
||||
['field_test_1' => 1, 'field_test_2_count' => 2],
|
||||
]);
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->groupBy('field_test_1')
|
||||
->conditionAggregate('field_test_2', 'COUNT', 2, '>')
|
||||
->execute();
|
||||
|
@ -427,7 +419,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Apply an aggregate condition and a group by fieldapi fields with multiple
|
||||
// conditions via AND.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->groupBy('field_test_1')
|
||||
->conditionAggregate('field_test_2', 'COUNT', 2)
|
||||
->conditionAggregate('field_test_2', 'SUM', 8)
|
||||
|
@ -436,7 +428,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Apply an aggregate condition and a group by fieldapi fields with multiple
|
||||
// conditions via OR.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test', 'OR')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery('OR')
|
||||
->groupBy('field_test_1')
|
||||
->conditionAggregate('field_test_2', 'COUNT', 2)
|
||||
->conditionAggregate('field_test_2', 'SUM', 8)
|
||||
|
@ -448,7 +440,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Group by a normal property and aggregate a fieldapi field and sort by the
|
||||
// groupby field.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('field_test_1', 'COUNT')
|
||||
->groupBy('user_id')
|
||||
->sort('user_id', 'DESC')
|
||||
|
@ -459,7 +451,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
['user_id' => 1, 'field_test_1_count' => 1],
|
||||
]);
|
||||
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->aggregate('field_test_1', 'COUNT')
|
||||
->groupBy('user_id')
|
||||
->sort('user_id', 'ASC')
|
||||
|
@ -470,7 +462,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
['user_id' => 3, 'field_test_1_count' => 2],
|
||||
]);
|
||||
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->conditionAggregate('field_test_1', 'COUNT', 2, '>')
|
||||
->groupBy('user_id')
|
||||
->sort('user_id', 'ASC')
|
||||
|
@ -482,7 +474,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Group by a normal property, aggregate a fieldapi field, and sort by the
|
||||
// aggregated field.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->sortAggregate('field_test_1', 'COUNT', 'DESC')
|
||||
->groupBy('user_id')
|
||||
->execute();
|
||||
|
@ -492,7 +484,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
['user_id' => 1, 'field_test_1_count' => 1],
|
||||
]);
|
||||
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->sortAggregate('field_test_1', 'COUNT', 'ASC')
|
||||
->groupBy('user_id')
|
||||
->execute();
|
||||
|
@ -503,7 +495,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
]);
|
||||
|
||||
// Group by and aggregate by fieldapi field, and sort by the groupby field.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->groupBy('field_test_1')
|
||||
->aggregate('field_test_2', 'COUNT')
|
||||
->sort('field_test_1', 'ASC')
|
||||
|
@ -514,7 +506,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
['field_test_1' => 3, 'field_test_2_count' => 1],
|
||||
]);
|
||||
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->groupBy('field_test_1')
|
||||
->aggregate('field_test_2', 'COUNT')
|
||||
->sort('field_test_1', 'DESC')
|
||||
|
@ -527,7 +519,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
|
||||
// Groupby and aggregate by fieldapi field, and sort by the aggregated
|
||||
// field.
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->groupBy('field_test_1')
|
||||
->sortAggregate('field_test_2', 'COUNT', 'DESC')
|
||||
->execute();
|
||||
|
@ -537,7 +529,7 @@ class EntityQueryAggregateTest extends EntityKernelTestBase {
|
|||
['field_test_1' => 3, 'field_test_2_count' => 1],
|
||||
]);
|
||||
|
||||
$this->queryResult = $this->factory->getAggregate('entity_test')
|
||||
$this->queryResult = $this->entityStorage->getAggregateQuery()
|
||||
->groupBy('field_test_1')
|
||||
->sortAggregate('field_test_2', 'COUNT', 'ASC')
|
||||
->execute();
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
use Drupal\taxonomy\Entity\Term;
|
||||
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
|
||||
|
||||
/**
|
||||
* Tests the Entity Query relationship API.
|
||||
|
@ -25,11 +24,6 @@ class EntityQueryRelationshipTest extends EntityKernelTestBase {
|
|||
*/
|
||||
public static $modules = ['taxonomy'];
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Entity\Query\QueryFactory
|
||||
*/
|
||||
protected $factory;
|
||||
|
||||
/**
|
||||
* Term entities.
|
||||
*
|
||||
|
@ -73,7 +67,7 @@ class EntityQueryRelationshipTest extends EntityKernelTestBase {
|
|||
// We want an entity reference field. It needs a vocabulary, terms, a field
|
||||
// storage and a field. First, create the vocabulary.
|
||||
$vocabulary = Vocabulary::create([
|
||||
'vid' => Unicode::strtolower($this->randomMachineName()),
|
||||
'vid' => mb_strtolower($this->randomMachineName()),
|
||||
]);
|
||||
$vocabulary->save();
|
||||
|
||||
|
@ -110,88 +104,88 @@ class EntityQueryRelationshipTest extends EntityKernelTestBase {
|
|||
$entity->save();
|
||||
$this->entities[] = $entity;
|
||||
}
|
||||
$this->factory = \Drupal::service('entity.query');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests querying.
|
||||
*/
|
||||
public function testQuery() {
|
||||
$storage = $this->container->get('entity_type.manager')->getStorage('entity_test');
|
||||
// This returns the 0th entity as that's the only one pointing to the 0th
|
||||
// account.
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->condition("user_id.entity.name", $this->accounts[0]->getUsername())
|
||||
->execute();
|
||||
$this->assertResults([0]);
|
||||
// This returns the 1st and 2nd entity as those point to the 1st account.
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->condition("user_id.entity.name", $this->accounts[0]->getUsername(), '<>')
|
||||
->execute();
|
||||
$this->assertResults([1, 2]);
|
||||
// This returns all three entities because all of them point to an
|
||||
// account.
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->exists("user_id.entity.name")
|
||||
->execute();
|
||||
$this->assertResults([0, 1, 2]);
|
||||
// This returns no entities because all of them point to an account.
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->notExists("user_id.entity.name")
|
||||
->execute();
|
||||
$this->assertEqual(count($this->queryResults), 0);
|
||||
// This returns the 0th entity as that's only one pointing to the 0th
|
||||
// term (test without specifying the field column).
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->condition("$this->fieldName.entity.name", $this->terms[0]->name->value)
|
||||
->execute();
|
||||
$this->assertResults([0]);
|
||||
// This returns the 0th entity as that's only one pointing to the 0th
|
||||
// term (test with specifying the column name).
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->condition("$this->fieldName.target_id.entity.name", $this->terms[0]->name->value)
|
||||
->execute();
|
||||
$this->assertResults([0]);
|
||||
// This returns the 1st and 2nd entity as those point to the 1st term.
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->condition("$this->fieldName.entity.name", $this->terms[0]->name->value, '<>')
|
||||
->execute();
|
||||
$this->assertResults([1, 2]);
|
||||
// This returns the 0th entity as that's only one pointing to the 0th
|
||||
// account.
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->condition("user_id.entity:user.name", $this->accounts[0]->getUsername())
|
||||
->execute();
|
||||
$this->assertResults([0]);
|
||||
// This returns the 1st and 2nd entity as those point to the 1st account.
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->condition("user_id.entity:user.name", $this->accounts[0]->getUsername(), '<>')
|
||||
->execute();
|
||||
$this->assertResults([1, 2]);
|
||||
// This returns all three entities because all of them point to an
|
||||
// account.
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->exists("user_id.entity:user.name")
|
||||
->execute();
|
||||
$this->assertResults([0, 1, 2]);
|
||||
// This returns no entities because all of them point to an account.
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->notExists("user_id.entity:user.name")
|
||||
->execute();
|
||||
$this->assertEqual(count($this->queryResults), 0);
|
||||
// This returns the 0th entity as that's only one pointing to the 0th
|
||||
// term (test without specifying the field column).
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->condition("$this->fieldName.entity:taxonomy_term.name", $this->terms[0]->name->value)
|
||||
->execute();
|
||||
$this->assertResults([0]);
|
||||
// This returns the 0th entity as that's only one pointing to the 0th
|
||||
// term (test with specifying the column name).
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->condition("$this->fieldName.target_id.entity:taxonomy_term.name", $this->terms[0]->name->value)
|
||||
->execute();
|
||||
$this->assertResults([0]);
|
||||
// This returns the 1st and 2nd entity as those point to the 1st term.
|
||||
$this->queryResults = $this->factory->get('entity_test')
|
||||
$this->queryResults = $storage->getQuery()
|
||||
->condition("$this->fieldName.entity:taxonomy_term.name", $this->terms[0]->name->value, '<>')
|
||||
->execute();
|
||||
$this->assertResults([1, 2]);
|
||||
|
@ -202,8 +196,10 @@ class EntityQueryRelationshipTest extends EntityKernelTestBase {
|
|||
*/
|
||||
public function testInvalidSpecifier() {
|
||||
$this->setExpectedException(PluginNotFoundException::class);
|
||||
$this->factory
|
||||
->get('taxonomy_term')
|
||||
$this->container
|
||||
->get('entity_type.manager')
|
||||
->getStorage('taxonomy_term')
|
||||
->getQuery()
|
||||
->condition('langcode.language.foo', 'bar')
|
||||
->execute();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
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;
|
||||
|
@ -10,6 +9,7 @@ use Drupal\field\Entity\FieldStorageConfig;
|
|||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\taxonomy\Entity\Term;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
|
@ -19,6 +19,8 @@ use Symfony\Component\HttpFoundation\Request;
|
|||
*/
|
||||
class EntityQueryTest extends EntityKernelTestBase {
|
||||
|
||||
use EntityReferenceTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
|
@ -31,11 +33,6 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
*/
|
||||
protected $queryResults;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Entity\Query\QueryFactory
|
||||
*/
|
||||
protected $factory;
|
||||
|
||||
/**
|
||||
* A list of bundle machine names created for this test.
|
||||
*
|
||||
|
@ -57,6 +54,13 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
*/
|
||||
public $figures;
|
||||
|
||||
/**
|
||||
* The entity_test_mulrev entity storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
|
@ -64,8 +68,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
|
||||
$this->installConfig(['language']);
|
||||
|
||||
$figures = Unicode::strtolower($this->randomMachineName());
|
||||
$greetings = Unicode::strtolower($this->randomMachineName());
|
||||
$figures = mb_strtolower($this->randomMachineName());
|
||||
$greetings = mb_strtolower($this->randomMachineName());
|
||||
foreach ([$figures => 'shape', $greetings => 'text'] as $field_name => $field_type) {
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
|
@ -94,23 +98,27 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
}
|
||||
// Each unit is a list of field name, langcode and a column-value array.
|
||||
$units[] = [$figures, 'en', [
|
||||
'color' => 'red',
|
||||
'shape' => 'triangle',
|
||||
]];
|
||||
'color' => 'red',
|
||||
'shape' => 'triangle',
|
||||
],
|
||||
];
|
||||
$units[] = [$figures, 'en', [
|
||||
'color' => 'blue',
|
||||
'shape' => 'circle',
|
||||
]];
|
||||
'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'
|
||||
]];
|
||||
'value' => 'merhaba',
|
||||
'format' => 'format-tr',
|
||||
],
|
||||
];
|
||||
$units[] = [$greetings, 'pl', [
|
||||
'value' => 'siema',
|
||||
'format' => 'format-pl'
|
||||
]];
|
||||
'value' => 'siema',
|
||||
'format' => 'format-pl',
|
||||
],
|
||||
];
|
||||
// Make these languages available to the greetings field.
|
||||
ConfigurableLanguage::createFromLangcode('tr')->save();
|
||||
ConfigurableLanguage::createFromLangcode('pl')->save();
|
||||
|
@ -139,7 +147,7 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$this->bundles = $bundles;
|
||||
$this->figures = $figures;
|
||||
$this->greetings = $greetings;
|
||||
$this->factory = \Drupal::service('entity.query');
|
||||
$this->storage = $this->container->get('entity_type.manager')->getStorage('entity_test_mulrev');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,7 +156,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
public function testEntityQuery() {
|
||||
$greetings = $this->greetings;
|
||||
$figures = $this->figures;
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->exists($greetings, 'tr')
|
||||
->condition("$figures.color", 'red')
|
||||
->sort('id')
|
||||
|
@ -157,7 +166,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
// bit 0 and bit 2 needs to be set.
|
||||
$this->assertResult(5, 7, 13, 15);
|
||||
|
||||
$query = $this->factory->get('entity_test_mulrev', 'OR')
|
||||
$query = $this->storage
|
||||
->getQuery('OR')
|
||||
->exists($greetings, 'tr')
|
||||
->condition("$figures.color", 'red')
|
||||
->sort('id');
|
||||
|
@ -169,7 +179,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$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')
|
||||
$query = $this->storage
|
||||
->getQuery()
|
||||
->condition("$figures.color", 'red')
|
||||
->sort('id');
|
||||
$cloned_query = clone $query;
|
||||
|
@ -182,7 +193,7 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$this->queryResults = $cloned_query->execute();
|
||||
$this->assertResult();
|
||||
|
||||
$query = $this->factory->get('entity_test_mulrev');
|
||||
$query = $this->storage->getQuery();
|
||||
$group = $query->orConditionGroup()
|
||||
->exists($greetings, 'tr')
|
||||
->condition("$figures.color", 'red');
|
||||
|
@ -195,7 +206,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$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')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->condition("$figures.color", 'blue')
|
||||
->condition("$figures.color", 'red')
|
||||
->sort('id')
|
||||
|
@ -203,7 +215,7 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$this->assertResult();
|
||||
|
||||
// But an entity might have a red and a blue figure both.
|
||||
$query = $this->factory->get('entity_test_mulrev');
|
||||
$query = $this->storage->getQuery();
|
||||
$group_blue = $query->andConditionGroup()->condition("$figures.color", 'blue');
|
||||
$group_red = $query->andConditionGroup()->condition("$figures.color", 'red');
|
||||
$this->queryResults = $query
|
||||
|
@ -215,7 +227,7 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$this->assertResult(3, 7, 11, 15);
|
||||
|
||||
// Do the same test but with IN operator.
|
||||
$query = $this->factory->get('entity_test_mulrev');
|
||||
$query = $this->storage->getQuery();
|
||||
$group_blue = $query->andConditionGroup()->condition("$figures.color", ['blue'], 'IN');
|
||||
$group_red = $query->andConditionGroup()->condition("$figures.color", ['red'], 'IN');
|
||||
$this->queryResults = $query
|
||||
|
@ -227,14 +239,16 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$this->assertResult(3, 7, 11, 15);
|
||||
|
||||
// An entity might have either red or blue figure.
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->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')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->exists("$figures.color")
|
||||
->notExists("$greetings.value")
|
||||
->sort('id')
|
||||
|
@ -243,7 +257,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$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')
|
||||
$ids = $this->storage
|
||||
->getQuery()
|
||||
->condition("$greetings.value", 'merhaba')
|
||||
->sort('id')
|
||||
->execute();
|
||||
|
@ -257,30 +272,35 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$entity->save();
|
||||
}
|
||||
// We changed the entity names, so the current revision should not match.
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->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')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->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')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->condition("$greetings.value", 'merhaba')
|
||||
->execute();
|
||||
$this->assertResult();
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->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')
|
||||
$results = $this->storage
|
||||
->getQuery()
|
||||
->condition("$greetings.value", 'siema', 'CONTAINS')
|
||||
->sort('id')
|
||||
->execute();
|
||||
|
@ -288,21 +308,24 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
// 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')
|
||||
$results = $this->storage
|
||||
->getQuery()
|
||||
->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')
|
||||
$results = $this->storage
|
||||
->getQuery()
|
||||
->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')
|
||||
$results = $this->storage
|
||||
->getQuery()
|
||||
->condition("$greetings.value", 'a', 'ENDS_WITH')
|
||||
->allRevisions()
|
||||
->sort('id')
|
||||
|
@ -311,6 +334,17 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
// 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->storage
|
||||
->getQuery()
|
||||
->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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -322,15 +356,18 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$greetings = $this->greetings;
|
||||
$figures = $this->figures;
|
||||
// Order up and down on a number.
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->sort('id')
|
||||
->execute();
|
||||
$this->assertResult(range(1, 15));
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->sort('id', 'DESC')
|
||||
->execute();
|
||||
$this->assertResult(range(15, 1));
|
||||
$query = $this->factory->get('entity_test_mulrev')
|
||||
$query = $this->storage
|
||||
->getQuery()
|
||||
->sort("$figures.color")
|
||||
->sort("$greetings.format")
|
||||
->sort('id');
|
||||
|
@ -380,7 +417,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
'page' => '0,2',
|
||||
]);
|
||||
\Drupal::getContainer()->get('request_stack')->push($request);
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->sort("$figures.color")
|
||||
->sort("$greetings.format")
|
||||
->sort('id')
|
||||
|
@ -389,7 +427,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$this->assertResult(15, 6, 7, 1);
|
||||
|
||||
// Now test the reversed order.
|
||||
$query = $this->factory->get('entity_test_mulrev')
|
||||
$query = $this->storage
|
||||
->getQuery()
|
||||
->sort("$figures.color", 'DESC')
|
||||
->sort("$greetings.format", 'DESC')
|
||||
->sort('id', 'DESC');
|
||||
|
@ -418,7 +457,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
'type' => ['data' => 'Type', 'specifier' => 'type'],
|
||||
];
|
||||
|
||||
$this->queryResults = array_values($this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = array_values($this->storage
|
||||
->getQuery()
|
||||
->tableSort($header)
|
||||
->execute());
|
||||
$this->assertBundleOrder('asc');
|
||||
|
@ -432,7 +472,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
'id' => ['data' => 'Id', 'specifier' => 'id'],
|
||||
'type' => ['data' => 'Type', 'specifier' => 'type'],
|
||||
];
|
||||
$this->queryResults = array_values($this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = array_values($this->storage
|
||||
->getQuery()
|
||||
->tableSort($header)
|
||||
->execute());
|
||||
$this->assertBundleOrder('desc');
|
||||
|
@ -442,7 +483,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
'order' => 'Id',
|
||||
]);
|
||||
\Drupal::getContainer()->get('request_stack')->push($request);
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->tableSort($header)
|
||||
->execute();
|
||||
$this->assertResult(range(15, 1));
|
||||
|
@ -477,7 +519,9 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
|
||||
// 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')
|
||||
$count = $this->container->get('entity_type.manager')
|
||||
->getStorage('entity_test')
|
||||
->getQuery()
|
||||
->exists("$field_name.color")
|
||||
->count()
|
||||
->execute();
|
||||
|
@ -490,7 +534,7 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
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');
|
||||
$query = $this->storage->getQuery();
|
||||
|
||||
$first_and = $query->andConditionGroup()
|
||||
->condition($this->figures . '.color', 'red')
|
||||
|
@ -509,7 +553,32 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
->sort('id')
|
||||
->execute();
|
||||
|
||||
$this->assertResult(6, 14);
|
||||
$this->assertResult(4, 6, 12, 14);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that condition count returns expected number of conditions.
|
||||
*/
|
||||
public function testConditionCount() {
|
||||
// Query for all entities of the first bundle that
|
||||
// have red as a colour AND are triangle shaped.
|
||||
$query = $this->storage->getQuery();
|
||||
|
||||
// Add an AND condition group with 2 conditions in it.
|
||||
$and_condition_group = $query->andConditionGroup()
|
||||
->condition($this->figures . '.color', 'red')
|
||||
->condition($this->figures . '.shape', 'triangle');
|
||||
|
||||
// We added 2 conditions so count should be 2.
|
||||
$this->assertEqual($and_condition_group->count(), 2);
|
||||
|
||||
// Add an OR condition group with 2 conditions in it.
|
||||
$or_condition_group = $query->orConditionGroup()
|
||||
->condition($this->figures . '.color', 'red')
|
||||
->condition($this->figures . '.shape', 'triangle');
|
||||
|
||||
// We added 2 conditions so count should be 2.
|
||||
$this->assertEqual($or_condition_group->count(), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -518,14 +587,16 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
public function testDelta() {
|
||||
$figures = $this->figures;
|
||||
// Test numeric delta value in field condition.
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->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')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->condition("$figures.1.color", 'red')
|
||||
->sort('id')
|
||||
->execute();
|
||||
|
@ -533,7 +604,7 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$this->assertResult();
|
||||
|
||||
// Test on two different deltas.
|
||||
$query = $this->factory->get('entity_test_mulrev');
|
||||
$query = $this->storage->getQuery();
|
||||
$or = $query->andConditionGroup()
|
||||
->condition("$figures.0.color", 'red')
|
||||
->condition("$figures.1.color", 'blue');
|
||||
|
@ -544,7 +615,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$this->assertResult(3, 7, 11, 15);
|
||||
|
||||
// Test the delta range condition.
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->condition("$figures.%delta.color", ['blue', 'red'], 'IN')
|
||||
->condition("$figures.%delta", [0, 1], 'IN')
|
||||
->sort('id')
|
||||
|
@ -553,21 +625,24 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$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')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->condition("$figures.%delta", 1)
|
||||
->sort('id')
|
||||
->execute();
|
||||
// Entity needs to have atleast two figures.
|
||||
// Entity needs to have at least 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')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->condition("id.0.value", [1, 3, 5], 'IN')
|
||||
->sort('id')
|
||||
->execute();
|
||||
$this->assertResult(1, 3, 5);
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->condition("id.1.value", [1, 3, 5], 'IN')
|
||||
->sort('id')
|
||||
->execute();
|
||||
|
@ -575,18 +650,21 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
|
||||
// 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')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->condition("id.%delta.value", [1, 3, 5], 'IN')
|
||||
->sort('id')
|
||||
->execute();
|
||||
$this->assertResult(1, 3, 5);
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->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')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->condition("id.%delta.value", [1, 3, 5], 'IN')
|
||||
->condition("id.%delta", 1, '=')
|
||||
->sort('id')
|
||||
|
@ -643,7 +721,7 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
* The tags and metadata should propagate to the SQL query object.
|
||||
*/
|
||||
public function testMetaData() {
|
||||
$query = \Drupal::entityQuery('entity_test_mulrev');
|
||||
$query = $this->storage->getQuery();
|
||||
$query
|
||||
->addTag('efq_metadata_test')
|
||||
->addMetaData('foo', 'bar')
|
||||
|
@ -667,7 +745,7 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
'translatable' => FALSE,
|
||||
'settings' => [
|
||||
'case_sensitive' => FALSE,
|
||||
]
|
||||
],
|
||||
]);
|
||||
$field_storage->save();
|
||||
|
||||
|
@ -703,8 +781,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$string = $this->randomMachineName(7) . 'a';
|
||||
$fixtures[] = [
|
||||
'original' => $string,
|
||||
'uppercase' => Unicode::strtoupper($string),
|
||||
'lowercase' => Unicode::strtolower($string),
|
||||
'uppercase' => mb_strtoupper($string),
|
||||
'lowercase' => mb_strtolower($string),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -713,140 +791,161 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
'name' => $this->randomMachineName(),
|
||||
'langcode' => 'en',
|
||||
'field_ci' => $fixtures[0]['uppercase'] . $fixtures[1]['lowercase'],
|
||||
'field_cs' => $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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->condition('field_ci', mb_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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->condition('field_ci', mb_strtolower(mb_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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->condition('field_cs', mb_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();
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->condition('field_cs', mb_strtolower(mb_substr($fixtures[0]['uppercase'] . $fixtures[1]['lowercase'], 4, 8)), 'CONTAINS')
|
||||
->execute();
|
||||
$this->assertIdentical(count($result), 0, 'Case sensitive, exact match.');
|
||||
|
||||
}
|
||||
|
@ -866,7 +965,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
'description' => [
|
||||
'value' => $this->randomString(),
|
||||
'format' => 'format1',
|
||||
]]);
|
||||
],
|
||||
]);
|
||||
$term1->save();
|
||||
|
||||
$term2 = Term::create([
|
||||
|
@ -875,10 +975,13 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
'description' => [
|
||||
'value' => $this->randomString(),
|
||||
'format' => 'format2',
|
||||
]]);
|
||||
],
|
||||
]);
|
||||
$term2->save();
|
||||
|
||||
$ids = \Drupal::entityQuery('taxonomy_term')
|
||||
$ids = $this->container->get('entity_type.manager')
|
||||
->getStorage('taxonomy_term')
|
||||
->getQuery()
|
||||
->condition('description.format', 'format1')
|
||||
->execute();
|
||||
|
||||
|
@ -887,11 +990,12 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test forward-revisions.
|
||||
* Test pending revisions.
|
||||
*/
|
||||
public function testForwardRevisions() {
|
||||
public function testPendingRevisions() {
|
||||
// Ensure entity 14 is returned.
|
||||
$result = \Drupal::entityQuery('entity_test_mulrev')
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->condition('id', [14], 'IN')
|
||||
->execute();
|
||||
$this->assertEqual(count($result), 1);
|
||||
|
@ -904,29 +1008,85 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$entity->isDefaultRevision(FALSE);
|
||||
$entity->{$this->figures}->setValue([
|
||||
'color' => 'red',
|
||||
'shape' => 'square'
|
||||
'shape' => 'square',
|
||||
]);
|
||||
$entity->save();
|
||||
|
||||
// Entity query should still return entity 14.
|
||||
$result = \Drupal::entityQuery('entity_test_mulrev')
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->condition('id', [14], 'IN')
|
||||
->execute();
|
||||
$this->assertEqual(count($result), 1);
|
||||
|
||||
// Verify that field conditions on the default and forward revision are
|
||||
// Verify that field conditions on the default and pending revision are
|
||||
// work as expected.
|
||||
$result = \Drupal::entityQuery('entity_test_mulrev')
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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')
|
||||
$result = $this->storage
|
||||
->getQuery()
|
||||
->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->storage
|
||||
->getQuery()
|
||||
->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->storage
|
||||
->getQuery()
|
||||
->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->storage
|
||||
->getQuery()
|
||||
->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->storage
|
||||
->getQuery()
|
||||
->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->storage
|
||||
->getQuery()
|
||||
->condition('id', [14], 'IN')
|
||||
->condition("$this->figures.color", 'red')
|
||||
->latestRevision()
|
||||
->execute();
|
||||
$this->assertSame([17 => '14'], $result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -935,7 +1095,8 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
*/
|
||||
public function testInjectionInCondition() {
|
||||
try {
|
||||
$this->queryResults = $this->factory->get('entity_test_mulrev')
|
||||
$this->queryResults = $this->storage
|
||||
->getQuery()
|
||||
->condition('1 ; -- ', [0, 1], 'IN')
|
||||
->sort('id')
|
||||
->execute();
|
||||
|
@ -946,4 +1107,57 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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');
|
||||
|
||||
$storage = $this->container->get('entity_type.manager')
|
||||
->getStorage('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 = $storage->getQuery()
|
||||
->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 = $storage->getQuery()
|
||||
->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 = $storage->getQuery()
|
||||
->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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ use Drupal\Core\Entity\EntityInterface;
|
|||
use Drupal\Core\Entity\EntityStorageException;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
@ -212,7 +212,7 @@ class EntityReferenceFieldTest extends EntityKernelTestBase {
|
|||
// Create the default target entity.
|
||||
$target_entity = EntityTestStringId::create([
|
||||
'id' => $this->randomString(),
|
||||
'type' => $this->bundle
|
||||
'type' => $this->bundle,
|
||||
]);
|
||||
$target_entity->save();
|
||||
|
||||
|
@ -247,24 +247,24 @@ class EntityReferenceFieldTest extends EntityKernelTestBase {
|
|||
->create(['name' => $this->randomString()]);
|
||||
|
||||
// Test content entity autocreation.
|
||||
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
|
||||
$this->assertUserAutocreate($entity, function (EntityInterface $entity, UserInterface $user) {
|
||||
$entity->set('user_id', $user);
|
||||
});
|
||||
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
|
||||
$this->assertUserAutocreate($entity, function (EntityInterface $entity, UserInterface $user) {
|
||||
$entity->set('user_id', $user, FALSE);
|
||||
});
|
||||
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
|
||||
$this->assertUserAutocreate($entity, function (EntityInterface $entity, UserInterface $user) {
|
||||
$entity->user_id->setValue($user);
|
||||
});
|
||||
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
|
||||
$this->assertUserAutocreate($entity, function (EntityInterface $entity, UserInterface $user) {
|
||||
$entity->user_id[0]->get('entity')->setValue($user);
|
||||
});
|
||||
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
|
||||
$this->assertUserAutocreate($entity, function (EntityInterface $entity, UserInterface $user) {
|
||||
$entity->user_id->setValue(['entity' => $user, 'target_id' => NULL]);
|
||||
});
|
||||
try {
|
||||
$message = 'Setting both the entity and an invalid target_id property fails.';
|
||||
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
|
||||
$this->assertUserAutocreate($entity, function (EntityInterface $entity, UserInterface $user) {
|
||||
$user->save();
|
||||
$entity->user_id->setValue(['entity' => $user, 'target_id' => $this->generateRandomEntityId()]);
|
||||
});
|
||||
|
@ -273,32 +273,32 @@ class EntityReferenceFieldTest extends EntityKernelTestBase {
|
|||
catch (\InvalidArgumentException $e) {
|
||||
$this->pass($message);
|
||||
}
|
||||
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
|
||||
$this->assertUserAutocreate($entity, function (EntityInterface $entity, UserInterface $user) {
|
||||
$entity->user_id = $user;
|
||||
});
|
||||
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
|
||||
$this->assertUserAutocreate($entity, function (EntityInterface $entity, UserInterface $user) {
|
||||
$entity->user_id->entity = $user;
|
||||
});
|
||||
|
||||
// Test config entity autocreation.
|
||||
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
|
||||
$this->assertUserRoleAutocreate($entity, function (EntityInterface $entity, RoleInterface $role) {
|
||||
$entity->set('user_role', $role);
|
||||
});
|
||||
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
|
||||
$this->assertUserRoleAutocreate($entity, function (EntityInterface $entity, RoleInterface $role) {
|
||||
$entity->set('user_role', $role, FALSE);
|
||||
});
|
||||
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
|
||||
$this->assertUserRoleAutocreate($entity, function (EntityInterface $entity, RoleInterface $role) {
|
||||
$entity->user_role->setValue($role);
|
||||
});
|
||||
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
|
||||
$this->assertUserRoleAutocreate($entity, function (EntityInterface $entity, RoleInterface $role) {
|
||||
$entity->user_role[0]->get('entity')->setValue($role);
|
||||
});
|
||||
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
|
||||
$this->assertUserRoleAutocreate($entity, function (EntityInterface $entity, RoleInterface $role) {
|
||||
$entity->user_role->setValue(['entity' => $role, 'target_id' => NULL]);
|
||||
});
|
||||
try {
|
||||
$message = 'Setting both the entity and an invalid target_id property fails.';
|
||||
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
|
||||
$this->assertUserRoleAutocreate($entity, function (EntityInterface $entity, RoleInterface $role) {
|
||||
$role->save();
|
||||
$entity->user_role->setValue(['entity' => $role, 'target_id' => $this->generateRandomEntityId(TRUE)]);
|
||||
});
|
||||
|
@ -307,10 +307,10 @@ class EntityReferenceFieldTest extends EntityKernelTestBase {
|
|||
catch (\InvalidArgumentException $e) {
|
||||
$this->pass($message);
|
||||
}
|
||||
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
|
||||
$this->assertUserRoleAutocreate($entity, function (EntityInterface $entity, RoleInterface $role) {
|
||||
$entity->user_role = $role;
|
||||
});
|
||||
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
|
||||
$this->assertUserRoleAutocreate($entity, function (EntityInterface $entity, RoleInterface $role) {
|
||||
$entity->user_role->entity = $role;
|
||||
});
|
||||
|
||||
|
@ -381,7 +381,7 @@ class EntityReferenceFieldTest extends EntityKernelTestBase {
|
|||
$definitions = [
|
||||
'target_reference' => BaseFieldDefinition::create('entity_reference')
|
||||
->setSetting('target_type', $entity_type->id())
|
||||
->setSetting('handler', 'default')
|
||||
->setSetting('handler', 'default'),
|
||||
];
|
||||
$this->state->set('entity_test_update.additional_base_field_definitions', $definitions);
|
||||
$this->entityManager->clearCachedDefinitions();
|
||||
|
|
|
@ -96,13 +96,11 @@ class EntityReferenceSelectionSortTest extends EntityKernelTestBase {
|
|||
$selection_options = [
|
||||
'target_type' => 'node',
|
||||
'handler' => 'default',
|
||||
'handler_settings' => [
|
||||
'target_bundles' => NULL,
|
||||
// Add sorting.
|
||||
'sort' => [
|
||||
'field' => 'field_text.value',
|
||||
'direction' => 'DESC',
|
||||
],
|
||||
'target_bundles' => NULL,
|
||||
// Add sorting.
|
||||
'sort' => [
|
||||
'field' => 'field_text.value',
|
||||
'direction' => 'DESC',
|
||||
],
|
||||
];
|
||||
$handler = $this->container->get('plugin.manager.entity_reference_selection')->getInstance($selection_options);
|
||||
|
@ -117,7 +115,7 @@ class EntityReferenceSelectionSortTest extends EntityKernelTestBase {
|
|||
$this->assertIdentical($result['article'], $expected_result, 'Query sorted by field returned expected values.');
|
||||
|
||||
// Assert sort by base field.
|
||||
$selection_options['handler_settings']['sort'] = [
|
||||
$selection_options['sort'] = [
|
||||
'field' => 'nid',
|
||||
'direction' => 'ASC',
|
||||
];
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTestMul;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRev;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
|
@ -23,9 +24,11 @@ class EntityRevisionTranslationTest extends EntityKernelTestBase {
|
|||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Enable an additional language.
|
||||
// Enable some additional languages.
|
||||
ConfigurableLanguage::createFromLangcode('de')->save();
|
||||
ConfigurableLanguage::createFromLangcode('it')->save();
|
||||
|
||||
$this->installEntitySchema('entity_test_mul');
|
||||
$this->installEntitySchema('entity_test_mulrev');
|
||||
}
|
||||
|
||||
|
@ -88,9 +91,9 @@ class EntityRevisionTranslationTest extends EntityKernelTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tests the translation values when saving a forward revision.
|
||||
* Tests the translation values when saving a pending revision.
|
||||
*/
|
||||
public function testTranslationValuesWhenSavingForwardRevisions() {
|
||||
public function testTranslationValuesWhenSavingPendingRevisions() {
|
||||
$user = $this->createUser();
|
||||
$storage = $this->entityManager->getStorage('entity_test_mulrev');
|
||||
|
||||
|
@ -103,33 +106,33 @@ class EntityRevisionTranslationTest extends EntityKernelTestBase {
|
|||
$entity->addTranslation('de', ['name' => 'default revision - de']);
|
||||
$entity->save();
|
||||
|
||||
// Create a forward revision for the entity and change a field value for
|
||||
// Create a pending revision for the entity and change a field value for
|
||||
// both languages.
|
||||
$forward_revision = $this->reloadEntity($entity);
|
||||
$pending_revision = $this->reloadEntity($entity);
|
||||
|
||||
$forward_revision->setNewRevision();
|
||||
$forward_revision->isDefaultRevision(FALSE);
|
||||
$pending_revision->setNewRevision();
|
||||
$pending_revision->isDefaultRevision(FALSE);
|
||||
|
||||
$forward_revision->name = 'forward revision - en';
|
||||
$forward_revision->save();
|
||||
$pending_revision->name = 'pending revision - en';
|
||||
$pending_revision->save();
|
||||
|
||||
$forward_revision_translation = $forward_revision->getTranslation('de');
|
||||
$forward_revision_translation->name = 'forward revision - de';
|
||||
$forward_revision_translation->save();
|
||||
$pending_revision_translation = $pending_revision->getTranslation('de');
|
||||
$pending_revision_translation->name = 'pending revision - de';
|
||||
$pending_revision_translation->save();
|
||||
|
||||
$forward_revision_id = $forward_revision->getRevisionId();
|
||||
$forward_revision = $storage->loadRevision($forward_revision_id);
|
||||
$pending_revision_id = $pending_revision->getRevisionId();
|
||||
$pending_revision = $storage->loadRevision($pending_revision_id);
|
||||
|
||||
// Change the value of the field in the default language, save the forward
|
||||
// Change the value of the field in the default language, save the pending
|
||||
// revision and check that the value of the field in the second language is
|
||||
// also taken from the forward revision, *not* from the default revision.
|
||||
$forward_revision->name = 'updated forward revision - en';
|
||||
$forward_revision->save();
|
||||
// also taken from the pending revision, *not* from the default revision.
|
||||
$pending_revision->name = 'updated pending revision - en';
|
||||
$pending_revision->save();
|
||||
|
||||
$forward_revision = $storage->loadRevision($forward_revision_id);
|
||||
$pending_revision = $storage->loadRevision($pending_revision_id);
|
||||
|
||||
$this->assertEquals($forward_revision->name->value, 'updated forward revision - en');
|
||||
$this->assertEquals($forward_revision->getTranslation('de')->name->value, 'forward revision - de');
|
||||
$this->assertEquals($pending_revision->name->value, 'updated pending revision - en');
|
||||
$this->assertEquals($pending_revision->getTranslation('de')->name->value, 'pending revision - de');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,4 +160,124 @@ class EntityRevisionTranslationTest extends EntityKernelTestBase {
|
|||
$this->assertFalse($translation->isDefaultRevision());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Entity\ContentEntityBase::setNewRevision
|
||||
*/
|
||||
public function testSetNewRevision() {
|
||||
$user = $this->createUser();
|
||||
|
||||
// All revisionable entity variations have to have the same results.
|
||||
foreach (entity_test_entity_types(ENTITY_TEST_TYPES_REVISABLE) as $entity_type) {
|
||||
$this->installEntitySchema($entity_type);
|
||||
|
||||
$entity = entity_create($entity_type, [
|
||||
'name' => 'foo',
|
||||
'user_id' => $user->id(),
|
||||
]);
|
||||
|
||||
$entity->save();
|
||||
$entity_id = $entity->id();
|
||||
$entity_rev_id = $entity->getRevisionId();
|
||||
$entity = entity_load($entity_type, $entity_id, TRUE);
|
||||
|
||||
$entity->setNewRevision(TRUE);
|
||||
$entity->setNewRevision(FALSE);
|
||||
$entity->save();
|
||||
$entity = entity_load($entity_type, $entity_id, TRUE);
|
||||
|
||||
$this->assertEquals($entity_rev_id, $entity->getRevisionId(), 'A new entity revision was not created.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that revision translations are correctly detected.
|
||||
*
|
||||
* @covers \Drupal\Core\Entity\ContentEntityStorageBase::isAnyStoredRevisionTranslated
|
||||
*/
|
||||
public function testIsAnyStoredRevisionTranslated() {
|
||||
/** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
|
||||
$storage = $this->entityManager->getStorage('entity_test_mul');
|
||||
$method = new \ReflectionMethod(get_class($storage), 'isAnyStoredRevisionTranslated');
|
||||
$method->setAccessible(TRUE);
|
||||
|
||||
// Check that a non-revisionable new entity is handled correctly.
|
||||
$entity = EntityTestMul::create();
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
$entity->addTranslation('it');
|
||||
$this->assertNotEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
|
||||
// Check that not yet stored translations are handled correctly.
|
||||
$entity = EntityTestMul::create();
|
||||
$entity->save();
|
||||
$entity->addTranslation('it');
|
||||
$this->assertNotEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
|
||||
// Check that removed translations are handled correctly.
|
||||
$entity->save();
|
||||
$entity->removeTranslation('it');
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertTrue($method->invoke($storage, $entity));
|
||||
$entity->save();
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
$entity->addTranslation('de');
|
||||
$entity->removeTranslation('de');
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
|
||||
// Check that a non-revisionable not translated entity is handled correctly.
|
||||
$entity = EntityTestMul::create();
|
||||
$entity->save();
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
|
||||
// Check that a non-revisionable translated entity is handled correctly.
|
||||
$entity->addTranslation('it');
|
||||
$entity->save();
|
||||
$this->assertNotEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertTrue($method->invoke($storage, $entity));
|
||||
|
||||
/** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
|
||||
$storage = $this->entityManager->getStorage('entity_test_mulrev');
|
||||
|
||||
// Check that a revisionable new entity is handled correctly.
|
||||
$entity = EntityTestMulRev::create();
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
$entity->addTranslation('it');
|
||||
$this->assertNotEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
|
||||
// Check that a revisionable not translated entity is handled correctly.
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->save();
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
|
||||
// Check that a revisionable translated pending revision is handled
|
||||
// correctly.
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $new_revision */
|
||||
$new_revision = $storage->createRevision($entity, FALSE);
|
||||
$new_revision->addTranslation('it');
|
||||
$new_revision->save();
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $storage->loadUnchanged($entity->id());
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertNotEmpty($new_revision->getTranslationLanguages(FALSE));
|
||||
$this->assertTrue($method->invoke($storage, $entity));
|
||||
|
||||
// Check that a revisionable translated default revision is handled
|
||||
// correctly.
|
||||
$new_revision->isDefaultRevision(TRUE);
|
||||
$new_revision->save();
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $storage->loadUnchanged($entity->id());
|
||||
$this->assertNotEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertNotEmpty($new_revision->getTranslationLanguages(FALSE));
|
||||
$this->assertTrue($method->invoke($storage, $entity));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,9 +8,11 @@ use Drupal\language\Entity\ConfigurableLanguage;
|
|||
/**
|
||||
* Tests the loaded Revision of an entity.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Entity\ContentEntityBase
|
||||
*
|
||||
* @group entity
|
||||
*/
|
||||
class EntityLoadedRevisionTest extends EntityKernelTestBase {
|
||||
class EntityRevisionsTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
|
@ -164,7 +166,99 @@ class EntityLoadedRevisionTest extends EntityKernelTestBase {
|
|||
$loadedRevisionId = \Drupal::state()->get('entity_test.loadedRevisionId');
|
||||
$this->assertEquals($entity->getLoadedRevisionId(), $loadedRevisionId);
|
||||
$this->assertEquals($entity->getRevisionId(), $entity->getLoadedRevisionId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that latest revisions are working as expected.
|
||||
*
|
||||
* @covers ::isLatestRevision
|
||||
*/
|
||||
public function testIsLatestRevision() {
|
||||
// Create a basic EntityTestMulRev entity and save it.
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->save();
|
||||
$this->assertTrue($entity->isLatestRevision());
|
||||
|
||||
// Load the created entity and create a new pending revision.
|
||||
$pending_revision = EntityTestMulRev::load($entity->id());
|
||||
$pending_revision->setNewRevision(TRUE);
|
||||
$pending_revision->isDefaultRevision(FALSE);
|
||||
|
||||
// The pending revision should still be marked as the latest one before it
|
||||
// is saved.
|
||||
$this->assertTrue($pending_revision->isLatestRevision());
|
||||
$pending_revision->save();
|
||||
$this->assertTrue($pending_revision->isLatestRevision());
|
||||
|
||||
// Load the default revision and check that it is not marked as the latest
|
||||
// revision.
|
||||
$default_revision = EntityTestMulRev::load($entity->id());
|
||||
$this->assertFalse($default_revision->isLatestRevision());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that latest affected revisions are working as expected.
|
||||
*
|
||||
* The latest revision affecting a particular translation behaves as the
|
||||
* latest revision for monolingual entities.
|
||||
*
|
||||
* @covers ::isLatestTranslationAffectedRevision
|
||||
* @covers \Drupal\Core\Entity\ContentEntityStorageBase::getLatestRevisionId
|
||||
* @covers \Drupal\Core\Entity\ContentEntityStorageBase::getLatestTranslationAffectedRevisionId
|
||||
*/
|
||||
public function testIsLatestAffectedRevisionTranslation() {
|
||||
ConfigurableLanguage::createFromLangcode('it')->save();
|
||||
|
||||
// Create a basic EntityTestMulRev entity and save it.
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->setName($this->randomString());
|
||||
$entity->save();
|
||||
$this->assertTrue($entity->isLatestTranslationAffectedRevision());
|
||||
|
||||
// Load the created entity and create a new pending revision.
|
||||
$pending_revision = EntityTestMulRev::load($entity->id());
|
||||
$pending_revision->setName($this->randomString());
|
||||
$pending_revision->setNewRevision(TRUE);
|
||||
$pending_revision->isDefaultRevision(FALSE);
|
||||
|
||||
// Check that no revision affecting Italian is available, given that no
|
||||
// Italian translation has been created yet.
|
||||
/** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
|
||||
$storage = $this->entityManager->getStorage($entity->getEntityTypeId());
|
||||
$this->assertNull($storage->getLatestTranslationAffectedRevisionId($entity->id(), 'it'));
|
||||
$this->assertEquals($pending_revision->getLoadedRevisionId(), $storage->getLatestRevisionId($entity->id()));
|
||||
|
||||
// The pending revision should still be marked as the latest affected one
|
||||
// before it is saved.
|
||||
$this->assertTrue($pending_revision->isLatestTranslationAffectedRevision());
|
||||
$pending_revision->save();
|
||||
$this->assertTrue($pending_revision->isLatestTranslationAffectedRevision());
|
||||
|
||||
// Load the default revision and check that it is not marked as the latest
|
||||
// (translation-affected) revision.
|
||||
$default_revision = EntityTestMulRev::load($entity->id());
|
||||
$this->assertFalse($default_revision->isLatestRevision());
|
||||
$this->assertFalse($default_revision->isLatestTranslationAffectedRevision());
|
||||
|
||||
// Add a translation in a new pending revision and verify that both the
|
||||
// English and Italian revision translations are the latest affected
|
||||
// revisions for their respective languages, while the English revision is
|
||||
// not the latest revision.
|
||||
/** @var \Drupal\entity_test\Entity\EntityTestMulRev $en_revision */
|
||||
$en_revision = clone $pending_revision;
|
||||
/** @var \Drupal\entity_test\Entity\EntityTestMulRev $it_revision */
|
||||
$it_revision = $pending_revision->addTranslation('it');
|
||||
$it_revision->setName($this->randomString());
|
||||
$it_revision->setNewRevision(TRUE);
|
||||
$it_revision->isDefaultRevision(FALSE);
|
||||
// @todo Remove this once the "original" property works with revisions. See
|
||||
// https://www.drupal.org/project/drupal/issues/2859042.
|
||||
$it_revision->original = $storage->loadRevision($it_revision->getLoadedRevisionId());
|
||||
$it_revision->save();
|
||||
$this->assertTrue($it_revision->isLatestRevision());
|
||||
$this->assertTrue($it_revision->isLatestTranslationAffectedRevision());
|
||||
$this->assertFalse($en_revision->isLatestRevision());
|
||||
$this->assertTrue($en_revision->isLatestTranslationAffectedRevision());
|
||||
}
|
||||
|
||||
}
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
||||
/**
|
||||
* Tests adding a custom bundle field.
|
||||
* Tests the default entity storage schema handler.
|
||||
*
|
||||
* @group system
|
||||
* @group Entity
|
||||
*/
|
||||
class EntitySchemaTest extends EntityKernelTestBase {
|
||||
|
||||
|
@ -86,27 +88,199 @@ class EntitySchemaTest extends EntityKernelTestBase {
|
|||
// Initially only the base table and the dedicated field data table should
|
||||
// exist.
|
||||
foreach ($tables as $index => $table) {
|
||||
$this->assertEqual($schema_handler->tableExists($table), !$index, SafeMarkup::format('Entity schema correct for the @table table.', ['@table' => $table]));
|
||||
$this->assertEqual($schema_handler->tableExists($table), !$index, new FormattableMarkup('Entity schema correct for the @table table.', ['@table' => $table]));
|
||||
}
|
||||
$this->assertTrue($schema_handler->tableExists($dedicated_tables[0]), SafeMarkup::format('Field schema correct for the @table table.', ['@table' => $table]));
|
||||
$this->assertTrue($schema_handler->tableExists($dedicated_tables[0]), new FormattableMarkup('Field schema correct for the @table table.', ['@table' => $table]));
|
||||
|
||||
// Update the entity type definition and check that the entity schema now
|
||||
// supports translations and revisions.
|
||||
$this->updateEntityType(TRUE);
|
||||
foreach ($tables as $table) {
|
||||
$this->assertTrue($schema_handler->tableExists($table), SafeMarkup::format('Entity schema correct for the @table table.', ['@table' => $table]));
|
||||
$this->assertTrue($schema_handler->tableExists($table), new FormattableMarkup('Entity schema correct for the @table table.', ['@table' => $table]));
|
||||
}
|
||||
foreach ($dedicated_tables as $table) {
|
||||
$this->assertTrue($schema_handler->tableExists($table), SafeMarkup::format('Field schema correct for the @table table.', ['@table' => $table]));
|
||||
$this->assertTrue($schema_handler->tableExists($table), new FormattableMarkup('Field schema correct for the @table table.', ['@table' => $table]));
|
||||
}
|
||||
|
||||
// Revert changes and check that the entity schema now does not support
|
||||
// neither translations nor revisions.
|
||||
$this->updateEntityType(FALSE);
|
||||
foreach ($tables as $index => $table) {
|
||||
$this->assertEqual($schema_handler->tableExists($table), !$index, SafeMarkup::format('Entity schema correct for the @table table.', ['@table' => $table]));
|
||||
$this->assertEqual($schema_handler->tableExists($table), !$index, new FormattableMarkup('Entity schema correct for the @table table.', ['@table' => $table]));
|
||||
}
|
||||
$this->assertTrue($schema_handler->tableExists($dedicated_tables[0]), SafeMarkup::format('Field schema correct for the @table table.', ['@table' => $table]));
|
||||
$this->assertTrue($schema_handler->tableExists($dedicated_tables[0]), new FormattableMarkup('Field schema correct for the @table table.', ['@table' => $table]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deleting and creating a field that is part of a primary key.
|
||||
*
|
||||
* @param string $entity_type_id
|
||||
* The ID of the entity type whose schema is being tested.
|
||||
* @param string $field_name
|
||||
* The name of the field that is being re-installed.
|
||||
*
|
||||
* @dataProvider providerTestPrimaryKeyUpdate
|
||||
*/
|
||||
public function testPrimaryKeyUpdate($entity_type_id, $field_name) {
|
||||
// EntityKernelTestBase::setUp() already installs the schema for the
|
||||
// 'entity_test' entity type.
|
||||
if ($entity_type_id !== 'entity_test') {
|
||||
$this->installEntitySchema($entity_type_id);
|
||||
}
|
||||
|
||||
/* @var \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface $update_manager */
|
||||
$update_manager = $this->container->get('entity.definition_update_manager');
|
||||
$entity_type = $update_manager->getEntityType($entity_type_id);
|
||||
|
||||
/* @see \Drupal\Core\Entity\ContentEntityBase::baseFieldDefinitions() */
|
||||
switch ($field_name) {
|
||||
case 'id':
|
||||
$field = BaseFieldDefinition::create('integer')
|
||||
->setLabel('ID')
|
||||
->setReadOnly(TRUE)
|
||||
->setSetting('unsigned', TRUE);
|
||||
break;
|
||||
|
||||
case 'revision_id':
|
||||
$field = BaseFieldDefinition::create('integer')
|
||||
->setLabel('Revision ID')
|
||||
->setReadOnly(TRUE)
|
||||
->setSetting('unsigned', TRUE);
|
||||
break;
|
||||
|
||||
case 'langcode':
|
||||
$field = BaseFieldDefinition::create('language')
|
||||
->setLabel('Language');
|
||||
if ($entity_type->isRevisionable()) {
|
||||
$field->setRevisionable(TRUE);
|
||||
}
|
||||
if ($entity_type->isTranslatable()) {
|
||||
$field->setTranslatable(TRUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$field
|
||||
->setName($field_name)
|
||||
->setTargetEntityTypeId($entity_type_id)
|
||||
->setProvider($entity_type->getProvider());
|
||||
|
||||
// Build up a map of expected primary keys depending on the entity type
|
||||
// configuration.
|
||||
$id_key = $entity_type->getKey('id');
|
||||
$revision_key = $entity_type->getKey('revision');
|
||||
$langcode_key = $entity_type->getKey('langcode');
|
||||
|
||||
$expected = [];
|
||||
$expected[$entity_type->getBaseTable()] = [$id_key];
|
||||
if ($entity_type->isRevisionable()) {
|
||||
$expected[$entity_type->getRevisionTable()] = [$revision_key];
|
||||
}
|
||||
if ($entity_type->isTranslatable()) {
|
||||
$expected[$entity_type->getDataTable()] = [$id_key, $langcode_key];
|
||||
}
|
||||
if ($entity_type->isRevisionable() && $entity_type->isTranslatable()) {
|
||||
$expected[$entity_type->getRevisionDataTable()] = [$revision_key, $langcode_key];
|
||||
}
|
||||
|
||||
// First, test explicitly deleting and re-installing a field. Make sure that
|
||||
// all primary keys are there to start with.
|
||||
$this->assertSame($expected, $this->findPrimaryKeys($entity_type));
|
||||
|
||||
// Then uninstall the field and make sure all primary keys that the field
|
||||
// was part of have been updated. Since this is not a valid state of the
|
||||
// entity type (for example a revisionable entity type without a revision ID
|
||||
// field or a translatable entity type without a language code field) the
|
||||
// actual primary keys at this point are irrelevant.
|
||||
$update_manager->uninstallFieldStorageDefinition($field);
|
||||
$this->assertNotEquals($expected, $this->findPrimaryKeys($entity_type));
|
||||
|
||||
// Finally, reinstall the field and make sure the primary keys have been
|
||||
// recreated.
|
||||
$update_manager->installFieldStorageDefinition($field->getName(), $entity_type_id, $field->getProvider(), $field);
|
||||
$this->assertSame($expected, $this->findPrimaryKeys($entity_type));
|
||||
|
||||
// Now test updating a field without data. This will end up deleting
|
||||
// and re-creating the field, similar to the code above.
|
||||
$update_manager->updateFieldStorageDefinition($field);
|
||||
$this->assertSame($expected, $this->findPrimaryKeys($entity_type));
|
||||
|
||||
// Now test updating a field with data.
|
||||
/* @var \Drupal\Core\Entity\FieldableEntityStorageInterface $storage */
|
||||
$storage = $this->entityManager->getStorage($entity_type_id);
|
||||
// The schema of ID fields is incorrectly recreated as 'int' instead of
|
||||
// 'serial', so we manually have to specify an ID.
|
||||
// @todo Remove this in https://www.drupal.org/project/drupal/issues/2928906
|
||||
$storage->create(['id' => 1, 'revision_id' => 1])->save();
|
||||
$this->assertTrue($storage->countFieldData($field, TRUE));
|
||||
$update_manager->updateFieldStorageDefinition($field);
|
||||
$this->assertSame($expected, $this->findPrimaryKeys($entity_type));
|
||||
$this->assertTrue($storage->countFieldData($field, TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the primary keys for a given entity type.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type whose primary keys are being fetched.
|
||||
*
|
||||
* @return array[]
|
||||
* An array where the keys are the table names of the entity type's tables
|
||||
* and the values are a list of the respective primary keys.
|
||||
*/
|
||||
protected function findPrimaryKeys(EntityTypeInterface $entity_type) {
|
||||
$base_table = $entity_type->getBaseTable();
|
||||
$revision_table = $entity_type->getRevisionTable();
|
||||
$data_table = $entity_type->getDataTable();
|
||||
$revision_data_table = $entity_type->getRevisionDataTable();
|
||||
|
||||
$schema = $this->database->schema();
|
||||
$find_primary_key_columns = new \ReflectionMethod(get_class($schema), 'findPrimaryKeyColumns');
|
||||
$find_primary_key_columns->setAccessible(TRUE);
|
||||
|
||||
// Build up a map of primary keys depending on the entity type
|
||||
// configuration. If the field that is being removed is part of a table's
|
||||
// primary key, we skip the assertion for that table as this represents an
|
||||
// intermediate and invalid state of the entity schema.
|
||||
$primary_keys[$base_table] = $find_primary_key_columns->invoke($schema, $base_table);
|
||||
if ($entity_type->isRevisionable()) {
|
||||
$primary_keys[$revision_table] = $find_primary_key_columns->invoke($schema, $revision_table);
|
||||
}
|
||||
if ($entity_type->isTranslatable()) {
|
||||
$primary_keys[$data_table] = $find_primary_key_columns->invoke($schema, $data_table);
|
||||
}
|
||||
if ($entity_type->isRevisionable() && $entity_type->isTranslatable()) {
|
||||
$primary_keys[$revision_data_table] = $find_primary_key_columns->invoke($schema, $revision_data_table);
|
||||
}
|
||||
|
||||
return $primary_keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test cases for EntitySchemaTest::testPrimaryKeyUpdate()
|
||||
*
|
||||
* @return array
|
||||
* An array of test cases consisting of an entity type ID and a field name.
|
||||
*/
|
||||
public function providerTestPrimaryKeyUpdate() {
|
||||
// Build up test cases for all possible entity type configurations.
|
||||
// For each entity type we test reinstalling each field that is part of
|
||||
// any table's primary key.
|
||||
$tests = [];
|
||||
|
||||
$tests['entity_test:id'] = ['entity_test', 'id'];
|
||||
|
||||
$tests['entity_test_rev:id'] = ['entity_test_rev', 'id'];
|
||||
$tests['entity_test_rev:revision_id'] = ['entity_test_rev', 'revision_id'];
|
||||
|
||||
$tests['entity_test_mul:id'] = ['entity_test_mul', 'id'];
|
||||
$tests['entity_test_mul:langcode'] = ['entity_test_mul', 'langcode'];
|
||||
|
||||
$tests['entity_test_mulrev:id'] = ['entity_test_mulrev', 'id'];
|
||||
$tests['entity_test_mulrev:revision_id'] = ['entity_test_mulrev', 'revision_id'];
|
||||
$tests['entity_test_mulrev:langcode'] = ['entity_test_mulrev', 'langcode'];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\TypedData\TranslationStatusInterface;
|
||||
use Drupal\entity_test\Entity\EntityTestMul;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRev;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
|
@ -341,12 +342,12 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
// retrieve a translation referring to it.
|
||||
$translation = $entity->getTranslation(LanguageInterface::LANGCODE_NOT_SPECIFIED);
|
||||
$this->assertFalse($translation->isNewTranslation(), 'Existing translations are not marked as new.');
|
||||
$this->assertIdentical($entity, $translation, 'The translation object corresponding to a non-default language is the entity object itself when the entity is language-neutral.');
|
||||
$this->assertSame($entity, $translation, 'The translation object corresponding to a non-default language is the entity object itself when the entity is language-neutral.');
|
||||
$entity->{$langcode_key}->value = $default_langcode;
|
||||
$translation = $entity->getTranslation($default_langcode);
|
||||
$this->assertIdentical($entity, $translation, 'The translation object corresponding to the default language (explicit) is the entity object itself.');
|
||||
$this->assertSame($entity, $translation, 'The translation object corresponding to the default language (explicit) is the entity object itself.');
|
||||
$translation = $entity->getTranslation(LanguageInterface::LANGCODE_DEFAULT);
|
||||
$this->assertIdentical($entity, $translation, 'The translation object corresponding to the default language (implicit) is the entity object itself.');
|
||||
$this->assertSame($entity, $translation, 'The translation object corresponding to the default language (implicit) is the entity object itself.');
|
||||
$this->assertTrue($entity->{$default_langcode_key}->value, 'The translation object is the default one.');
|
||||
|
||||
// Verify that trying to retrieve a translation for a locked language when
|
||||
|
@ -657,7 +658,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
$translation = $this->entityManager->getTranslationFromContext($entity2, $default_langcode);
|
||||
$translation_build = $controller->view($translation);
|
||||
$translation_output = (string) $renderer->renderRoot($translation_build);
|
||||
$this->assertIdentical($entity2_output, $translation_output, 'When the entity has no translation no fallback is applied.');
|
||||
$this->assertSame($entity2_output, $translation_output, 'When the entity has no translation no fallback is applied.');
|
||||
|
||||
// Checks that entity translations are rendered properly.
|
||||
$controller = $this->entityManager->getViewBuilder($entity_type);
|
||||
|
@ -806,7 +807,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
foreach ($langcodes as $langcode) {
|
||||
$adapter = $entity->getTranslation($langcode)->getTypedData();
|
||||
$name = $adapter->get('name')->value;
|
||||
$this->assertEqual($name, $values[$langcode]['name'], SafeMarkup::format('Name correctly retrieved from "@langcode" adapter', ['@langcode' => $langcode]));
|
||||
$this->assertEqual($name, $values[$langcode]['name'], new FormattableMarkup('Name correctly retrieved from "@langcode" adapter', ['@langcode' => $langcode]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1013,4 +1014,31 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the translation object cache.
|
||||
*/
|
||||
public function testTranslationObjectCache() {
|
||||
$default_langcode = $this->langcodes[1];
|
||||
$translation_langcode = $this->langcodes[2];
|
||||
|
||||
$entity = EntityTestMul::create([
|
||||
'name' => 'test',
|
||||
'langcode' => $default_langcode,
|
||||
]);
|
||||
$entity->save();
|
||||
$entity->addTranslation($translation_langcode)->save();
|
||||
|
||||
// Test that the default translation object is put into the translation
|
||||
// object cache when a new translation object is initialized.
|
||||
$entity = \Drupal::entityTypeManager()->getStorage($entity->getEntityTypeId())->loadUnchanged($entity->id());
|
||||
$default_translation_spl_object_hash = spl_object_hash($entity);
|
||||
$this->assertEquals($default_translation_spl_object_hash, spl_object_hash($entity->getTranslation($translation_langcode)->getTranslation($default_langcode)));
|
||||
|
||||
// Test that non-default translations are always served from the translation
|
||||
// object cache.
|
||||
$entity = \Drupal::entityTypeManager()->getStorage($entity->getEntityTypeId())->loadUnchanged($entity->id());
|
||||
$this->assertEquals(spl_object_hash($entity->getTranslation($translation_langcode)), spl_object_hash($entity->getTranslation($translation_langcode)));
|
||||
$this->assertEquals(spl_object_hash($entity->getTranslation($translation_langcode)), spl_object_hash($entity->getTranslation($translation_langcode)->getTranslation($default_langcode)->getTranslation($translation_langcode)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,11 @@ class EntityTypeConstraintsTest extends EntityKernelTestBase {
|
|||
// Test reading the annotation. There should be two constraints, the defined
|
||||
// constraint and the automatically added EntityChanged constraint.
|
||||
$entity_type = $this->entityManager->getDefinition('entity_test_constraints');
|
||||
$default_constraints = ['NotNull' => [], 'EntityChanged' => NULL];
|
||||
$default_constraints = [
|
||||
'NotNull' => [],
|
||||
'EntityChanged' => NULL,
|
||||
'EntityUntranslatableFields' => NULL,
|
||||
];
|
||||
$this->assertEqual($default_constraints, $entity_type->getConstraints());
|
||||
|
||||
// Enable our test module and test extending constraints.
|
||||
|
@ -41,7 +45,7 @@ class EntityTypeConstraintsTest extends EntityKernelTestBase {
|
|||
$this->assertEqual($default_constraints + $extra_constraints, $entity_type->getConstraints());
|
||||
|
||||
// Test altering constraints.
|
||||
$altered_constraints = ['Test' => [ 'some_setting' => TRUE]];
|
||||
$altered_constraints = ['Test' => ['some_setting' => TRUE]];
|
||||
$this->state->set('entity_test_constraints.alter', $altered_constraints);
|
||||
// Clear the cache in state instance in the Drupal container, so it can pick
|
||||
// up the modified value.
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\TypedData\EntityDataDefinition;
|
||||
use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
@ -11,6 +14,7 @@ use Drupal\Core\TypedData\DataReferenceDefinition;
|
|||
use Drupal\Core\TypedData\DataReferenceDefinitionInterface;
|
||||
use Drupal\Core\TypedData\ListDataDefinitionInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
|
||||
/**
|
||||
* Tests deriving metadata of entity and field data types.
|
||||
|
@ -31,10 +35,11 @@ class EntityTypedDataDefinitionTest extends KernelTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['filter', 'text', 'node', 'user'];
|
||||
public static $modules = ['system', 'filter', 'text', 'node', 'user'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setup();
|
||||
|
||||
$this->typedDataManager = $this->container->get('typed_data_manager');
|
||||
}
|
||||
|
||||
|
@ -81,11 +86,21 @@ class EntityTypedDataDefinitionTest extends KernelTestBase {
|
|||
* Tests deriving metadata about entities.
|
||||
*/
|
||||
public function testEntities() {
|
||||
NodeType::create([
|
||||
'type' => 'article',
|
||||
'name' => 'Article',
|
||||
])->save();
|
||||
|
||||
$entity_definition = EntityDataDefinition::create('node');
|
||||
$bundle_definition = EntityDataDefinition::create('node', 'article');
|
||||
// Entities are complex data.
|
||||
$this->assertFalse($entity_definition instanceof ListDataDefinitionInterface);
|
||||
$this->assertTrue($entity_definition instanceof ComplexDataDefinitionInterface);
|
||||
|
||||
// Entity definitions should inherit their labels from the entity type.
|
||||
$this->assertEquals('Content', $entity_definition->getLabel());
|
||||
$this->assertEquals('Article', $bundle_definition->getLabel());
|
||||
|
||||
$field_definitions = $entity_definition->getPropertyDefinitions();
|
||||
// Comparison should ignore the internal static cache, so compare the
|
||||
// serialized objects instead.
|
||||
|
@ -101,8 +116,8 @@ class EntityTypedDataDefinitionTest extends KernelTestBase {
|
|||
|
||||
// Test that the definition factory creates the right definitions for all
|
||||
// entity data types variants.
|
||||
$this->assertEqual($this->typedDataManager->createDataDefinition('entity'), EntityDataDefinition::create());
|
||||
$this->assertEqual($this->typedDataManager->createDataDefinition('entity:node'), EntityDataDefinition::create('node'));
|
||||
$this->assertEqual(serialize($this->typedDataManager->createDataDefinition('entity')), serialize(EntityDataDefinition::create()));
|
||||
$this->assertEqual(serialize($this->typedDataManager->createDataDefinition('entity:node')), serialize(EntityDataDefinition::create('node')));
|
||||
|
||||
// Config entities don't support typed data.
|
||||
$entity_definition = EntityDataDefinition::create('node_type');
|
||||
|
@ -123,7 +138,40 @@ class EntityTypedDataDefinitionTest extends KernelTestBase {
|
|||
// Test that the definition factory creates the right definition object.
|
||||
$reference_definition2 = $this->typedDataManager->createDataDefinition('entity_reference');
|
||||
$this->assertTrue($reference_definition2 instanceof DataReferenceDefinitionInterface);
|
||||
$this->assertEqual($reference_definition2, $reference_definition);
|
||||
$this->assertEqual(serialize($reference_definition2), serialize($reference_definition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that an entity annotation can mark the data definition as internal.
|
||||
*
|
||||
* @dataProvider entityDefinitionIsInternalProvider
|
||||
*/
|
||||
public function testEntityDefinitionIsInternal($internal, $expected) {
|
||||
$entity_type_id = $this->randomMachineName();
|
||||
|
||||
$entity_type = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity_type->entityClassImplements(ConfigEntityInterface::class)->willReturn(FALSE);
|
||||
$entity_type->getLabel()->willReturn($this->randomString());
|
||||
$entity_type->getConstraints()->willReturn([]);
|
||||
$entity_type->isInternal()->willReturn($internal);
|
||||
|
||||
$entity_manager = $this->prophesize(EntityManagerInterface::class);
|
||||
$entity_manager->getDefinitions()->willReturn([$entity_type_id => $entity_type->reveal()]);
|
||||
$this->container->set('entity.manager', $entity_manager->reveal());
|
||||
|
||||
$entity_data_definition = EntityDataDefinition::create($entity_type_id);
|
||||
$this->assertSame($expected, $entity_data_definition->isInternal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test cases for testEntityDefinitionIsInternal.
|
||||
*/
|
||||
public function entityDefinitionIsInternalProvider() {
|
||||
return [
|
||||
'internal' => [TRUE, TRUE],
|
||||
'external' => [FALSE, FALSE],
|
||||
'undefined' => [NULL, FALSE],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Entity\Plugin\Validation\Constraint\CompositeConstraintBase;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
/**
|
||||
* Tests the Entity Validation API.
|
||||
|
@ -16,7 +17,7 @@ class EntityValidationTest extends EntityKernelTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['filter', 'text'];
|
||||
public static $modules = ['filter', 'text', 'language'];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
@ -39,6 +40,10 @@ class EntityValidationTest extends EntityKernelTestBase {
|
|||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Enable an additional language.
|
||||
ConfigurableLanguage::createFromLangcode('de')
|
||||
->save();
|
||||
|
||||
// Create the test field.
|
||||
module_load_install('entity_test');
|
||||
entity_test_install();
|
||||
|
@ -196,8 +201,53 @@ class EntityValidationTest extends EntityKernelTestBase {
|
|||
$this->assertTrue($constraint instanceof CompositeConstraintBase, 'Constraint is composite constraint.');
|
||||
$this->assertEqual('type', $violations[0]->getPropertyPath());
|
||||
|
||||
/** @var CompositeConstraintBase $constraint */
|
||||
/** @var \Drupal\Core\Entity\Plugin\Validation\Constraint\CompositeConstraintBase $constraint */
|
||||
$this->assertEqual($constraint->coversFields(), ['name', 'type'], 'Information about covered fields can be retrieved.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the EntityChangedConstraintValidator with multiple translations.
|
||||
*/
|
||||
public function testEntityChangedConstraintOnConcurrentMultilingualEditing() {
|
||||
$this->installEntitySchema('entity_test_mulrev_changed');
|
||||
$storage = \Drupal::entityTypeManager()
|
||||
->getStorage('entity_test_mulrev_changed');
|
||||
|
||||
// Create a test entity.
|
||||
$entity = $this->createTestEntity('entity_test_mulrev_changed');
|
||||
$entity->save();
|
||||
|
||||
$entity->setChangedTime($entity->getChangedTime() - 1);
|
||||
$violations = $entity->validate();
|
||||
$this->assertEquals(1, $violations->count());
|
||||
$this->assertEqual($violations[0]->getMessage(), 'The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.');
|
||||
|
||||
$entity = $storage->loadUnchanged($entity->id());
|
||||
$translation = $entity->addTranslation('de');
|
||||
$entity->save();
|
||||
|
||||
// Ensure that the new translation has a newer changed timestamp than the
|
||||
// default translation.
|
||||
$this->assertGreaterThan($entity->getChangedTime(), $translation->getChangedTime());
|
||||
|
||||
// Simulate concurrent form editing by saving the entity with an altered
|
||||
// non-translatable field in order for the changed timestamp to be updated
|
||||
// across all entity translations.
|
||||
$original_entity_time = $entity->getChangedTime();
|
||||
$entity->set('not_translatable', $this->randomString());
|
||||
$entity->save();
|
||||
// Simulate form submission of an uncached form by setting the previous
|
||||
// timestamp of an entity translation on the saved entity object. This
|
||||
// happens in the entity form API where we put the changed timestamp of
|
||||
// the entity in a form hidden value and then set it on the entity which on
|
||||
// form submit is loaded from the storage if the form is not yet cached.
|
||||
$entity->setChangedTime($original_entity_time);
|
||||
// Setting the changed timestamp from the user input on the entity loaded
|
||||
// from the storage is used as a prevention from saving a form built with a
|
||||
// previous version of the entity and thus reverting changes by other users.
|
||||
$violations = $entity->validate();
|
||||
$this->assertEquals(1, $violations->count());
|
||||
$this->assertEqual($violations[0]->getMessage(), 'The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue