Update to Drupal 8.0.0-rc3. For more information, see https://www.drupal.org/node/2608078
This commit is contained in:
parent
6419a031d7
commit
4afb23bbd3
762 changed files with 20080 additions and 6368 deletions
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\KernelTests\Core\Theme\ThemeRenderAndAutoescapeTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\KernelTests\Core\Theme;
|
||||
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Component\Render\MarkupInterface;
|
||||
use Drupal\Component\Render\MarkupTrait;
|
||||
use Drupal\Core\GeneratedLink;
|
||||
use Drupal\Core\Render\RenderContext;
|
||||
use Drupal\Core\Render\Markup;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests Twig with MarkupInterface objects.
|
||||
*
|
||||
* @group Theme
|
||||
*/
|
||||
class TwigMarkupInterfaceTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'language'
|
||||
];
|
||||
|
||||
/**
|
||||
* @dataProvider providerTestMarkupInterfaceEmpty
|
||||
*/
|
||||
public function testMarkupInterfaceEmpty($expected, $variable) {
|
||||
$this->assertEquals($expected, $this->renderObjectWithTwig($variable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide test examples.
|
||||
*/
|
||||
public function providerTestMarkupInterfaceEmpty() {
|
||||
return [
|
||||
'empty TranslatableMarkup' => ['', new TranslatableMarkup('')],
|
||||
'non-empty TranslatableMarkup' => ['<span>test</span>', new TranslatableMarkup('test')],
|
||||
'empty FormattableMarkup' => ['', new FormattableMarkup('', ['@foo' => 'bar'])],
|
||||
'non-empty FormattableMarkup' => ['<span>bar</span>', new FormattableMarkup('@foo', ['@foo' => 'bar'])],
|
||||
'non-empty Markup' => ['<span>test</span>', Markup::create('test')],
|
||||
'empty GeneratedLink' => ['', new GeneratedLink()],
|
||||
'non-empty GeneratedLink' => ['<span><a hef="http://www.example.com">test</a></span>', (new GeneratedLink())->setGeneratedLink('<a hef="http://www.example.com">test</a>')],
|
||||
// Test objects that do not implement \Countable.
|
||||
'empty SafeMarkupTestMarkup' => ['<span></span>', SafeMarkupTestMarkup::create('')],
|
||||
'non-empty SafeMarkupTestMarkup' => ['<span>test</span>', SafeMarkupTestMarkup::create('test')],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests behaviour if a string is translated to become an empty string.
|
||||
*/
|
||||
public function testEmptyTranslation() {
|
||||
$settings = Settings::getAll();
|
||||
$settings['locale_custom_strings_en'] = ['' => ['test' => '']];
|
||||
// Recreate the settings static.
|
||||
new Settings($settings);
|
||||
|
||||
$variable = new TranslatableMarkup('test');
|
||||
$this->assertEquals('', $this->renderObjectWithTwig($variable));
|
||||
|
||||
$variable = new TranslatableMarkup('test', [], ['langcode' => 'de']);
|
||||
$this->assertEquals('<span>test</span>', $this->renderObjectWithTwig($variable));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Drupal\Component\Render\MarkupInterface
|
||||
* The rendered HTML.
|
||||
*/
|
||||
protected function renderObjectWithTwig($variable) {
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = \Drupal::service('renderer');
|
||||
$context = new RenderContext();
|
||||
return $renderer->executeInRenderContext($context, function () use ($renderer, $variable) {
|
||||
$elements = [
|
||||
'#type' => 'inline_template',
|
||||
'#template' => '{%- if variable is not empty -%}<span>{{ variable }}</span>{%- endif -%}',
|
||||
'#context' => array('variable' => $variable),
|
||||
];
|
||||
return $renderer->render($elements);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements MarkupInterface without implementing \Countable
|
||||
*/
|
||||
class SafeMarkupTestMarkup implements MarkupInterface {
|
||||
use MarkupTrait;
|
||||
|
||||
/**
|
||||
* Overrides MarkupTrait::create() to allow creation with empty strings.
|
||||
*/
|
||||
public static function create($string) {
|
||||
$object = new static();
|
||||
$object->string = $string;
|
||||
return $object;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\InspectorTest.
|
||||
* Contains \Drupal\Tests\Component\Assertion\InspectorTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\Assertion;
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Component\HttpFoundation\SecuredRedirectResponseTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Component\HttpFoundation;
|
||||
|
||||
use Drupal\Component\HttpFoundation\SecuredRedirectResponse;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
|
||||
/**
|
||||
* Test secure redirect base class.
|
||||
*
|
||||
* @group Routing
|
||||
* @coversDefaultClass \Drupal\Component\HttpFoundation\SecuredRedirectResponse
|
||||
*/
|
||||
class SecuredRedirectResponseTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Test copying of redirect response.
|
||||
*
|
||||
* @covers ::createFromRedirectResponse
|
||||
* @covers ::fromResponse
|
||||
*/
|
||||
public function testRedirectCopy() {
|
||||
$redirect = new RedirectResponse('/magic_redirect_url', 301, ['x-cache-foobar' => 123]);
|
||||
$redirect->setProtocolVersion('2.0');
|
||||
$redirect->setCharset('ibm-943_P14A-2000');
|
||||
$redirect->headers->setCookie(new Cookie('name', 'value'));
|
||||
|
||||
// Make a cloned redirect.
|
||||
$secureRedirect = SecuredRedirectStub::createFromRedirectResponse($redirect);
|
||||
$this->assertEquals('/magic_redirect_url', $secureRedirect->getTargetUrl());
|
||||
$this->assertEquals(301, $secureRedirect->getStatusCode());
|
||||
// We pull the headers from the original redirect because there are default headers applied.
|
||||
$headers1 = $redirect->headers->allPreserveCase();
|
||||
$headers2 = $secureRedirect->headers->allPreserveCase();
|
||||
// We unset cache headers so we don't test arcane Symfony weirdness.
|
||||
// https://github.com/symfony/symfony/issues/16171
|
||||
unset($headers1['Cache-Control'], $headers2['Cache-Control']);
|
||||
$this->assertEquals($headers1, $headers2);
|
||||
$this->assertEquals('2.0', $secureRedirect->getProtocolVersion());
|
||||
$this->assertEquals('ibm-943_P14A-2000', $secureRedirect->getCharset());
|
||||
$this->assertEquals($redirect->headers->getCookies(), $secureRedirect->headers->getCookies());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SecuredRedirectStub extends SecuredRedirectResponse {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function isSafe($url) {
|
||||
// Empty implementation for testing.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
|
@ -22,6 +22,20 @@ use Drupal\Tests\UnitTestCase;
|
|||
*/
|
||||
class SafeMarkupTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The error message of the last error in the error handler.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $lastErrorMessage;
|
||||
|
||||
/**
|
||||
* The error number of the last error in the error handler.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $lastErrorNumber;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -159,6 +173,40 @@ class SafeMarkupTest extends UnitTestCase {
|
|||
|
||||
return $tests;
|
||||
}
|
||||
/**
|
||||
* Custom error handler that saves the last error.
|
||||
*
|
||||
* We need this custom error handler because we cannot rely on the error to
|
||||
* exception conversion as __toString is never allowed to leak any kind of
|
||||
* exception.
|
||||
*
|
||||
* @param int $error_number
|
||||
* The error number.
|
||||
* @param string $error_message
|
||||
* The error message.
|
||||
*/
|
||||
public function errorHandler($error_number, $error_message) {
|
||||
$this->lastErrorNumber = $error_number;
|
||||
$this->lastErrorMessage = $error_message;
|
||||
}
|
||||
|
||||
/**
|
||||
* String formatting with SafeMarkup::format() and an unsupported placeholder.
|
||||
*
|
||||
* When you call SafeMarkup::format() with an unsupported placeholder, an
|
||||
* InvalidArgumentException should be thrown.
|
||||
*/
|
||||
public function testUnexpectedFormat() {
|
||||
|
||||
// We set a custom error handler because of https://github.com/sebastianbergmann/phpunit/issues/487
|
||||
set_error_handler([$this, 'errorHandler']);
|
||||
// We want this to trigger an error.
|
||||
$error = SafeMarkup::format('Broken placeholder: ~placeholder', ['~placeholder' => 'broken'])->__toString();
|
||||
restore_error_handler();
|
||||
|
||||
$this->assertEquals(E_USER_ERROR, $this->lastErrorNumber);
|
||||
$this->assertEquals('Invalid placeholder: ~placeholder', $this->lastErrorMessage);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -75,20 +75,33 @@ class ComposerIntegrationTest extends UnitTestCase {
|
|||
* core's composer.json.
|
||||
*/
|
||||
public function testAllModulesReplaced() {
|
||||
// Assemble a path to core modules.
|
||||
$module_path = $this->root . '/core/modules';
|
||||
|
||||
// Grab the 'replace' section of the core composer.json file.
|
||||
$json = json_decode(file_get_contents($this->root . '/core/composer.json'));
|
||||
$composer_replace_packages = $json->replace;
|
||||
$composer_replace_packages = (array) $json->replace;
|
||||
|
||||
$folders = scandir($this->root . '/core/modules');
|
||||
// Get a list of all the files in the module path.
|
||||
$folders = scandir($module_path);
|
||||
|
||||
// Make sure we only deal with directories that aren't . or ..
|
||||
$module_names = [];
|
||||
$discard = ['.', '..'];
|
||||
foreach ($folders as $file_name) {
|
||||
if ($file_name !== '.' && $file_name !== '..' && is_dir($file_name)) {
|
||||
if ((!in_array($file_name, $discard)) && is_dir($module_path . '/' . $file_name)) {
|
||||
$module_names[] = $file_name;
|
||||
}
|
||||
}
|
||||
|
||||
// Assert that each core module has a corresponding 'replace' in
|
||||
// composer.json.
|
||||
foreach ($module_names as $module_name) {
|
||||
$this->assertTrue(array_key_exists('drupal/'.$module_name, $composer_replace_packages), 'Found ' . $module_name . ' in replace list of composer.json');
|
||||
$this->assertArrayHasKey(
|
||||
'drupal/' . $module_name,
|
||||
$composer_replace_packages,
|
||||
'Unable to find ' . $module_name . ' in replace list of composer.json'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains
|
||||
* \Drupal\Tests\Core\DependencyInjection\Compiler\ProxyServicesPassTest.
|
||||
* Contains \Drupal\Tests\Core\DependencyInjection\Compiler\ProxyServicesPassTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\DependencyInjection\Compiler;
|
||||
|
|
824
core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php
Normal file
824
core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php
Normal file
|
@ -0,0 +1,824 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Entity\EntityFieldManagerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Entity;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\ContentEntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
|
||||
use Drupal\Core\Entity\EntityFieldManager;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeRepositoryInterface;
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldTypePluginManagerInterface;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\BooleanItem;
|
||||
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
|
||||
use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Drupal\Core\TypedData\TypedDataManagerInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Prophecy\Argument;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Entity\EntityFieldManager
|
||||
* @group Entity
|
||||
*/
|
||||
class EntityFieldManagerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The typed data manager.
|
||||
*
|
||||
* @var \Drupal\Core\TypedData\TypedDataManagerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $typedDataManager;
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The cache backend to use.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $cacheBackend;
|
||||
|
||||
/**
|
||||
* The cache tags invalidator.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $cacheTagsInvalidator;
|
||||
|
||||
/**
|
||||
* The language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The keyvalue factory.
|
||||
*
|
||||
* @var \Drupal\Core\KeyValueStore\KeyValueFactoryInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $keyValueFactory;
|
||||
|
||||
/**
|
||||
* The event dispatcher.
|
||||
*
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The entity type repository.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeRepositoryInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $entityTypeRepository;
|
||||
|
||||
/**
|
||||
* The entity type bundle info.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $entityTypeBundleInfo;
|
||||
|
||||
/**
|
||||
* The entity display repository.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $entityDisplayRepository;
|
||||
|
||||
/**
|
||||
* The entity field manager under test.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityFieldManager
|
||||
*/
|
||||
protected $entityFieldManager;
|
||||
|
||||
/**
|
||||
* The dependency injection container.
|
||||
*
|
||||
* @var \Symfony\Component\DependencyInjection\ContainerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* The entity type definition.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $entityType;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->container = $this->prophesize(ContainerInterface::class);
|
||||
\Drupal::setContainer($this->container->reveal());
|
||||
|
||||
$this->typedDataManager = $this->prophesize(TypedDataManagerInterface::class);
|
||||
$this->typedDataManager->getDefinition('field_item:boolean')->willReturn([
|
||||
'class' => BooleanItem::class,
|
||||
]);
|
||||
$this->container->get('typed_data_manager')->willReturn($this->typedDataManager->reveal());
|
||||
|
||||
$this->moduleHandler = $this->prophesize(ModuleHandlerInterface::class);
|
||||
$this->moduleHandler->alter('entity_base_field_info', Argument::type('array'), Argument::any())->willReturn(NULL);
|
||||
$this->moduleHandler->alter('entity_bundle_field_info', Argument::type('array'), Argument::any(), Argument::type('string'))->willReturn(NULL);
|
||||
|
||||
$this->cacheBackend = $this->prophesize(CacheBackendInterface::class);
|
||||
$this->cacheTagsInvalidator = $this->prophesize(CacheTagsInvalidatorInterface::class);
|
||||
|
||||
$language = new Language(['id' => 'en']);
|
||||
$this->languageManager = $this->prophesize(LanguageManagerInterface::class);
|
||||
$this->languageManager->getCurrentLanguage()->willReturn($language);
|
||||
$this->languageManager->getLanguages()->willReturn(['en' => (object) ['id' => 'en']]);
|
||||
|
||||
$this->keyValueFactory = $this->prophesize(KeyValueFactoryInterface::class);
|
||||
|
||||
$this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
|
||||
$this->entityTypeRepository = $this->prophesize(EntityTypeRepositoryInterface::class);
|
||||
$this->entityTypeBundleInfo = $this->prophesize(EntityTypeBundleInfoInterface::class);
|
||||
$this->entityDisplayRepository = $this->prophesize(EntityDisplayRepositoryInterface::class);
|
||||
|
||||
$this->entityFieldManager = new TestEntityFieldManager($this->entityTypeManager->reveal(), $this->entityTypeBundleInfo->reveal(), $this->entityDisplayRepository->reveal(), $this->typedDataManager->reveal(), $this->languageManager->reveal(), $this->keyValueFactory->reveal(), $this->moduleHandler->reveal(), $this->cacheBackend->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the entity type manager to be tested.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface[]|\Prophecy\Prophecy\ProphecyInterface[] $definitions
|
||||
* (optional) An array of entity type definitions.
|
||||
*/
|
||||
protected function setUpEntityTypeDefinitions($definitions = []) {
|
||||
$class = $this->getMockClass(EntityInterface::class);
|
||||
foreach ($definitions as $key => $entity_type) {
|
||||
// \Drupal\Core\Entity\EntityTypeInterface::getLinkTemplates() is called
|
||||
// by \Drupal\Core\Entity\EntityManager::processDefinition() so it must
|
||||
// always be mocked.
|
||||
$entity_type->getLinkTemplates()->willReturn([]);
|
||||
|
||||
// Give the entity type a legitimate class to return.
|
||||
$entity_type->getClass()->willReturn($class);
|
||||
|
||||
$definitions[$key] = $entity_type->reveal();
|
||||
}
|
||||
|
||||
$this->entityTypeManager->getDefinition(Argument::type('string'))
|
||||
->will(function ($args) use ($definitions) {
|
||||
if (isset($definitions[$args[0]])) {
|
||||
return $definitions[$args[0]];
|
||||
}
|
||||
throw new PluginNotFoundException($args[0]);
|
||||
});
|
||||
$this->entityTypeManager->getDefinition(Argument::type('string'), FALSE)
|
||||
->will(function ($args) use ($definitions) {
|
||||
if (isset($definitions[$args[0]])) {
|
||||
return $definitions[$args[0]];
|
||||
}
|
||||
});
|
||||
$this->entityTypeManager->getDefinitions()->willReturn($definitions);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getBaseFieldDefinitions() method.
|
||||
*
|
||||
* @covers ::getBaseFieldDefinitions
|
||||
* @covers ::buildBaseFieldDefinitions
|
||||
*/
|
||||
public function testGetBaseFieldDefinitions() {
|
||||
$field_definition = $this->setUpEntityWithFieldDefinition();
|
||||
|
||||
$expected = ['id' => $field_definition];
|
||||
$this->assertSame($expected, $this->entityFieldManager->getBaseFieldDefinitions('test_entity_type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getFieldDefinitions() method.
|
||||
*
|
||||
* @covers ::getFieldDefinitions
|
||||
* @covers ::buildBundleFieldDefinitions
|
||||
*/
|
||||
public function testGetFieldDefinitions() {
|
||||
$field_definition = $this->setUpEntityWithFieldDefinition();
|
||||
|
||||
$expected = ['id' => $field_definition];
|
||||
$this->assertSame($expected, $this->entityFieldManager->getFieldDefinitions('test_entity_type', 'test_entity_bundle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getFieldStorageDefinitions() method.
|
||||
*
|
||||
* @covers ::getFieldStorageDefinitions
|
||||
* @covers ::buildFieldStorageDefinitions
|
||||
*/
|
||||
public function testGetFieldStorageDefinitions() {
|
||||
$field_definition = $this->setUpEntityWithFieldDefinition(TRUE);
|
||||
$field_storage_definition = $this->prophesize(FieldStorageDefinitionInterface::class);
|
||||
$field_storage_definition->getName()->willReturn('field_storage');
|
||||
|
||||
$definitions = ['field_storage' => $field_storage_definition->reveal()];
|
||||
|
||||
$this->moduleHandler->getImplementations('entity_base_field_info')->willReturn([]);
|
||||
$this->moduleHandler->getImplementations('entity_field_storage_info')->willReturn(['example_module']);
|
||||
$this->moduleHandler->invoke('example_module', 'entity_field_storage_info', [$this->entityType])->willReturn($definitions);
|
||||
$this->moduleHandler->alter('entity_field_storage_info', $definitions, $this->entityType)->willReturn(NULL);
|
||||
|
||||
$expected = [
|
||||
'id' => $field_definition,
|
||||
'field_storage' => $field_storage_definition->reveal(),
|
||||
];
|
||||
$this->assertSame($expected, $this->entityFieldManager->getFieldStorageDefinitions('test_entity_type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getBaseFieldDefinitions() method with a translatable entity type.
|
||||
*
|
||||
* @covers ::getBaseFieldDefinitions
|
||||
* @covers ::buildBaseFieldDefinitions
|
||||
*
|
||||
* @dataProvider providerTestGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode
|
||||
*/
|
||||
public function testGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode($default_langcode_key) {
|
||||
$this->setUpEntityWithFieldDefinition(FALSE, 'id', ['langcode' => 'langcode', 'default_langcode' => $default_langcode_key]);
|
||||
|
||||
$field_definition = $this->prophesize()->willImplement(FieldDefinitionInterface::class)->willImplement(FieldStorageDefinitionInterface::class);
|
||||
$field_definition->isTranslatable()->willReturn(TRUE);
|
||||
|
||||
$entity_class = EntityManagerTestEntity::class;
|
||||
$entity_class::$baseFieldDefinitions += ['langcode' => $field_definition];
|
||||
|
||||
$this->entityType->isTranslatable()->willReturn(TRUE);
|
||||
|
||||
$definitions = $this->entityFieldManager->getBaseFieldDefinitions('test_entity_type');
|
||||
|
||||
$this->assertTrue(isset($definitions[$default_langcode_key]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode().
|
||||
*
|
||||
* @return array
|
||||
* Test data.
|
||||
*/
|
||||
public function providerTestGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode() {
|
||||
return [
|
||||
['default_langcode'],
|
||||
['custom_default_langcode_key'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getBaseFieldDefinitions() method with a translatable entity type.
|
||||
*
|
||||
* @covers ::getBaseFieldDefinitions
|
||||
* @covers ::buildBaseFieldDefinitions
|
||||
*
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage The Test entity type cannot be translatable as it does not define a translatable "langcode" field.
|
||||
*
|
||||
* @dataProvider providerTestGetBaseFieldDefinitionsTranslatableEntityTypeLangcode
|
||||
*/
|
||||
public function testGetBaseFieldDefinitionsTranslatableEntityTypeLangcode($provide_key, $provide_field, $translatable) {
|
||||
$keys = $provide_key ? ['langcode' => 'langcode'] : [];
|
||||
$this->setUpEntityWithFieldDefinition(FALSE, 'id', $keys);
|
||||
|
||||
if ($provide_field) {
|
||||
$field_definition = $this->prophesize()->willImplement(FieldDefinitionInterface::class)->willImplement(FieldStorageDefinitionInterface::class);
|
||||
$field_definition->isTranslatable()->willReturn($translatable);
|
||||
if (!$translatable) {
|
||||
$field_definition->setTranslatable(!$translatable)->shouldBeCalled();
|
||||
}
|
||||
|
||||
$entity_class = EntityManagerTestEntity::class;
|
||||
$entity_class::$baseFieldDefinitions += ['langcode' => $field_definition->reveal()];
|
||||
}
|
||||
|
||||
$this->entityType->isTranslatable()->willReturn(TRUE);
|
||||
$this->entityType->getLabel()->willReturn('Test');
|
||||
|
||||
$this->entityFieldManager->getBaseFieldDefinitions('test_entity_type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testGetBaseFieldDefinitionsTranslatableEntityTypeLangcode().
|
||||
*
|
||||
* @return array
|
||||
* Test data.
|
||||
*/
|
||||
public function providerTestGetBaseFieldDefinitionsTranslatableEntityTypeLangcode() {
|
||||
return [
|
||||
[FALSE, TRUE, TRUE],
|
||||
[TRUE, FALSE, TRUE],
|
||||
[TRUE, TRUE, FALSE],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getBaseFieldDefinitions() method with caching.
|
||||
*
|
||||
* @covers ::getBaseFieldDefinitions
|
||||
*/
|
||||
public function testGetBaseFieldDefinitionsWithCaching() {
|
||||
$field_definition = $this->setUpEntityWithFieldDefinition();
|
||||
|
||||
$expected = ['id' => $field_definition];
|
||||
|
||||
$this->cacheBackend->get('entity_base_field_definitions:test_entity_type:en')
|
||||
->willReturn(FALSE)
|
||||
->shouldBeCalled();
|
||||
$this->cacheBackend->set('entity_base_field_definitions:test_entity_type:en', Argument::any(), Cache::PERMANENT, ['entity_types', 'entity_field_info'])
|
||||
->will(function ($args) {
|
||||
$data = (object) ['data' => $args[1]];
|
||||
$this->get('entity_base_field_definitions:test_entity_type:en')
|
||||
->willReturn($data)
|
||||
->shouldBeCalled();
|
||||
})
|
||||
->shouldBeCalled();
|
||||
|
||||
$this->assertSame($expected, $this->entityFieldManager->getBaseFieldDefinitions('test_entity_type'));
|
||||
$this->entityFieldManager->testClearEntityFieldInfo();
|
||||
$this->assertSame($expected, $this->entityFieldManager->getBaseFieldDefinitions('test_entity_type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getFieldDefinitions() method with caching.
|
||||
*
|
||||
* @covers ::getFieldDefinitions
|
||||
*/
|
||||
public function testGetFieldDefinitionsWithCaching() {
|
||||
$field_definition = $this->setUpEntityWithFieldDefinition(FALSE, 'id');
|
||||
|
||||
$expected = ['id' => $field_definition];
|
||||
|
||||
$this->cacheBackend->get('entity_base_field_definitions:test_entity_type:en')
|
||||
->willReturn((object) ['data' => $expected])
|
||||
->shouldBeCalledTimes(2);
|
||||
$this->cacheBackend->get('entity_bundle_field_definitions:test_entity_type:test_bundle:en')
|
||||
->willReturn(FALSE)
|
||||
->shouldBeCalledTimes(1);
|
||||
$this->cacheBackend->set('entity_bundle_field_definitions:test_entity_type:test_bundle:en', Argument::any(), Cache::PERMANENT, ['entity_types', 'entity_field_info'])
|
||||
->will(function ($args) {
|
||||
$data = (object) ['data' => $args[1]];
|
||||
$this->get('entity_bundle_field_definitions:test_entity_type:test_bundle:en')
|
||||
->willReturn($data)
|
||||
->shouldBeCalled();
|
||||
})
|
||||
->shouldBeCalled();
|
||||
|
||||
$this->assertSame($expected, $this->entityFieldManager->getFieldDefinitions('test_entity_type', 'test_bundle'));
|
||||
$this->entityFieldManager->testClearEntityFieldInfo();
|
||||
$this->assertSame($expected, $this->entityFieldManager->getFieldDefinitions('test_entity_type', 'test_bundle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getFieldStorageDefinitions() method with caching.
|
||||
*
|
||||
* @covers ::getFieldStorageDefinitions
|
||||
*/
|
||||
public function testGetFieldStorageDefinitionsWithCaching() {
|
||||
$field_definition = $this->setUpEntityWithFieldDefinition(TRUE, 'id');
|
||||
$field_storage_definition = $this->prophesize(FieldStorageDefinitionInterface::class);
|
||||
$field_storage_definition->getName()->willReturn('field_storage');
|
||||
|
||||
$definitions = ['field_storage' => $field_storage_definition->reveal()];
|
||||
|
||||
$this->moduleHandler->getImplementations('entity_field_storage_info')->willReturn(['example_module']);
|
||||
$this->moduleHandler->invoke('example_module', 'entity_field_storage_info', [$this->entityType])->willReturn($definitions);
|
||||
$this->moduleHandler->alter('entity_field_storage_info', $definitions, $this->entityType)->willReturn(NULL);
|
||||
|
||||
$expected = [
|
||||
'id' => $field_definition,
|
||||
'field_storage' => $field_storage_definition->reveal(),
|
||||
];
|
||||
|
||||
$this->cacheBackend->get('entity_base_field_definitions:test_entity_type:en')
|
||||
->willReturn((object) ['data' => ['id' => $expected['id']]])
|
||||
->shouldBeCalledTimes(2);
|
||||
$this->cacheBackend->get('entity_field_storage_definitions:test_entity_type:en')->willReturn(FALSE);
|
||||
|
||||
$this->cacheBackend->set('entity_field_storage_definitions:test_entity_type:en', Argument::any(), Cache::PERMANENT, ['entity_types', 'entity_field_info'])
|
||||
->will(function () use ($expected) {
|
||||
$this->get('entity_field_storage_definitions:test_entity_type:en')
|
||||
->willReturn((object) ['data' => $expected])
|
||||
->shouldBeCalled();
|
||||
})
|
||||
->shouldBeCalled();
|
||||
|
||||
|
||||
$this->assertSame($expected, $this->entityFieldManager->getFieldStorageDefinitions('test_entity_type'));
|
||||
$this->entityFieldManager->testClearEntityFieldInfo();
|
||||
$this->assertSame($expected, $this->entityFieldManager->getFieldStorageDefinitions('test_entity_type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getBaseFieldDefinitions() method with an invalid definition.
|
||||
*
|
||||
* @covers ::getBaseFieldDefinitions
|
||||
* @covers ::buildBaseFieldDefinitions
|
||||
*
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testGetBaseFieldDefinitionsInvalidDefinition() {
|
||||
$this->setUpEntityWithFieldDefinition(FALSE, 'langcode', ['langcode' => 'langcode']);
|
||||
|
||||
$this->entityType->isTranslatable()->willReturn(TRUE);
|
||||
$this->entityType->getLabel()->willReturn('the_label');
|
||||
|
||||
$this->entityFieldManager->getBaseFieldDefinitions('test_entity_type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that getFieldDefinitions() method sets the 'provider' definition key.
|
||||
*
|
||||
* @covers ::getFieldDefinitions
|
||||
* @covers ::buildBundleFieldDefinitions
|
||||
*/
|
||||
public function testGetFieldDefinitionsProvider() {
|
||||
$this->setUpEntityWithFieldDefinition(TRUE);
|
||||
|
||||
$module = 'entity_manager_test_module';
|
||||
|
||||
// @todo Mock FieldDefinitionInterface once it exposes a proper provider
|
||||
// setter. See https://www.drupal.org/node/2225961.
|
||||
$field_definition = $this->prophesize(BaseFieldDefinition::class);
|
||||
|
||||
// We expect two calls as the field definition will be returned from both
|
||||
// base and bundle entity field info hook implementations.
|
||||
$field_definition->getProvider()->shouldBeCalled();
|
||||
$field_definition->setProvider($module)->shouldBeCalledTimes(2);
|
||||
$field_definition->setName(0)->shouldBeCalledTimes(2);
|
||||
$field_definition->setTargetEntityTypeId('test_entity_type')->shouldBeCalled();
|
||||
$field_definition->setTargetBundle(NULL)->shouldBeCalled();
|
||||
$field_definition->setTargetBundle('test_bundle')->shouldBeCalled();
|
||||
|
||||
$this->moduleHandler->getImplementations(Argument::type('string'))->willReturn([$module]);
|
||||
$this->moduleHandler->invoke($module, 'entity_base_field_info', [$this->entityType])->willReturn([$field_definition->reveal()]);
|
||||
$this->moduleHandler->invoke($module, 'entity_bundle_field_info', Argument::type('array'))->willReturn([$field_definition->reveal()]);
|
||||
|
||||
$this->entityFieldManager->getFieldDefinitions('test_entity_type', 'test_bundle');
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares an entity that defines a field definition.
|
||||
*
|
||||
* @param bool $custom_invoke_all
|
||||
* (optional) Whether the test will set up its own
|
||||
* ModuleHandlerInterface::invokeAll() implementation. Defaults to FALSE.
|
||||
* @param string $field_definition_id
|
||||
* (optional) The ID to use for the field definition. Defaults to 'id'.
|
||||
* @param array $entity_keys
|
||||
* (optional) An array of entity keys for the mocked entity type. Defaults
|
||||
* to an empty array.
|
||||
*
|
||||
* @return \Drupal\Core\Field\BaseFieldDefinition|\Prophecy\Prophecy\ProphecyInterface
|
||||
* A field definition object.
|
||||
*/
|
||||
protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $field_definition_id = 'id', $entity_keys = []) {
|
||||
$field_type_manager = $this->prophesize(FieldTypePluginManagerInterface::class);
|
||||
$field_type_manager->getDefaultStorageSettings('boolean')->willReturn([]);
|
||||
$field_type_manager->getDefaultFieldSettings('boolean')->willReturn([]);
|
||||
$this->container->get('plugin.manager.field.field_type')->willReturn($field_type_manager->reveal());
|
||||
|
||||
$string_translation = $this->prophesize(TranslationInterface::class);
|
||||
$this->container->get('string_translation')->willReturn($string_translation->reveal());
|
||||
|
||||
$entity_class = EntityManagerTestEntity::class;
|
||||
|
||||
$field_definition = $this->prophesize()->willImplement(FieldDefinitionInterface::class)->willImplement(FieldStorageDefinitionInterface::class);
|
||||
$entity_class::$baseFieldDefinitions = [
|
||||
$field_definition_id => $field_definition->reveal(),
|
||||
];
|
||||
$entity_class::$bundleFieldDefinitions = [];
|
||||
|
||||
if (!$custom_invoke_all) {
|
||||
$this->moduleHandler->getImplementations(Argument::cetera())->willReturn([]);
|
||||
}
|
||||
|
||||
// Mock the base field definition override.
|
||||
$override_entity_type = $this->prophesize(EntityTypeInterface::class);
|
||||
|
||||
$this->entityType = $this->prophesize(EntityTypeInterface::class);
|
||||
$this->setUpEntityTypeDefinitions(['test_entity_type' => $this->entityType, 'base_field_override' => $override_entity_type]);
|
||||
|
||||
$storage = $this->prophesize(ConfigEntityStorageInterface::class);
|
||||
$storage->loadMultiple(Argument::type('array'))->willReturn([]);
|
||||
$this->entityTypeManager->getStorage('base_field_override')->willReturn($storage->reveal());
|
||||
|
||||
$this->entityType->getClass()->willReturn($entity_class);
|
||||
$this->entityType->getKeys()->willReturn($entity_keys + ['default_langcode' => 'default_langcode']);
|
||||
$this->entityType->isSubclassOf(FieldableEntityInterface::class)->willReturn(TRUE);
|
||||
$this->entityType->isTranslatable()->willReturn(FALSE);
|
||||
$this->entityType->getProvider()->willReturn('the_provider');
|
||||
$this->entityType->id()->willReturn('the_entity_id');
|
||||
|
||||
return $field_definition->reveal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the clearCachedFieldDefinitions() method.
|
||||
*
|
||||
* @covers ::clearCachedFieldDefinitions
|
||||
*/
|
||||
public function testClearCachedFieldDefinitions() {
|
||||
$this->setUpEntityTypeDefinitions();
|
||||
|
||||
$this->cacheTagsInvalidator->invalidateTags(['entity_field_info'])->shouldBeCalled();
|
||||
$this->container->get('cache_tags.invalidator')->willReturn($this->cacheTagsInvalidator->reveal())->shouldBeCalled();
|
||||
|
||||
$this->typedDataManager->clearCachedDefinitions()->shouldBeCalled();
|
||||
|
||||
$this->entityFieldManager->clearCachedFieldDefinitions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getExtraFields
|
||||
*/
|
||||
function testGetExtraFields() {
|
||||
$this->setUpEntityTypeDefinitions();
|
||||
|
||||
$entity_type_id = $this->randomMachineName();
|
||||
$bundle = $this->randomMachineName();
|
||||
$language_code = 'en';
|
||||
$hook_bundle_extra_fields = [
|
||||
$entity_type_id => [
|
||||
$bundle => [
|
||||
'form' => [
|
||||
'foo_extra_field' => [
|
||||
'label' => 'Foo',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
$processed_hook_bundle_extra_fields = $hook_bundle_extra_fields;
|
||||
$processed_hook_bundle_extra_fields[$entity_type_id][$bundle] += [
|
||||
'display' => [],
|
||||
];
|
||||
$cache_id = 'entity_bundle_extra_fields:' . $entity_type_id . ':' . $bundle . ':' . $language_code;
|
||||
|
||||
$language = new Language(['id' => $language_code]);
|
||||
$this->languageManager->getCurrentLanguage()
|
||||
->willReturn($language)
|
||||
->shouldBeCalledTimes(1);
|
||||
|
||||
$this->cacheBackend->get($cache_id)->shouldBeCalled();
|
||||
|
||||
$this->moduleHandler->invokeAll('entity_extra_field_info')->willReturn($hook_bundle_extra_fields);
|
||||
$this->moduleHandler->alter('entity_extra_field_info', $hook_bundle_extra_fields)->shouldBeCalled();
|
||||
|
||||
$this->cacheBackend->set($cache_id, $processed_hook_bundle_extra_fields[$entity_type_id][$bundle], Cache::PERMANENT, ['entity_field_info'])->shouldBeCalled();
|
||||
|
||||
$this->assertSame($processed_hook_bundle_extra_fields[$entity_type_id][$bundle], $this->entityFieldManager->getExtraFields($entity_type_id, $bundle));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFieldMap
|
||||
*/
|
||||
public function testGetFieldMap() {
|
||||
$this->entityTypeBundleInfo->getBundleInfo('test_entity_type')->willReturn([])->shouldBeCalled();
|
||||
|
||||
// Set up a content entity type.
|
||||
$entity_type = $this->prophesize(ContentEntityTypeInterface::class);
|
||||
$entity_class = EntityManagerTestEntity::class;
|
||||
|
||||
// Define an ID field definition as a base field.
|
||||
$id_definition = $this->prophesize(FieldDefinitionInterface::class);
|
||||
$id_definition->getType()->willReturn('integer');
|
||||
$base_field_definitions = [
|
||||
'id' => $id_definition->reveal(),
|
||||
];
|
||||
$entity_class::$baseFieldDefinitions = $base_field_definitions;
|
||||
|
||||
// Set up the stored bundle field map.
|
||||
$key_value_store = $this->prophesize(KeyValueStoreInterface::class);
|
||||
$this->keyValueFactory->get('entity.definitions.bundle_field_map')->willReturn($key_value_store->reveal());
|
||||
$key_value_store->getAll()->willReturn([
|
||||
'test_entity_type' => [
|
||||
'by_bundle' => [
|
||||
'type' => 'string',
|
||||
'bundles' => ['second_bundle' => 'second_bundle'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
// Set up a non-content entity type.
|
||||
$non_content_entity_type = $this->prophesize(EntityTypeInterface::class);
|
||||
|
||||
// Mock the base field definition override.
|
||||
$override_entity_type = $this->prophesize(EntityTypeInterface::class);
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'test_entity_type' => $entity_type,
|
||||
'non_fieldable' => $non_content_entity_type,
|
||||
'base_field_override' => $override_entity_type,
|
||||
]);
|
||||
|
||||
$entity_type->getClass()->willReturn($entity_class);
|
||||
$entity_type->getKeys()->willReturn(['default_langcode' => 'default_langcode']);
|
||||
$entity_type->isSubclassOf(FieldableEntityInterface::class)->willReturn(TRUE);
|
||||
$entity_type->isTranslatable()->shouldBeCalled();
|
||||
$entity_type->getProvider()->shouldBeCalled();
|
||||
|
||||
$non_content_entity_type->isSubclassOf(FieldableEntityInterface::class)->willReturn(FALSE);
|
||||
|
||||
$override_entity_type->isSubclassOf(FieldableEntityInterface::class)->willReturn(FALSE);
|
||||
|
||||
// Set up the entity type bundle info to return two bundles for the
|
||||
// fieldable entity type.
|
||||
$this->entityTypeBundleInfo->getBundleInfo('test_entity_type')->willReturn([
|
||||
'first_bundle' => 'first_bundle',
|
||||
'second_bundle' => 'second_bundle',
|
||||
])->shouldBeCalled();
|
||||
$this->moduleHandler->getImplementations('entity_base_field_info')->willReturn([]);
|
||||
|
||||
$expected = [
|
||||
'test_entity_type' => [
|
||||
'id' => [
|
||||
'type' => 'integer',
|
||||
'bundles' => ['first_bundle' => 'first_bundle', 'second_bundle' => 'second_bundle'],
|
||||
],
|
||||
'by_bundle' => [
|
||||
'type' => 'string',
|
||||
'bundles' => ['second_bundle' => 'second_bundle'],
|
||||
],
|
||||
]
|
||||
];
|
||||
$this->assertEquals($expected, $this->entityFieldManager->getFieldMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFieldMap
|
||||
*/
|
||||
public function testGetFieldMapFromCache() {
|
||||
$expected = [
|
||||
'test_entity_type' => [
|
||||
'id' => [
|
||||
'type' => 'integer',
|
||||
'bundles' => ['first_bundle' => 'first_bundle', 'second_bundle' => 'second_bundle'],
|
||||
],
|
||||
'by_bundle' => [
|
||||
'type' => 'string',
|
||||
'bundles' => ['second_bundle' => 'second_bundle'],
|
||||
],
|
||||
]
|
||||
];
|
||||
$this->setUpEntityTypeDefinitions();
|
||||
$this->cacheBackend->get('entity_field_map')->willReturn((object) ['data' => $expected]);
|
||||
|
||||
// Call the field map twice to make sure the static cache works.
|
||||
$this->assertEquals($expected, $this->entityFieldManager->getFieldMap());
|
||||
$this->assertEquals($expected, $this->entityFieldManager->getFieldMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFieldMapByFieldType
|
||||
*/
|
||||
public function testGetFieldMapByFieldType() {
|
||||
// Set up a content entity type.
|
||||
$entity_type = $this->prophesize(ContentEntityTypeInterface::class);
|
||||
$entity_class = EntityManagerTestEntity::class;
|
||||
|
||||
// Set up the entity type bundle info to return two bundles for the
|
||||
// fieldable entity type.
|
||||
$this->entityTypeBundleInfo->getBundleInfo('test_entity_type')->willReturn([
|
||||
'first_bundle' => 'first_bundle',
|
||||
'second_bundle' => 'second_bundle',
|
||||
])->shouldBeCalled();
|
||||
$this->moduleHandler->getImplementations('entity_base_field_info')->willReturn([])->shouldBeCalled();
|
||||
|
||||
// Define an ID field definition as a base field.
|
||||
$id_definition = $this->prophesize(FieldDefinitionInterface::class);
|
||||
$id_definition->getType()->willReturn('integer')->shouldBeCalled();
|
||||
$base_field_definitions = [
|
||||
'id' => $id_definition->reveal(),
|
||||
];
|
||||
$entity_class::$baseFieldDefinitions = $base_field_definitions;
|
||||
|
||||
// Set up the stored bundle field map.
|
||||
$key_value_store = $this->prophesize(KeyValueStoreInterface::class);
|
||||
$this->keyValueFactory->get('entity.definitions.bundle_field_map')->willReturn($key_value_store->reveal())->shouldBeCalled();
|
||||
$key_value_store->getAll()->willReturn([
|
||||
'test_entity_type' => [
|
||||
'by_bundle' => [
|
||||
'type' => 'string',
|
||||
'bundles' => ['second_bundle' => 'second_bundle'],
|
||||
],
|
||||
],
|
||||
])->shouldBeCalled();
|
||||
|
||||
// Mock the base field definition override.
|
||||
$override_entity_type = $this->prophesize(EntityTypeInterface::class);
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'test_entity_type' => $entity_type,
|
||||
'base_field_override' => $override_entity_type,
|
||||
]);
|
||||
|
||||
$entity_type->getClass()->willReturn($entity_class)->shouldBeCalled();
|
||||
$entity_type->getKeys()->willReturn(['default_langcode' => 'default_langcode'])->shouldBeCalled();
|
||||
$entity_type->isSubclassOf(FieldableEntityInterface::class)->willReturn(TRUE)->shouldBeCalled();
|
||||
$entity_type->isTranslatable()->shouldBeCalled();
|
||||
$entity_type->getProvider()->shouldBeCalled();
|
||||
|
||||
$override_entity_type->isSubclassOf(FieldableEntityInterface::class)->willReturn(FALSE)->shouldBeCalled();
|
||||
|
||||
$integerFields = $this->entityFieldManager->getFieldMapByFieldType('integer');
|
||||
$this->assertCount(1, $integerFields['test_entity_type']);
|
||||
$this->assertArrayNotHasKey('non_fieldable', $integerFields);
|
||||
$this->assertArrayHasKey('id', $integerFields['test_entity_type']);
|
||||
$this->assertArrayNotHasKey('by_bundle', $integerFields['test_entity_type']);
|
||||
|
||||
$stringFields = $this->entityFieldManager->getFieldMapByFieldType('string');
|
||||
$this->assertCount(1, $stringFields['test_entity_type']);
|
||||
$this->assertArrayNotHasKey('non_fieldable', $stringFields);
|
||||
$this->assertArrayHasKey('by_bundle', $stringFields['test_entity_type']);
|
||||
$this->assertArrayNotHasKey('id', $stringFields['test_entity_type']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestEntityFieldManager extends EntityFieldManager {
|
||||
|
||||
/**
|
||||
* Allows the static caches to be cleared.
|
||||
*/
|
||||
public function testClearEntityFieldInfo() {
|
||||
$this->baseFieldDefinitions = [];
|
||||
$this->fieldDefinitions = [];
|
||||
$this->fieldStorageDefinitions = [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a content entity with dummy static method implementations.
|
||||
*/
|
||||
abstract class EntityManagerTestEntity implements \Iterator, ContentEntityInterface {
|
||||
|
||||
/**
|
||||
* The base field definitions.
|
||||
*
|
||||
* @var \Drupal\Core\Field\FieldDefinitionInterface[]
|
||||
*/
|
||||
public static $baseFieldDefinitions = [];
|
||||
|
||||
/**
|
||||
* The bundle field definitions.
|
||||
*
|
||||
* @var array[]
|
||||
* Keys are entity type IDs, values are arrays of which the keys are bundle
|
||||
* names and the values are field definitions.
|
||||
*/
|
||||
public static $bundleFieldDefinitions = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
return static::$baseFieldDefinitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
|
||||
return isset(static::$bundleFieldDefinitions[$entity_type->id()][$bundle]) ? static::$bundleFieldDefinitions[$entity_type->id()][$bundle] : [];
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
94
core/tests/Drupal/Tests/Core/Entity/EntityRepositoryTest.php
Normal file
94
core/tests/Drupal/Tests/Core/Entity/EntityRepositoryTest.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Entity\EntityRepositoryTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\EntityRepository;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Entity\EntityManager
|
||||
* @group Entity
|
||||
*/
|
||||
class EntityRepositoryTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The entity repository under test.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityRepository
|
||||
*/
|
||||
protected $entityRepository;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
|
||||
$this->languageManager = $this->prophesize(LanguageManagerInterface::class);
|
||||
|
||||
$this->entityRepository = new EntityRepository($this->entityTypeManager->reveal(), $this->languageManager->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getTranslationFromContext() method.
|
||||
*
|
||||
* @covers ::getTranslationFromContext
|
||||
*/
|
||||
public function testGetTranslationFromContext() {
|
||||
$language = new Language(['id' => 'en']);
|
||||
$this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
|
||||
->willReturn($language)
|
||||
->shouldBeCalledTimes(1);
|
||||
$this->languageManager->getFallbackCandidates(Argument::type('array'))
|
||||
->will(function ($args) {
|
||||
$context = $args[0];
|
||||
$candidates = array();
|
||||
if (!empty($context['langcode'])) {
|
||||
$candidates[$context['langcode']] = $context['langcode'];
|
||||
}
|
||||
return $candidates;
|
||||
})
|
||||
->shouldBeCalledTimes(1);
|
||||
|
||||
$translated_entity = $this->prophesize(ContentEntityInterface::class);
|
||||
|
||||
$entity = $this->prophesize(ContentEntityInterface::class);
|
||||
$entity->getUntranslated()->willReturn($entity);
|
||||
$entity->language()->willReturn($language);
|
||||
$entity->hasTranslation(LanguageInterface::LANGCODE_DEFAULT)->willReturn(FALSE);
|
||||
$entity->hasTranslation('custom_langcode')->willReturn(TRUE);
|
||||
$entity->getTranslation('custom_langcode')->willReturn($translated_entity->reveal());
|
||||
$entity->getTranslationLanguages()->willReturn([new Language(['id' => 'en']), new Language(['id' => 'custom_langcode'])]);
|
||||
$entity->addCacheContexts(['languages:language_content'])->shouldBeCalled();
|
||||
|
||||
$this->assertSame($entity->reveal(), $this->entityRepository->getTranslationFromContext($entity->reveal()));
|
||||
$this->assertSame($translated_entity->reveal(), $this->entityRepository->getTranslationFromContext($entity->reveal(), 'custom_langcode'));
|
||||
}
|
||||
|
||||
}
|
274
core/tests/Drupal/Tests/Core/Entity/EntityTypeBundleInfoTest.php
Normal file
274
core/tests/Drupal/Tests/Core/Entity/EntityTypeBundleInfoTest.php
Normal file
|
@ -0,0 +1,274 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Entity\EntityTypeBundleInfoTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Entity;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfo;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\TypedData\TypedDataManagerInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Prophecy\Argument;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Entity\EntityTypeBundleInfo
|
||||
* @group Entity
|
||||
*/
|
||||
class EntityTypeBundleInfoTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The cache backend to use.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $cacheBackend;
|
||||
|
||||
/**
|
||||
* The cache tags invalidator.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $cacheTagsInvalidator;
|
||||
|
||||
/**
|
||||
* The typed data manager.
|
||||
*
|
||||
* @var \Drupal\Core\TypedData\TypedDataManagerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $typedDataManager;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The entity type bundle info under test.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeBundleInfo
|
||||
*/
|
||||
protected $entityTypeBundleInfo;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->moduleHandler = $this->prophesize(ModuleHandlerInterface::class);
|
||||
$this->moduleHandler->getImplementations('entity_type_build')->willReturn([]);
|
||||
$this->moduleHandler->alter('entity_type', Argument::type('array'))->willReturn(NULL);
|
||||
|
||||
$this->cacheBackend = $this->prophesize(CacheBackendInterface::class);
|
||||
|
||||
$this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
|
||||
|
||||
$this->cacheTagsInvalidator = $this->prophesize(CacheTagsInvalidatorInterface::class);
|
||||
|
||||
$language = new Language(['id' => 'en']);
|
||||
$this->languageManager = $this->prophesize(LanguageManagerInterface::class);
|
||||
$this->languageManager->getCurrentLanguage()->willReturn($language);
|
||||
$this->languageManager->getLanguages()->willReturn(['en' => (object) ['id' => 'en']]);
|
||||
|
||||
$this->typedDataManager = $this->prophesize(TypedDataManagerInterface::class);
|
||||
|
||||
$this->cacheBackend = $this->prophesize(CacheBackendInterface::class);
|
||||
|
||||
$container = $this->prophesize(ContainerInterface::class);
|
||||
$container->get('cache_tags.invalidator')->willReturn($this->cacheTagsInvalidator->reveal());
|
||||
//$container->get('typed_data_manager')->willReturn($this->typedDataManager->reveal());
|
||||
\Drupal::setContainer($container->reveal());
|
||||
|
||||
$this->entityTypeBundleInfo = new EntityTypeBundleInfo($this->entityTypeManager->reveal(), $this->languageManager->reveal(), $this->moduleHandler->reveal(), $this->typedDataManager->reveal(), $this->cacheBackend->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the entity type manager to be tested.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface[]|\Prophecy\Prophecy\ProphecyInterface[] $definitions
|
||||
* (optional) An array of entity type definitions.
|
||||
*/
|
||||
protected function setUpEntityTypeDefinitions($definitions = []) {
|
||||
$class = $this->getMockClass(EntityInterface::class);
|
||||
foreach ($definitions as $key => $entity_type) {
|
||||
// \Drupal\Core\Entity\EntityTypeInterface::getLinkTemplates() is called
|
||||
// by \Drupal\Core\Entity\EntityManager::processDefinition() so it must
|
||||
// always be mocked.
|
||||
$entity_type->getLinkTemplates()->willReturn([]);
|
||||
|
||||
// Give the entity type a legitimate class to return.
|
||||
$entity_type->getClass()->willReturn($class);
|
||||
|
||||
$definitions[$key] = $entity_type->reveal();
|
||||
}
|
||||
|
||||
$this->entityTypeManager->getDefinition(Argument::cetera())
|
||||
->will(function ($args) use ($definitions) {
|
||||
$entity_type_id = $args[0];
|
||||
$exception_on_invalid = $args[1];
|
||||
if (isset($definitions[$entity_type_id])) {
|
||||
return $definitions[$entity_type_id];
|
||||
}
|
||||
elseif (!$exception_on_invalid) {
|
||||
return NULL;
|
||||
}
|
||||
else throw new PluginNotFoundException($entity_type_id);
|
||||
});
|
||||
$this->entityTypeManager->getDefinitions()->willReturn($definitions);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the clearCachedBundles() method.
|
||||
*
|
||||
* @covers ::clearCachedBundles
|
||||
*/
|
||||
public function testClearCachedBundles() {
|
||||
$this->setUpEntityTypeDefinitions();
|
||||
|
||||
$this->typedDataManager->clearCachedDefinitions()->shouldBeCalled();
|
||||
|
||||
$this->cacheTagsInvalidator->invalidateTags(['entity_bundles'])->shouldBeCalled();
|
||||
|
||||
$this->entityTypeBundleInfo->clearCachedBundles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getBundleInfo() method.
|
||||
*
|
||||
* @covers ::getBundleInfo
|
||||
*
|
||||
* @dataProvider providerTestGetBundleInfo
|
||||
*/
|
||||
public function testGetBundleInfo($entity_type_id, $expected) {
|
||||
$this->moduleHandler->invokeAll('entity_bundle_info')->willReturn([]);
|
||||
$this->moduleHandler->alter('entity_bundle_info', Argument::type('array'))->willReturn(NULL);
|
||||
|
||||
$apple = $this->prophesize(EntityTypeInterface::class);
|
||||
$apple->getLabel()->willReturn('Apple');
|
||||
$apple->getBundleOf()->willReturn(NULL);
|
||||
|
||||
$banana = $this->prophesize(EntityTypeInterface::class);
|
||||
$banana->getLabel()->willReturn('Banana');
|
||||
$banana->getBundleOf()->willReturn(NULL);
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'apple' => $apple,
|
||||
'banana' => $banana,
|
||||
]);
|
||||
|
||||
$bundle_info = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id);
|
||||
$this->assertSame($expected, $bundle_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testGetBundleInfo().
|
||||
*
|
||||
* @return array
|
||||
* Test data.
|
||||
*/
|
||||
public function providerTestGetBundleInfo() {
|
||||
return [
|
||||
['apple', [
|
||||
'apple' => [
|
||||
'label' => 'Apple',
|
||||
],
|
||||
]],
|
||||
['banana', [
|
||||
'banana' => [
|
||||
'label' => 'Banana',
|
||||
],
|
||||
]],
|
||||
['pear', []],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAllBundleInfo() method.
|
||||
*
|
||||
* @covers ::getAllBundleInfo
|
||||
*/
|
||||
public function testGetAllBundleInfo() {
|
||||
$this->moduleHandler->invokeAll('entity_bundle_info')->willReturn([]);
|
||||
$this->moduleHandler->alter('entity_bundle_info', Argument::type('array'))->willReturn(NULL);
|
||||
|
||||
$apple = $this->prophesize(EntityTypeInterface::class);
|
||||
$apple->getLabel()->willReturn('Apple');
|
||||
$apple->getBundleOf()->willReturn(NULL);
|
||||
|
||||
$banana = $this->prophesize(EntityTypeInterface::class);
|
||||
$banana->getLabel()->willReturn('Banana');
|
||||
$banana->getBundleOf()->willReturn(NULL);
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'apple' => $apple,
|
||||
'banana' => $banana,
|
||||
]);
|
||||
|
||||
$this->cacheBackend->get('entity_bundle_info:en')->willReturn(FALSE);
|
||||
$this->cacheBackend->set('entity_bundle_info:en', Argument::any(), Cache::PERMANENT, ['entity_types', 'entity_bundles'])
|
||||
->will(function () {
|
||||
$this->get('entity_bundle_info:en')
|
||||
->willReturn((object) ['data' => 'cached data'])
|
||||
->shouldBeCalled();
|
||||
})
|
||||
->shouldBeCalled();
|
||||
|
||||
$this->cacheTagsInvalidator->invalidateTags(['entity_bundles'])->shouldBeCalled();
|
||||
|
||||
$this->typedDataManager->clearCachedDefinitions()->shouldBeCalled();
|
||||
|
||||
$expected = [
|
||||
'apple' => [
|
||||
'apple' => [
|
||||
'label' => 'Apple',
|
||||
],
|
||||
],
|
||||
'banana' => [
|
||||
'banana' => [
|
||||
'label' => 'Banana',
|
||||
],
|
||||
],
|
||||
];
|
||||
$bundle_info = $this->entityTypeBundleInfo->getAllBundleInfo();
|
||||
$this->assertSame($expected, $bundle_info);
|
||||
|
||||
$bundle_info = $this->entityTypeBundleInfo->getAllBundleInfo();
|
||||
$this->assertSame($expected, $bundle_info);
|
||||
|
||||
$this->entityTypeBundleInfo->clearCachedBundles();
|
||||
|
||||
$bundle_info = $this->entityTypeBundleInfo->getAllBundleInfo();
|
||||
$this->assertSame('cached data', $bundle_info);
|
||||
}
|
||||
|
||||
}
|
510
core/tests/Drupal/Tests/Core/Entity/EntityTypeManagerTest.php
Normal file
510
core/tests/Drupal/Tests/Core/Entity/EntityTypeManagerTest.php
Normal file
|
@ -0,0 +1,510 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Entity\EntityTypeManagerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Entity;
|
||||
|
||||
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
|
||||
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\EntityHandlerBase;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManager;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Prophecy\Argument;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Entity\EntityTypeManager
|
||||
* @group Entity
|
||||
*/
|
||||
class EntityTypeManagerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The entity type manager under test.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManager
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The translation manager.
|
||||
*
|
||||
* @var \Drupal\Core\StringTranslation\TranslationInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $translationManager;
|
||||
|
||||
/**
|
||||
* The plugin discovery.
|
||||
*
|
||||
* @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $discovery;
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The cache backend.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $cacheBackend;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->moduleHandler = $this->prophesize(ModuleHandlerInterface::class);
|
||||
$this->moduleHandler->getImplementations('entity_type_build')->willReturn([]);
|
||||
$this->moduleHandler->alter('entity_type', Argument::type('array'))->willReturn(NULL);
|
||||
|
||||
$this->cacheBackend = $this->prophesize(CacheBackendInterface::class);
|
||||
$this->translationManager = $this->prophesize(TranslationInterface::class);
|
||||
|
||||
$this->entityTypeManager = new TestEntityTypeManager(new \ArrayObject(), $this->moduleHandler->reveal(), $this->cacheBackend->reveal(), $this->translationManager->reveal(), $this->getClassResolverStub());
|
||||
$this->discovery = $this->prophesize(DiscoveryInterface::class);
|
||||
$this->entityTypeManager->setDiscovery($this->discovery->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the entity type manager to be tested.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface[]|\Prophecy\Prophecy\ProphecyInterface[] $definitions
|
||||
* (optional) An array of entity type definitions.
|
||||
*/
|
||||
protected function setUpEntityTypeDefinitions($definitions = []) {
|
||||
$class = $this->getMockClass(EntityInterface::class);
|
||||
foreach ($definitions as $key => $entity_type) {
|
||||
// \Drupal\Core\Entity\EntityTypeInterface::getLinkTemplates() is called
|
||||
// by \Drupal\Core\Entity\EntityManager::processDefinition() so it must
|
||||
// always be mocked.
|
||||
$entity_type->getLinkTemplates()->willReturn([]);
|
||||
|
||||
// Give the entity type a legitimate class to return.
|
||||
$entity_type->getClass()->willReturn($class);
|
||||
|
||||
$definitions[$key] = $entity_type->reveal();
|
||||
}
|
||||
|
||||
$this->discovery->getDefinition(Argument::cetera())
|
||||
->will(function ($args) use ($definitions) {
|
||||
$entity_type_id = $args[0];
|
||||
$exception_on_invalid = $args[1];
|
||||
if (isset($definitions[$entity_type_id])) {
|
||||
return $definitions[$entity_type_id];
|
||||
}
|
||||
elseif (!$exception_on_invalid) {
|
||||
return NULL;
|
||||
}
|
||||
else throw new PluginNotFoundException($entity_type_id);
|
||||
});
|
||||
$this->discovery->getDefinitions()->willReturn($definitions);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the hasHandler() method.
|
||||
*
|
||||
* @covers ::hasHandler
|
||||
*
|
||||
* @dataProvider providerTestHasHandler
|
||||
*/
|
||||
public function testHasHandler($entity_type_id, $expected) {
|
||||
$apple = $this->prophesize(EntityTypeInterface::class);
|
||||
$apple->hasHandlerClass('storage')->willReturn(TRUE);
|
||||
|
||||
$banana = $this->prophesize(EntityTypeInterface::class);
|
||||
$banana->hasHandlerClass('storage')->willReturn(FALSE);
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'apple' => $apple,
|
||||
'banana' => $banana,
|
||||
]);
|
||||
|
||||
$entity_type = $this->entityTypeManager->hasHandler($entity_type_id, 'storage');
|
||||
$this->assertSame($expected, $entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testHasHandler().
|
||||
*
|
||||
* @return array
|
||||
* Test data.
|
||||
*/
|
||||
public function providerTestHasHandler() {
|
||||
return [
|
||||
['apple', TRUE],
|
||||
['banana', FALSE],
|
||||
['pear', FALSE],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getStorage() method.
|
||||
*
|
||||
* @covers ::getStorage
|
||||
*/
|
||||
public function testGetStorage() {
|
||||
$class = $this->getTestHandlerClass();
|
||||
$entity = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity->getHandlerClass('storage')->willReturn($class);
|
||||
$this->setUpEntityTypeDefinitions(['test_entity_type' => $entity]);
|
||||
|
||||
$this->assertInstanceOf($class, $this->entityTypeManager->getStorage('test_entity_type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getListBuilder() method.
|
||||
*
|
||||
* @covers ::getListBuilder
|
||||
*/
|
||||
public function testGetListBuilder() {
|
||||
$class = $this->getTestHandlerClass();
|
||||
$entity = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity->getHandlerClass('list_builder')->willReturn($class);
|
||||
$this->setUpEntityTypeDefinitions(['test_entity_type' => $entity]);
|
||||
|
||||
$this->assertInstanceOf($class, $this->entityTypeManager->getListBuilder('test_entity_type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getViewBuilder() method.
|
||||
*
|
||||
* @covers ::getViewBuilder
|
||||
*/
|
||||
public function testGetViewBuilder() {
|
||||
$class = $this->getTestHandlerClass();
|
||||
$entity = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity->getHandlerClass('view_builder')->willReturn($class);
|
||||
$this->setUpEntityTypeDefinitions(['test_entity_type' => $entity]);
|
||||
|
||||
$this->assertInstanceOf($class, $this->entityTypeManager->getViewBuilder('test_entity_type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAccessControlHandler() method.
|
||||
*
|
||||
* @covers ::getAccessControlHandler
|
||||
*/
|
||||
public function testGetAccessControlHandler() {
|
||||
$class = $this->getTestHandlerClass();
|
||||
$entity = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity->getHandlerClass('access')->willReturn($class);
|
||||
$this->setUpEntityTypeDefinitions(['test_entity_type' => $entity]);
|
||||
|
||||
$this->assertInstanceOf($class, $this->entityTypeManager->getAccessControlHandler('test_entity_type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getFormObject() method.
|
||||
*
|
||||
* @covers ::getFormObject
|
||||
*/
|
||||
public function testGetFormObject() {
|
||||
$entity_manager = $this->prophesize(EntityManagerInterface::class);
|
||||
$container = $this->prophesize(ContainerInterface::class);
|
||||
$container->get('entity.manager')->willReturn($entity_manager->reveal());
|
||||
\Drupal::setContainer($container->reveal());
|
||||
|
||||
$apple = $this->prophesize(EntityTypeInterface::class);
|
||||
$apple->getFormClass('default')->willReturn(TestEntityForm::class);
|
||||
|
||||
$banana = $this->prophesize(EntityTypeInterface::class);
|
||||
$banana->getFormClass('default')->willReturn(TestEntityFormInjected::class);
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'apple' => $apple,
|
||||
'banana' => $banana,
|
||||
]);
|
||||
|
||||
$apple_form = $this->entityTypeManager->getFormObject('apple', 'default');
|
||||
$this->assertInstanceOf(TestEntityForm::class, $apple_form);
|
||||
$this->assertAttributeInstanceOf(ModuleHandlerInterface::class, 'moduleHandler', $apple_form);
|
||||
$this->assertAttributeInstanceOf(TranslationInterface::class, 'stringTranslation', $apple_form);
|
||||
|
||||
$banana_form = $this->entityTypeManager->getFormObject('banana', 'default');
|
||||
$this->assertInstanceOf(TestEntityFormInjected::class, $banana_form);
|
||||
$this->assertAttributeEquals('yellow', 'color', $banana_form);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getFormObject() method with an invalid operation.
|
||||
*
|
||||
* @covers ::getFormObject
|
||||
*
|
||||
* @expectedException \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
|
||||
*/
|
||||
public function testGetFormObjectInvalidOperation() {
|
||||
$entity = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity->getFormClass('edit')->willReturn('');
|
||||
$this->setUpEntityTypeDefinitions(['test_entity_type' => $entity]);
|
||||
|
||||
$this->entityTypeManager->getFormObject('test_entity_type', 'edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getHandler() method.
|
||||
*
|
||||
* @covers ::getHandler
|
||||
*/
|
||||
public function testGetHandler() {
|
||||
$class = $this->getTestHandlerClass();
|
||||
$apple = $this->prophesize(EntityTypeInterface::class);
|
||||
$apple->getHandlerClass('storage')->willReturn($class);
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'apple' => $apple,
|
||||
]);
|
||||
|
||||
$apple_controller = $this->entityTypeManager->getHandler('apple', 'storage');
|
||||
$this->assertInstanceOf($class, $apple_controller);
|
||||
$this->assertAttributeInstanceOf(ModuleHandlerInterface::class, 'moduleHandler', $apple_controller);
|
||||
$this->assertAttributeInstanceOf(TranslationInterface::class, 'stringTranslation', $apple_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getHandler() method when no controller is defined.
|
||||
*
|
||||
* @covers ::getHandler
|
||||
*
|
||||
* @expectedException \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
|
||||
*/
|
||||
public function testGetHandlerMissingHandler() {
|
||||
$entity = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity->getHandlerClass('storage')->willReturn('');
|
||||
$this->setUpEntityTypeDefinitions(['test_entity_type' => $entity]);
|
||||
$this->entityTypeManager->getHandler('test_entity_type', 'storage');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getRouteProviders
|
||||
*/
|
||||
public function testGetRouteProviders() {
|
||||
$apple = $this->prophesize(EntityTypeInterface::class);
|
||||
$apple->getRouteProviderClasses()->willReturn(['default' => TestRouteProvider::class]);
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'apple' => $apple,
|
||||
]);
|
||||
|
||||
$apple_route_provider = $this->entityTypeManager->getRouteProviders('apple');
|
||||
$this->assertInstanceOf(TestRouteProvider::class, $apple_route_provider['default']);
|
||||
$this->assertAttributeInstanceOf(ModuleHandlerInterface::class, 'moduleHandler', $apple_route_provider['default']);
|
||||
$this->assertAttributeInstanceOf(TranslationInterface::class, 'stringTranslation', $apple_route_provider['default']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the processDefinition() method.
|
||||
*
|
||||
* @covers ::processDefinition
|
||||
*
|
||||
* @expectedException \Drupal\Core\Entity\Exception\InvalidLinkTemplateException
|
||||
* @expectedExceptionMessage Link template 'canonical' for entity type 'apple' must start with a leading slash, the current link template is 'path/to/apple'
|
||||
*/
|
||||
public function testProcessDefinition() {
|
||||
$apple = $this->prophesize(EntityTypeInterface::class);
|
||||
$this->setUpEntityTypeDefinitions(['apple' => $apple]);
|
||||
|
||||
$apple->getLinkTemplates()->willReturn(['canonical' => 'path/to/apple']);
|
||||
|
||||
$definition = $apple->reveal();
|
||||
$this->entityTypeManager->processDefinition($definition, 'apple');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getDefinition() method.
|
||||
*
|
||||
* @covers ::getDefinition
|
||||
*
|
||||
* @dataProvider providerTestGetDefinition
|
||||
*/
|
||||
public function testGetDefinition($entity_type_id, $expected) {
|
||||
$entity = $this->prophesize(EntityTypeInterface::class);
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'apple' => $entity,
|
||||
'banana' => $entity,
|
||||
]);
|
||||
|
||||
$entity_type = $this->entityTypeManager->getDefinition($entity_type_id, FALSE);
|
||||
if ($expected) {
|
||||
$this->assertInstanceOf(EntityTypeInterface::class, $entity_type);
|
||||
}
|
||||
else {
|
||||
$this->assertNull($entity_type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testGetDefinition().
|
||||
*
|
||||
* @return array
|
||||
* Test data.
|
||||
*/
|
||||
public function providerTestGetDefinition() {
|
||||
return [
|
||||
['apple', TRUE],
|
||||
['banana', TRUE],
|
||||
['pear', FALSE],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getDefinition() method with an invalid definition.
|
||||
*
|
||||
* @covers ::getDefinition
|
||||
*
|
||||
* @expectedException \Drupal\Component\Plugin\Exception\PluginNotFoundException
|
||||
* @expectedExceptionMessage The "pear" entity type does not exist.
|
||||
*/
|
||||
public function testGetDefinitionInvalidException() {
|
||||
$this->setUpEntityTypeDefinitions();
|
||||
|
||||
$this->entityTypeManager->getDefinition('pear', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a mock controller class name.
|
||||
*
|
||||
* @return string
|
||||
* A mock controller class name.
|
||||
*/
|
||||
protected function getTestHandlerClass() {
|
||||
return get_class($this->getMockForAbstractClass(EntityHandlerBase::class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestEntityTypeManager extends EntityTypeManager {
|
||||
|
||||
/**
|
||||
* Sets the discovery for the manager.
|
||||
*
|
||||
* @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $discovery
|
||||
* The discovery object.
|
||||
*/
|
||||
public function setDiscovery(DiscoveryInterface $discovery) {
|
||||
$this->discovery = $discovery;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a test entity form.
|
||||
*/
|
||||
class TestEntityForm extends EntityHandlerBase {
|
||||
|
||||
/**
|
||||
* The entity manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getBaseFormId() {
|
||||
return 'the_base_form_id';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'the_form_id';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setEntity(EntityInterface $entity) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setOperation($operation) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setEntityManager(EntityManagerInterface $entity_manager) {
|
||||
$this->entityManager = $entity_manager;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setEntityTypeManager(EntityTypeManagerInterface $entity_type_manager) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a test entity form that uses injection.
|
||||
*/
|
||||
class TestEntityFormInjected extends TestEntityForm implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* The color of the entity type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $color;
|
||||
|
||||
/**
|
||||
* Constructs a new TestEntityFormInjected.
|
||||
*
|
||||
* @param string $color
|
||||
* The color of the entity type.
|
||||
*/
|
||||
public function __construct($color) {
|
||||
$this->color = $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static('yellow');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a test entity route provider.
|
||||
*/
|
||||
class TestRouteProvider extends EntityHandlerBase {
|
||||
|
||||
}
|
180
core/tests/Drupal/Tests/Core/Entity/EntityTypeRepositoryTest.php
Normal file
180
core/tests/Drupal/Tests/Core/Entity/EntityTypeRepositoryTest.php
Normal file
|
@ -0,0 +1,180 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Entity\EntityTypeRepositoryTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Entity;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeRepository;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Entity\EntityTypeRepository
|
||||
* @group Entity
|
||||
*/
|
||||
class EntityTypeRepositoryTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The entity type repository under test.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeRepository
|
||||
*/
|
||||
protected $entityTypeRepository;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
|
||||
|
||||
$this->entityTypeRepository = new EntityTypeRepository($this->entityTypeManager->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the entity type manager to be tested.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface[]|\Prophecy\Prophecy\ProphecyInterface[] $definitions
|
||||
* (optional) An array of entity type definitions.
|
||||
*/
|
||||
protected function setUpEntityTypeDefinitions($definitions = []) {
|
||||
$class = $this->getMockClass(EntityInterface::class);
|
||||
foreach ($definitions as $key => $entity_type) {
|
||||
// \Drupal\Core\Entity\EntityTypeInterface::getLinkTemplates() is called
|
||||
// by \Drupal\Core\Entity\EntityManager::processDefinition() so it must
|
||||
// always be mocked.
|
||||
$entity_type->getLinkTemplates()->willReturn([]);
|
||||
|
||||
// Give the entity type a legitimate class to return.
|
||||
$entity_type->getClass()->willReturn($class);
|
||||
|
||||
$definitions[$key] = $entity_type->reveal();
|
||||
}
|
||||
|
||||
$this->entityTypeManager->getDefinition(Argument::cetera())
|
||||
->will(function ($args) use ($definitions) {
|
||||
$entity_type_id = $args[0];
|
||||
$exception_on_invalid = $args[1];
|
||||
if (isset($definitions[$entity_type_id])) {
|
||||
return $definitions[$entity_type_id];
|
||||
}
|
||||
elseif (!$exception_on_invalid) {
|
||||
return NULL;
|
||||
}
|
||||
else throw new PluginNotFoundException($entity_type_id);
|
||||
});
|
||||
$this->entityTypeManager->getDefinitions()->willReturn($definitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getEntityTypeLabels() method.
|
||||
*
|
||||
* @covers ::getEntityTypeLabels
|
||||
*/
|
||||
public function testGetEntityTypeLabels() {
|
||||
$apple = $this->prophesize(EntityTypeInterface::class);
|
||||
$apple->getLabel()->willReturn('Apple');
|
||||
$apple->getBundleOf()->willReturn(NULL);
|
||||
|
||||
$banana = $this->prophesize(EntityTypeInterface::class);
|
||||
$banana->getLabel()->willReturn('Banana');
|
||||
$banana->getBundleOf()->willReturn(NULL);
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'apple' => $apple,
|
||||
'banana' => $banana,
|
||||
]);
|
||||
|
||||
$expected = [
|
||||
'apple' => 'Apple',
|
||||
'banana' => 'Banana',
|
||||
];
|
||||
$this->assertSame($expected, $this->entityTypeRepository->getEntityTypeLabels());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getEntityTypeFromClass
|
||||
*/
|
||||
public function testGetEntityTypeFromClass() {
|
||||
$apple = $this->prophesize(EntityTypeInterface::class);
|
||||
$banana = $this->prophesize(EntityTypeInterface::class);
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'apple' => $apple,
|
||||
'banana' => $banana,
|
||||
]);
|
||||
|
||||
$apple->getOriginalClass()->willReturn('\Drupal\apple\Entity\Apple');
|
||||
|
||||
$banana->getOriginalClass()->willReturn('\Drupal\banana\Entity\Banana');
|
||||
$banana->getClass()->willReturn('\Drupal\mango\Entity\Mango');
|
||||
$banana->id()
|
||||
->willReturn('banana')
|
||||
->shouldBeCalledTimes(2);
|
||||
|
||||
$entity_type_id = $this->entityTypeRepository->getEntityTypeFromClass('\Drupal\banana\Entity\Banana');
|
||||
$this->assertSame('banana', $entity_type_id);
|
||||
$entity_type_id = $this->entityTypeRepository->getEntityTypeFromClass('\Drupal\mango\Entity\Mango');
|
||||
$this->assertSame('banana', $entity_type_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getEntityTypeFromClass
|
||||
*
|
||||
* @expectedException \Drupal\Core\Entity\Exception\NoCorrespondingEntityClassException
|
||||
* @expectedExceptionMessage The \Drupal\pear\Entity\Pear class does not correspond to an entity type.
|
||||
*/
|
||||
public function testGetEntityTypeFromClassNoMatch() {
|
||||
$apple = $this->prophesize(EntityTypeInterface::class);
|
||||
$banana = $this->prophesize(EntityTypeInterface::class);
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'apple' => $apple,
|
||||
'banana' => $banana,
|
||||
]);
|
||||
|
||||
$apple->getOriginalClass()->willReturn('\Drupal\apple\Entity\Apple');
|
||||
$banana->getOriginalClass()->willReturn('\Drupal\banana\Entity\Banana');
|
||||
|
||||
$this->entityTypeRepository->getEntityTypeFromClass('\Drupal\pear\Entity\Pear');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getEntityTypeFromClass
|
||||
*
|
||||
* @expectedException \Drupal\Core\Entity\Exception\AmbiguousEntityClassException
|
||||
* @expectedExceptionMessage Multiple entity types found for \Drupal\apple\Entity\Apple.
|
||||
*/
|
||||
public function testGetEntityTypeFromClassAmbiguous() {
|
||||
$boskoop = $this->prophesize(EntityTypeInterface::class);
|
||||
$boskoop->getOriginalClass()->willReturn('\Drupal\apple\Entity\Apple');
|
||||
$boskoop->id()->willReturn('boskop');
|
||||
|
||||
$gala = $this->prophesize(EntityTypeInterface::class);
|
||||
$gala->getOriginalClass()->willReturn('\Drupal\apple\Entity\Apple');
|
||||
$gala->id()->willReturn('gala');
|
||||
|
||||
$this->setUpEntityTypeDefinitions([
|
||||
'boskoop' => $boskoop,
|
||||
'gala' => $gala,
|
||||
]);
|
||||
|
||||
$this->entityTypeRepository->getEntityTypeFromClass('\Drupal\apple\Entity\Apple');
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\system\Tests\Extension\InfoParserUnitTest.
|
||||
* Contains \Drupal\Tests\Core\Extension\InfoParserUnitTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Extension;
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Field\FieldDefinitionListenerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Field;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Entity\DynamicallyFieldableEntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityFieldManagerInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldDefinitionListener;
|
||||
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
|
||||
use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Field\FieldDefinitionListener
|
||||
* @group Field
|
||||
*/
|
||||
class FieldDefinitionListenerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The key-value factory.
|
||||
*
|
||||
* @var \Drupal\Core\KeyValueStore\KeyValueFactoryInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $keyValueFactory;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The entity field manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityFieldManagerInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $entityFieldManager;
|
||||
|
||||
/**
|
||||
* The cache backend.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface|\Prophecy\Prophecy\ProphecyInterface
|
||||
*/
|
||||
protected $cacheBackend;
|
||||
|
||||
/**
|
||||
* The field definition listener under test.
|
||||
*
|
||||
* @var \Drupal\Core\Field\FieldDefinitionListener
|
||||
*/
|
||||
protected $fieldDefinitionListener;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->keyValueFactory = $this->prophesize(KeyValueFactoryInterface::class);
|
||||
$this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
|
||||
$this->entityFieldManager = $this->prophesize(EntityFieldManagerInterface::class);
|
||||
$this->cacheBackend = $this->prophesize(CacheBackendInterface::class);
|
||||
|
||||
$this->fieldDefinitionListener = new FieldDefinitionListener($this->entityTypeManager->reveal(), $this->entityFieldManager->reveal(), $this->keyValueFactory->reveal(), $this->cacheBackend->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the entity manager to be tested.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface[]|\Prophecy\Prophecy\ProphecyInterface[] $definitions
|
||||
* (optional) An array of entity type definitions.
|
||||
*/
|
||||
protected function setUpEntityManager($definitions = array()) {
|
||||
$class = $this->getMockClass(EntityInterface::class);
|
||||
foreach ($definitions as $key => $entity_type) {
|
||||
// \Drupal\Core\Entity\EntityTypeInterface::getLinkTemplates() is called
|
||||
// by \Drupal\Core\Entity\EntityManager::processDefinition() so it must
|
||||
// always be mocked.
|
||||
$entity_type->getLinkTemplates()->willReturn([]);
|
||||
|
||||
// Give the entity type a legitimate class to return.
|
||||
$entity_type->getClass()->willReturn($class);
|
||||
|
||||
$definitions[$key] = $entity_type->reveal();
|
||||
}
|
||||
|
||||
$this->entityTypeManager->getDefinition(Argument::cetera())
|
||||
->will(function ($args) use ($definitions) {
|
||||
$entity_type_id = $args[0];
|
||||
$exception_on_invalid = $args[1];
|
||||
if (isset($definitions[$entity_type_id])) {
|
||||
return $definitions[$entity_type_id];
|
||||
}
|
||||
elseif (!$exception_on_invalid) {
|
||||
return NULL;
|
||||
}
|
||||
else throw new PluginNotFoundException($entity_type_id);
|
||||
});
|
||||
$this->entityTypeManager->getDefinitions()->willReturn($definitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::onFieldDefinitionCreate
|
||||
*/
|
||||
public function testOnFieldDefinitionCreateNewField() {
|
||||
$field_definition = $this->prophesize(FieldDefinitionInterface::class);
|
||||
$field_definition->getTargetEntityTypeId()->willReturn('test_entity_type');
|
||||
$field_definition->getTargetBundle()->willReturn('test_bundle');
|
||||
$field_definition->getName()->willReturn('test_field');
|
||||
$field_definition->getType()->willReturn('test_type');
|
||||
|
||||
$storage = $this->prophesize(DynamicallyFieldableEntityStorageInterface::class);
|
||||
$storage->onFieldDefinitionCreate($field_definition->reveal())->shouldBeCalledTimes(1);
|
||||
$this->entityTypeManager->getStorage('test_entity_type')->willReturn($storage->reveal());
|
||||
|
||||
$entity = $this->prophesize(EntityTypeInterface::class);
|
||||
$this->setUpEntityManager(['test_entity_type' => $entity]);
|
||||
|
||||
// Set up the stored bundle field map.
|
||||
$key_value_store = $this->prophesize(KeyValueStoreInterface::class);
|
||||
$this->keyValueFactory->get('entity.definitions.bundle_field_map')->willReturn($key_value_store->reveal());
|
||||
$key_value_store->get('test_entity_type')->willReturn([]);
|
||||
$key_value_store->set('test_entity_type', [
|
||||
'test_field' => [
|
||||
'type' => 'test_type',
|
||||
'bundles' => ['test_bundle' => 'test_bundle'],
|
||||
],
|
||||
])->shouldBeCalled();
|
||||
|
||||
$this->fieldDefinitionListener->onFieldDefinitionCreate($field_definition->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::onFieldDefinitionCreate
|
||||
*/
|
||||
public function testOnFieldDefinitionCreateExistingField() {
|
||||
$field_definition = $this->prophesize(FieldDefinitionInterface::class);
|
||||
$field_definition->getTargetEntityTypeId()->willReturn('test_entity_type');
|
||||
$field_definition->getTargetBundle()->willReturn('test_bundle');
|
||||
$field_definition->getName()->willReturn('test_field');
|
||||
|
||||
$storage = $this->prophesize(DynamicallyFieldableEntityStorageInterface::class);
|
||||
$storage->onFieldDefinitionCreate($field_definition->reveal())->shouldBeCalledTimes(1);
|
||||
$this->entityTypeManager->getStorage('test_entity_type')->willReturn($storage->reveal());
|
||||
|
||||
$entity = $this->prophesize(EntityTypeInterface::class);
|
||||
$this->setUpEntityManager(['test_entity_type' => $entity]);
|
||||
|
||||
// Set up the stored bundle field map.
|
||||
$key_value_store = $this->prophesize(KeyValueStoreInterface::class);
|
||||
$this->keyValueFactory->get('entity.definitions.bundle_field_map')->willReturn($key_value_store->reveal());
|
||||
$key_value_store->get('test_entity_type')->willReturn([
|
||||
'test_field' => [
|
||||
'type' => 'test_type',
|
||||
'bundles' => ['existing_bundle' => 'existing_bundle'],
|
||||
],
|
||||
]);
|
||||
$key_value_store->set('test_entity_type', [
|
||||
'test_field' => [
|
||||
'type' => 'test_type',
|
||||
'bundles' => ['existing_bundle' => 'existing_bundle', 'test_bundle' => 'test_bundle'],
|
||||
],
|
||||
])
|
||||
->shouldBeCalled();
|
||||
|
||||
$this->fieldDefinitionListener->onFieldDefinitionCreate($field_definition->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::onFieldDefinitionUpdate
|
||||
*/
|
||||
public function testOnFieldDefinitionUpdate() {
|
||||
$field_definition = $this->prophesize(FieldDefinitionInterface::class);
|
||||
$field_definition->getTargetEntityTypeId()->willReturn('test_entity_type');
|
||||
|
||||
$storage = $this->prophesize(DynamicallyFieldableEntityStorageInterface::class);
|
||||
$storage->onFieldDefinitionUpdate($field_definition->reveal(), $field_definition->reveal())->shouldBeCalledTimes(1);
|
||||
$this->entityTypeManager->getStorage('test_entity_type')->willReturn($storage->reveal());
|
||||
|
||||
$entity = $this->prophesize(EntityTypeInterface::class);
|
||||
$this->setUpEntityManager(['test_entity_type' => $entity]);
|
||||
|
||||
$this->fieldDefinitionListener->onFieldDefinitionUpdate($field_definition->reveal(), $field_definition->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::onFieldDefinitionDelete
|
||||
*/
|
||||
public function testOnFieldDefinitionDeleteMultipleBundles() {
|
||||
$field_definition = $this->prophesize(FieldDefinitionInterface::class);
|
||||
$field_definition->getTargetEntityTypeId()->willReturn('test_entity_type');
|
||||
$field_definition->getTargetBundle()->willReturn('test_bundle');
|
||||
$field_definition->getName()->willReturn('test_field');
|
||||
|
||||
$storage = $this->prophesize(DynamicallyFieldableEntityStorageInterface::class);
|
||||
$storage->onFieldDefinitionDelete($field_definition->reveal())->shouldBeCalledTimes(1);
|
||||
$this->entityTypeManager->getStorage('test_entity_type')->willReturn($storage->reveal());
|
||||
|
||||
$entity = $this->prophesize(EntityTypeInterface::class);
|
||||
$this->setUpEntityManager(['test_entity_type' => $entity]);
|
||||
|
||||
// Set up the stored bundle field map.
|
||||
$key_value_store = $this->prophesize(KeyValueStoreInterface::class);
|
||||
$this->keyValueFactory->get('entity.definitions.bundle_field_map')->willReturn($key_value_store->reveal());
|
||||
$key_value_store->get('test_entity_type')->willReturn([
|
||||
'test_field' => [
|
||||
'type' => 'test_type',
|
||||
'bundles' => ['test_bundle' => 'test_bundle'],
|
||||
],
|
||||
'second_field' => [
|
||||
'type' => 'test_type',
|
||||
'bundles' => ['test_bundle' => 'test_bundle'],
|
||||
],
|
||||
]);
|
||||
$key_value_store->set('test_entity_type', [
|
||||
'second_field' => [
|
||||
'type' => 'test_type',
|
||||
'bundles' => ['test_bundle' => 'test_bundle'],
|
||||
],
|
||||
])
|
||||
->shouldBeCalled();
|
||||
|
||||
$this->fieldDefinitionListener->onFieldDefinitionDelete($field_definition->reveal());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @covers ::onFieldDefinitionDelete
|
||||
*/
|
||||
public function testOnFieldDefinitionDeleteSingleBundles() {
|
||||
$field_definition = $this->prophesize(FieldDefinitionInterface::class);
|
||||
$field_definition->getTargetEntityTypeId()->willReturn('test_entity_type');
|
||||
$field_definition->getTargetBundle()->willReturn('test_bundle');
|
||||
$field_definition->getName()->willReturn('test_field');
|
||||
|
||||
$storage = $this->prophesize(DynamicallyFieldableEntityStorageInterface::class);
|
||||
$storage->onFieldDefinitionDelete($field_definition->reveal())->shouldBeCalledTimes(1);
|
||||
$this->entityTypeManager->getStorage('test_entity_type')->willReturn($storage->reveal());
|
||||
|
||||
$entity = $this->prophesize(EntityTypeInterface::class);
|
||||
$this->setUpEntityManager(['test_entity_type' => $entity]);
|
||||
|
||||
// Set up the stored bundle field map.
|
||||
$key_value_store = $this->prophesize(KeyValueStoreInterface::class);
|
||||
$this->keyValueFactory->get('entity.definitions.bundle_field_map')->willReturn($key_value_store->reveal());
|
||||
$key_value_store->get('test_entity_type')->willReturn([
|
||||
'test_field' => [
|
||||
'type' => 'test_type',
|
||||
'bundles' => ['test_bundle' => 'test_bundle', 'second_bundle' => 'second_bundle'],
|
||||
],
|
||||
]);
|
||||
$key_value_store->set('test_entity_type', [
|
||||
'test_field' => [
|
||||
'type' => 'test_type',
|
||||
'bundles' => ['second_bundle' => 'second_bundle'],
|
||||
],
|
||||
])
|
||||
->shouldBeCalled();
|
||||
|
||||
$this->fieldDefinitionListener->onFieldDefinitionDelete($field_definition->reveal());
|
||||
}
|
||||
|
||||
}
|
|
@ -56,7 +56,7 @@ class ContextTest extends UnitTestCase {
|
|||
* @covers ::getContextValue
|
||||
*/
|
||||
public function testDefaultValue() {
|
||||
$this->setUpDefaultValue();
|
||||
$this->setUpDefaultValue('test');
|
||||
|
||||
$context = new Context($this->contextDefinition);
|
||||
$context->setTypedDataManager($this->typedDataManager);
|
||||
|
@ -67,7 +67,18 @@ class ContextTest extends UnitTestCase {
|
|||
* @covers ::getContextData
|
||||
*/
|
||||
public function testDefaultDataValue() {
|
||||
$this->setUpDefaultValue();
|
||||
$this->setUpDefaultValue('test');
|
||||
|
||||
$context = new Context($this->contextDefinition);
|
||||
$context->setTypedDataManager($this->typedDataManager);
|
||||
$this->assertEquals($this->typedData, $context->getContextData());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getContextData
|
||||
*/
|
||||
public function testNullDataValue() {
|
||||
$this->setUpDefaultValue(NULL);
|
||||
|
||||
$context = new Context($this->contextDefinition);
|
||||
$context->setTypedDataManager($this->typedDataManager);
|
||||
|
@ -127,8 +138,11 @@ class ContextTest extends UnitTestCase {
|
|||
|
||||
/**
|
||||
* Set up mocks for the getDefaultValue() method call.
|
||||
*
|
||||
* @param mixed $default_value
|
||||
* The default value to assign to the mock context definition.
|
||||
*/
|
||||
protected function setUpDefaultValue() {
|
||||
protected function setUpDefaultValue($default_value = NULL) {
|
||||
$mock_data_definition = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
|
||||
|
||||
$this->contextDefinition = $this->getMockBuilder('Drupal\Core\Plugin\Context\ContextDefinitionInterface')
|
||||
|
@ -137,7 +151,7 @@ class ContextTest extends UnitTestCase {
|
|||
|
||||
$this->contextDefinition->expects($this->once())
|
||||
->method('getDefaultValue')
|
||||
->willReturn('test');
|
||||
->willReturn($default_value);
|
||||
|
||||
$this->contextDefinition->expects($this->once())
|
||||
->method('getDataDefinition')
|
||||
|
@ -147,7 +161,7 @@ class ContextTest extends UnitTestCase {
|
|||
|
||||
$this->typedDataManager->expects($this->once())
|
||||
->method('create')
|
||||
->with($mock_data_definition, 'test')
|
||||
->with($mock_data_definition, $default_value)
|
||||
->willReturn($this->typedData);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Render\PlaceholderGeneratorTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Render;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Render\Element;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Render\PlaceholderGenerator
|
||||
* @group Render
|
||||
*/
|
||||
class PlaceholderGeneratorTest extends RendererTestBase {
|
||||
|
||||
/**
|
||||
* The tested placeholder generator.
|
||||
*
|
||||
* @var \Drupal\Core\Render\PlaceholderGenerator
|
||||
*/
|
||||
protected $placeholderGenerator;
|
||||
|
||||
/**
|
||||
* @covers ::createPlaceholder
|
||||
* @dataProvider providerCreatePlaceholderGeneratesValidHtmlMarkup
|
||||
*
|
||||
* Ensure that the generated placeholder markup is valid. If it is not, then
|
||||
* simply using DOMDocument on HTML that contains placeholders may modify the
|
||||
* placeholders' markup, which would make it impossible to replace the
|
||||
* placeholders: the placeholder markup in #attached versus that in the HTML
|
||||
* processed by DOMDocument would no longer match.
|
||||
*/
|
||||
public function testCreatePlaceholderGeneratesValidHtmlMarkup(array $element) {
|
||||
$build = $this->placeholderGenerator->createPlaceholder($element);
|
||||
|
||||
$original_placeholder_markup = (string)$build['#markup'];
|
||||
$processed_placeholder_markup = Html::serialize(Html::load($build['#markup']));
|
||||
|
||||
$this->assertEquals($original_placeholder_markup, $processed_placeholder_markup);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function providerCreatePlaceholderGeneratesValidHtmlMarkup() {
|
||||
return [
|
||||
'multiple-arguments' => [['#lazy_builder' => ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', ['foo', 'bar']]]],
|
||||
'special-character-&' => [['#lazy_builder' => ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', ['foo&bar']]]],
|
||||
'special-character-"' => [['#lazy_builder' => ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', ['foo"bar']]]],
|
||||
'special-character-<' => [['#lazy_builder' => ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', ['foo<bar']]]],
|
||||
'special-character->' => [['#lazy_builder' => ['Drupal\Tests\Core\Render\PlaceholdersTest::callback', ['foo>bar']]]],
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -66,7 +66,7 @@ class TranslationManagerTest extends UnitTestCase {
|
|||
* Tests translation using placeholders.
|
||||
*
|
||||
* @param string $string
|
||||
* A string containing the English string to translate.
|
||||
* A string containing the English text to translate.
|
||||
* @param array $args
|
||||
* An associative array of replacements to make after translation.
|
||||
* @param string $expected_string
|
||||
|
|
|
@ -200,6 +200,20 @@ class TwigExtensionTest extends UnitTestCase {
|
|||
];
|
||||
$result = $twig_extension->safeJoin($twig_environment, $items, '<br/>');
|
||||
$this->assertEquals('<em>will be escaped</em><br/><em>will be markup</em><br/><strong>will be rendered</strong>', $result);
|
||||
|
||||
// Ensure safe_join Twig filter supports Traversable variables.
|
||||
$items = new \ArrayObject([
|
||||
'<em>will be escaped</em>',
|
||||
$markup,
|
||||
['#markup' => '<strong>will be rendered</strong>'],
|
||||
]);
|
||||
$result = $twig_extension->safeJoin($twig_environment, $items, ', ');
|
||||
$this->assertEquals('<em>will be escaped</em>, <em>will be markup</em>, <strong>will be rendered</strong>', $result);
|
||||
|
||||
// Ensure safe_join Twig filter supports empty variables.
|
||||
$items = NULL;
|
||||
$result = $twig_extension->safeJoin($twig_environment, $items, '<br>');
|
||||
$this->assertEmpty($result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
135
core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php
Normal file
135
core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php
Normal file
|
@ -0,0 +1,135 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Template\TwigSandboxTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Template;
|
||||
|
||||
use Drupal\Core\Template\TwigSandboxPolicy;
|
||||
use Drupal\Core\Template\Loader\StringLoader;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the twig sandbox policy.
|
||||
*
|
||||
* @group Template
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Template\TwigSandboxPolicy
|
||||
*/
|
||||
class TwigSandboxTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The Twig environment loaded with the sandbox extension.
|
||||
*
|
||||
* @var \Twig_Environment
|
||||
*/
|
||||
protected $twig;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$loader = new StringLoader();
|
||||
$this->twig = new \Twig_Environment($loader);
|
||||
$policy = new TwigSandboxPolicy();
|
||||
$sandbox = new \Twig_Extension_Sandbox($policy, TRUE);
|
||||
$this->twig->addExtension($sandbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that dangerous methods cannot be called in entity objects.
|
||||
*
|
||||
* @dataProvider getTwigEntityDangerousMethods
|
||||
* @expectedException \Twig_Sandbox_SecurityError
|
||||
*/
|
||||
public function testEntityDangerousMethods($template) {
|
||||
$entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
|
||||
$this->twig->render($template, ['entity' => $entity]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for ::testEntityDangerousMethods.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTwigEntityDangerousMethods() {
|
||||
return [
|
||||
['{{ entity.delete }}'],
|
||||
['{{ entity.save }}'],
|
||||
['{{ entity.create }}'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that prefixed methods can be called from within Twig templates.
|
||||
*
|
||||
* Currently "get", "has", and "is" are the only allowed prefixes.
|
||||
*/
|
||||
public function testEntitySafePrefixes() {
|
||||
$entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
|
||||
$entity->expects($this->atLeastOnce())
|
||||
->method('hasLinkTemplate')
|
||||
->with('test')
|
||||
->willReturn(TRUE);
|
||||
$result = $this->twig->render('{{ entity.hasLinkTemplate("test") }}', ['entity' => $entity]);
|
||||
$this->assertTrue((bool)$result, 'Sandbox policy allows has* functions to be called.');
|
||||
|
||||
$entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
|
||||
$entity->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->willReturn(TRUE);
|
||||
$result = $this->twig->render('{{ entity.isNew }}', ['entity' => $entity]);
|
||||
$this->assertTrue((bool)$result, 'Sandbox policy allows is* functions to be called.');
|
||||
|
||||
$entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
|
||||
$entity->expects($this->atLeastOnce())
|
||||
->method('getEntityType')
|
||||
->willReturn('test');
|
||||
$result = $this->twig->render('{{ entity.getEntityType }}', ['entity' => $entity]);
|
||||
$this->assertEquals($result, 'test', 'Sandbox policy allows get* functions to be called.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that valid methods can be called from within Twig templates.
|
||||
*
|
||||
* Currently the following methods are whitelisted: id, label, bundle, and
|
||||
* get.
|
||||
*/
|
||||
public function testEntitySafeMethods() {
|
||||
$entity = $this->getMockBuilder('Drupal\Core\Entity\ContentEntityBase')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$entity->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->with('title')
|
||||
->willReturn('test');
|
||||
$result = $this->twig->render('{{ entity.get("title") }}', ['entity' => $entity]);
|
||||
$this->assertEquals($result, 'test', 'Sandbox policy allows get() to be called.');
|
||||
|
||||
$entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
|
||||
$entity->expects($this->atLeastOnce())
|
||||
->method('id')
|
||||
->willReturn('1234');
|
||||
$result = $this->twig->render('{{ entity.id }}', ['entity' => $entity]);
|
||||
$this->assertEquals($result, '1234', 'Sandbox policy allows get() to be called.');
|
||||
|
||||
$entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
|
||||
$entity->expects($this->atLeastOnce())
|
||||
->method('label')
|
||||
->willReturn('testing');
|
||||
$result = $this->twig->render('{{ entity.label }}', ['entity' => $entity]);
|
||||
$this->assertEquals($result, 'testing', 'Sandbox policy allows get() to be called.');
|
||||
|
||||
$entity = $this->getMock('Drupal\Core\Entity\EntityInterface');
|
||||
$entity->expects($this->atLeastOnce())
|
||||
->method('bundle')
|
||||
->willReturn('testing');
|
||||
$result = $this->twig->render('{{ entity.bundle }}', ['entity' => $entity]);
|
||||
$this->assertEquals($result, 'testing', 'Sandbox policy allows get() to be called.');
|
||||
}
|
||||
|
||||
}
|
|
@ -54,18 +54,18 @@ EOS;
|
|||
$module_a = <<<'EOS'
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Module A update A.
|
||||
*/
|
||||
function module_a_post_update_a() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Module A update B.
|
||||
*/
|
||||
function module_a_post_update_b() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Module A update A.
|
||||
*/
|
||||
function module_a_post_update_a() {
|
||||
}
|
||||
|
||||
EOS;
|
||||
$module_b = <<<'EOS'
|
||||
<?php
|
||||
|
@ -236,8 +236,12 @@ EOS;
|
|||
public function testRegisterInvokedUpdatesWithoutExistingUpdates() {
|
||||
$this->setupBasicModules();
|
||||
$key_value = $this->prophesize(KeyValueStoreInterface::class);
|
||||
$key_value->get('existing_updates', [])->willReturn([]);
|
||||
$key_value->set('existing_updates', ['module_a_post_update_a'])->willReturn(NULL);
|
||||
$key_value->get('existing_updates', [])
|
||||
->willReturn([])
|
||||
->shouldBeCalledTimes(1);
|
||||
$key_value->set('existing_updates', ['module_a_post_update_a'])
|
||||
->willReturn(NULL)
|
||||
->shouldBeCalledTimes(1);
|
||||
$key_value = $key_value->reveal();
|
||||
|
||||
$update_registry = new UpdateRegistry('vfs://drupal', 'sites/default', [
|
||||
|
@ -253,8 +257,12 @@ EOS;
|
|||
public function testRegisterInvokedUpdatesWithMultiple() {
|
||||
$this->setupBasicModules();
|
||||
$key_value = $this->prophesize(KeyValueStoreInterface::class);
|
||||
$key_value->get('existing_updates', [])->willReturn([]);
|
||||
$key_value->set('existing_updates', ['module_a_post_update_a', 'module_a_post_update_b'])->willReturn(NULL);
|
||||
$key_value->get('existing_updates', [])
|
||||
->willReturn([])
|
||||
->shouldBeCalledTimes(1);
|
||||
$key_value->set('existing_updates', ['module_a_post_update_a', 'module_a_post_update_b'])
|
||||
->willReturn(NULL)
|
||||
->shouldBeCalledTimes(1);
|
||||
$key_value = $key_value->reveal();
|
||||
|
||||
$update_registry = new UpdateRegistry('vfs://drupal', 'sites/default', [
|
||||
|
@ -270,8 +278,12 @@ EOS;
|
|||
public function testRegisterInvokedUpdatesWithExistingUpdates() {
|
||||
$this->setupBasicModules();
|
||||
$key_value = $this->prophesize(KeyValueStoreInterface::class);
|
||||
$key_value->get('existing_updates', [])->willReturn(['module_a_post_update_b']);
|
||||
$key_value->set('existing_updates', ['module_a_post_update_b', 'module_a_post_update_a'])->willReturn(NULL);
|
||||
$key_value->get('existing_updates', [])
|
||||
->willReturn(['module_a_post_update_b'])
|
||||
->shouldBeCalledTimes(1);
|
||||
$key_value->set('existing_updates', ['module_a_post_update_b', 'module_a_post_update_a'])
|
||||
->willReturn(NULL)
|
||||
->shouldBeCalledTimes(1);
|
||||
$key_value = $key_value->reveal();
|
||||
|
||||
$update_registry = new UpdateRegistry('vfs://drupal', 'sites/default', [
|
||||
|
@ -287,8 +299,12 @@ EOS;
|
|||
public function testFilterOutInvokedUpdatesByModule() {
|
||||
$this->setupBasicModules();
|
||||
$key_value = $this->prophesize(KeyValueStoreInterface::class);
|
||||
$key_value->get('existing_updates', [])->willReturn(['module_a_post_update_b', 'module_a_post_update_a', 'module_b_post_update_a']);
|
||||
$key_value->set('existing_updates', ['module_b_post_update_a'])->willReturn(NULL);
|
||||
$key_value->get('existing_updates', [])
|
||||
->willReturn(['module_a_post_update_b', 'module_a_post_update_a', 'module_b_post_update_a'])
|
||||
->shouldBeCalledTimes(1);
|
||||
$key_value->set('existing_updates', ['module_b_post_update_a'])
|
||||
->willReturn(NULL)
|
||||
->shouldBeCalledTimes(1);
|
||||
$key_value = $key_value->reveal();
|
||||
|
||||
$update_registry = new UpdateRegistry('vfs://drupal', 'sites/default', [
|
||||
|
|
Reference in a new issue