Issue #2226027 by tim.plunkett: ConfigEntityBase::preSave() tries to load the original entity but instead loads itself.
parent
669b898b86
commit
979bb625ce
|
@ -278,8 +278,9 @@ abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface
|
|||
throw new ConfigDuplicateUUIDException(String::format('Attempt to save a configuration entity %id with UUID %uuid when this UUID is already used for %matched', array('%id' => $this->id(), '%uuid' => $this->uuid(), '%matched' => $matched_entity)));
|
||||
}
|
||||
|
||||
// If this entity is not new, load the original entity for comparison.
|
||||
if (!$this->isNew()) {
|
||||
$original = $storage->loadUnchanged($this->id());
|
||||
$original = $storage->loadUnchanged($this->getOriginalId());
|
||||
// Ensure that the UUID cannot be changed for an existing entity.
|
||||
if ($original && ($original->uuid() != $this->uuid())) {
|
||||
throw new ConfigDuplicateUUIDException(String::format('Attempt to save a configuration entity %id with UUID %uuid when this entity already exists with UUID %original_uuid', array('%id' => $this->id(), '%uuid' => $this->uuid(), '%original_uuid' => $original->uuid())));
|
||||
|
|
|
@ -18,6 +18,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
|
|||
use Drupal\Core\Entity\EntityStorageException;
|
||||
use Drupal\Core\Entity\Query\QueryFactory;
|
||||
use Drupal\Component\Uuid\UuidInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
|
@ -65,6 +66,13 @@ class ConfigEntityStorage extends EntityStorageBase implements ConfigEntityStora
|
|||
*/
|
||||
protected $configStorage;
|
||||
|
||||
/**
|
||||
* The language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* Constructs a ConfigEntityStorage object.
|
||||
*
|
||||
|
@ -76,8 +84,10 @@ class ConfigEntityStorage extends EntityStorageBase implements ConfigEntityStora
|
|||
* The config storage service.
|
||||
* @param \Drupal\Component\Uuid\UuidInterface $uuid_service
|
||||
* The UUID service.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, UuidInterface $uuid_service) {
|
||||
public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, UuidInterface $uuid_service, LanguageManagerInterface $language_manager) {
|
||||
parent::__construct($entity_type);
|
||||
|
||||
$this->idKey = $this->entityType->getKey('id');
|
||||
|
@ -86,6 +96,7 @@ class ConfigEntityStorage extends EntityStorageBase implements ConfigEntityStora
|
|||
$this->configFactory = $config_factory;
|
||||
$this->configStorage = $config_storage;
|
||||
$this->uuidService = $uuid_service;
|
||||
$this->languageManager = $language_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,7 +107,8 @@ class ConfigEntityStorage extends EntityStorageBase implements ConfigEntityStora
|
|||
$entity_type,
|
||||
$container->get('config.factory'),
|
||||
$container->get('config.storage'),
|
||||
$container->get('uuid')
|
||||
$container->get('uuid'),
|
||||
$container->get('language_manager')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -228,7 +240,7 @@ class ConfigEntityStorage extends EntityStorageBase implements ConfigEntityStora
|
|||
$class::preCreate($this, $values);
|
||||
|
||||
// Set default language to site default if not provided.
|
||||
$values += array('langcode' => language_default()->id);
|
||||
$values += array('langcode' => $this->languageManager->getDefaultLanguage()->id);
|
||||
|
||||
$entity = new $class($values, $this->entityTypeId);
|
||||
// Mark this entity as new, so isNew() returns TRUE. This does not check
|
||||
|
@ -331,9 +343,6 @@ class ConfigEntityStorage extends EntityStorageBase implements ConfigEntityStora
|
|||
$config->save();
|
||||
$entity->postSave($this, TRUE);
|
||||
$this->invokeHook('update', $entity);
|
||||
|
||||
// Immediately update the original ID.
|
||||
$entity->setOriginalId($entity->id());
|
||||
}
|
||||
else {
|
||||
$return = SAVED_NEW;
|
||||
|
@ -343,6 +352,11 @@ class ConfigEntityStorage extends EntityStorageBase implements ConfigEntityStora
|
|||
$this->invokeHook('insert', $entity);
|
||||
}
|
||||
|
||||
// After saving, this is now the "original entity", and subsequent saves
|
||||
// will be updates instead of inserts, and updates must always be able to
|
||||
// correctly identify the original entity.
|
||||
$entity->setOriginalId($entity->id());
|
||||
|
||||
unset($entity->original);
|
||||
|
||||
return $return;
|
||||
|
|
|
@ -314,7 +314,9 @@ abstract class Entity extends DependencySerialization implements EntityInterface
|
|||
public function createDuplicate() {
|
||||
$duplicate = clone $this;
|
||||
$entity_type = $this->getEntityType();
|
||||
// Reset the entity ID and indicate that this is a new entity.
|
||||
$duplicate->{$entity_type->getKey('id')} = NULL;
|
||||
$duplicate->enforceIsNew();
|
||||
|
||||
// Check if the entity type supports UUIDs and generate a new one if so.
|
||||
if ($entity_type->hasKey('uuid')) {
|
||||
|
|
|
@ -105,6 +105,18 @@ class Breakpoint extends ConfigEntityBase implements BreakpointInterface {
|
|||
*/
|
||||
public $multipliers = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function id() {
|
||||
// If no ID is specified, build one from the properties that uniquely define
|
||||
// this breakpoint.
|
||||
if (!isset($this->id)) {
|
||||
$this->id = $this->sourceType . '.' . $this->source . '.' . $this->name;
|
||||
}
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Drupal\config\ConfigEntityBase::save().
|
||||
*/
|
||||
|
@ -114,13 +126,6 @@ class Breakpoint extends ConfigEntityBase implements BreakpointInterface {
|
|||
throw new InvalidBreakpointException('Invalid data detected.');
|
||||
}
|
||||
|
||||
// Build an id if none is set.
|
||||
// Since a particular name can be used by multiple theme/modules we need
|
||||
// to make a unique id.
|
||||
if (empty($this->id)) {
|
||||
$this->id = $this->sourceType . '.' . $this->source . '.' . $this->name;
|
||||
}
|
||||
|
||||
// Set the label if none is set.
|
||||
if (empty($this->label)) {
|
||||
$this->label = $this->name;
|
||||
|
|
|
@ -104,10 +104,19 @@ class BreakpointGroup extends ConfigEntityBase implements BreakpointGroupInterfa
|
|||
if (!$this->isValid()) {
|
||||
throw new InvalidBreakpointException('Invalid data detected.');
|
||||
}
|
||||
if (empty($this->id)) {
|
||||
parent::save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function id() {
|
||||
// If no ID is specified, build one from the properties that uniquely define
|
||||
// this breakpoint group.
|
||||
if (!isset($this->id)) {
|
||||
$this->id = $this->sourceType . '.' . $this->source . '.' . $this->name;
|
||||
}
|
||||
parent::save();
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -46,7 +46,7 @@ class BreakpointAPITest extends BreakpointTestBase {
|
|||
$this->assertTrue($exception, 'breakpoint_config_name: An exception is thrown when an invalid sourceType is entered.');
|
||||
|
||||
// Try an invalid source.
|
||||
$breakpoint->id = '';
|
||||
$breakpoint = $breakpoint->createDuplicate();
|
||||
$breakpoint->sourceType = Breakpoint::SOURCE_TYPE_USER_DEFINED;
|
||||
$breakpoint->source = 'custom*_module source';
|
||||
|
||||
|
@ -60,7 +60,7 @@ class BreakpointAPITest extends BreakpointTestBase {
|
|||
$this->assertTrue($exception, 'breakpoint_config_name: An exception is thrown when an invalid source is entered.');
|
||||
|
||||
// Try an invalid name (make sure there is at least once capital letter).
|
||||
$breakpoint->id = '';
|
||||
$breakpoint = $breakpoint->createDuplicate();
|
||||
$breakpoint->source = 'custom_module';
|
||||
$breakpoint->name = drupal_ucfirst($this->randomName());
|
||||
|
||||
|
@ -74,7 +74,7 @@ class BreakpointAPITest extends BreakpointTestBase {
|
|||
$this->assertTrue($exception, 'breakpoint_config_name: An exception is thrown when an invalid name is entered.');
|
||||
|
||||
// Try a valid breakpoint.
|
||||
$breakpoint->id = '';
|
||||
$breakpoint = $breakpoint->createDuplicate();
|
||||
$breakpoint->name = drupal_strtolower($this->randomName());
|
||||
$breakpoint->mediaQuery = 'all';
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ class BreakpointGroupAPITest extends BreakpointGroupTestBase {
|
|||
$this->assertTrue($exception, 'An exception is thrown when an invalid sourceType is entered.');
|
||||
|
||||
// Try an invalid source.
|
||||
$breakpoint_group = $breakpoint_group->createDuplicate();
|
||||
$breakpoint_group->name = '';
|
||||
$breakpoint_group->sourceType = Breakpoint::SOURCE_TYPE_USER_DEFINED;
|
||||
$breakpoint_group->source = 'custom*_module source';
|
||||
|
@ -63,6 +64,7 @@ class BreakpointGroupAPITest extends BreakpointGroupTestBase {
|
|||
$this->assertTrue($exception, 'An exception is thrown when an invalid source is entered.');
|
||||
|
||||
// Try a valid breakpoint_group.
|
||||
$breakpoint_group = $breakpoint_group->createDuplicate();
|
||||
$breakpoint_group->name = 'test';
|
||||
$breakpoint_group->source = 'custom_module_source';
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ use Drupal\Core\Config\Entity\ConfigEntityStorage;
|
|||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\Query\QueryFactory;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
|
@ -56,6 +57,8 @@ class FieldConfigStorage extends ConfigEntityStorage {
|
|||
* The config storage service.
|
||||
* @param \Drupal\Component\Uuid\UuidInterface $uuid_service
|
||||
* The UUID service.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Extension\ModuleHandler $module_handler
|
||||
|
@ -63,8 +66,8 @@ class FieldConfigStorage extends ConfigEntityStorage {
|
|||
* @param \Drupal\Core\KeyValueStore\StateInterface $state
|
||||
* The state key value store.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, UuidInterface $uuid_service, EntityManagerInterface $entity_manager, ModuleHandler $module_handler, StateInterface $state) {
|
||||
parent::__construct($entity_type, $config_factory, $config_storage, $uuid_service);
|
||||
public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager, ModuleHandler $module_handler, StateInterface $state) {
|
||||
parent::__construct($entity_type, $config_factory, $config_storage, $uuid_service, $language_manager);
|
||||
$this->entityManager = $entity_manager;
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->state = $state;
|
||||
|
@ -79,6 +82,7 @@ class FieldConfigStorage extends ConfigEntityStorage {
|
|||
$container->get('config.factory'),
|
||||
$container->get('config.storage'),
|
||||
$container->get('uuid'),
|
||||
$container->get('language_manager'),
|
||||
$container->get('entity.manager'),
|
||||
$container->get('module_handler'),
|
||||
$container->get('state')
|
||||
|
|
|
@ -12,6 +12,7 @@ use Drupal\Core\Config\Entity\ConfigEntityStorage;
|
|||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\Query\QueryFactory;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Component\Uuid\UuidInterface;
|
||||
|
@ -54,13 +55,15 @@ class FieldInstanceConfigStorage extends ConfigEntityStorage {
|
|||
* The config storage service.
|
||||
* @param \Drupal\Component\Uuid\UuidInterface $uuid_service
|
||||
* The UUID service.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\KeyValueStore\StateInterface $state
|
||||
* The state key value store.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, UuidInterface $uuid_service, EntityManagerInterface $entity_manager, StateInterface $state) {
|
||||
parent::__construct($entity_type, $config_factory, $config_storage, $uuid_service);
|
||||
public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, UuidInterface $uuid_service, LanguageManagerInterface $language_manager, EntityManagerInterface $entity_manager, StateInterface $state) {
|
||||
parent::__construct($entity_type, $config_factory, $config_storage, $uuid_service, $language_manager);
|
||||
$this->entityManager = $entity_manager;
|
||||
$this->state = $state;
|
||||
}
|
||||
|
@ -74,6 +77,7 @@ class FieldInstanceConfigStorage extends ConfigEntityStorage {
|
|||
$container->get('config.factory'),
|
||||
$container->get('config.storage'),
|
||||
$container->get('uuid'),
|
||||
$container->get('language_manager'),
|
||||
$container->get('entity.manager'),
|
||||
$container->get('state')
|
||||
);
|
||||
|
|
|
@ -41,9 +41,10 @@ class FilterCrudTest extends DrupalUnitTestBase {
|
|||
$this->verifyTextFormat($format);
|
||||
|
||||
// Add another text format specifying all possible properties.
|
||||
$format = entity_create('filter_format');
|
||||
$format->format = 'custom_format';
|
||||
$format->name = 'Custom format';
|
||||
$format = entity_create('filter_format', array(
|
||||
'format' => 'custom_format',
|
||||
'name' => 'Custom format',
|
||||
));
|
||||
$format->setFilterConfig('filter_url', array(
|
||||
'status' => 1,
|
||||
'settings' => array(
|
||||
|
|
|
@ -369,6 +369,8 @@ class ConfigEntityBaseUnitTest extends UnitTestCase {
|
|||
$duplicate = $this->entity->createDuplicate();
|
||||
$this->assertInstanceOf('\Drupal\Core\Entity\Entity', $duplicate);
|
||||
$this->assertNotSame($this->entity, $duplicate);
|
||||
$this->assertFalse($this->entity->isNew());
|
||||
$this->assertTrue($duplicate->isNew());
|
||||
$this->assertNull($duplicate->id());
|
||||
$this->assertNull($duplicate->getOriginalId());
|
||||
$this->assertNotEquals($this->entity->uuid(), $duplicate->uuid());
|
||||
|
|
|
@ -0,0 +1,723 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Config\Entity\ConfigEntityStorageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Config\Entity {
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Config\Entity\ConfigEntityStorage
|
||||
*
|
||||
* @group Drupal
|
||||
*/
|
||||
class ConfigEntityStorageTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The entity type.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entityType;
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The UUID service.
|
||||
*
|
||||
* @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $uuidService;
|
||||
|
||||
/**
|
||||
* The language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The config storage controller.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Entity\ConfigEntityStorage
|
||||
*/
|
||||
protected $entityStorage;
|
||||
|
||||
/**
|
||||
* The config factory service.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $configFactory;
|
||||
|
||||
/**
|
||||
* The config storage service.
|
||||
*
|
||||
* @var \Drupal\Core\Config\StorageInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $configStorage;
|
||||
|
||||
/**
|
||||
* The entity query.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\Query\QueryInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entityQuery;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'ConfigEntityStorage unit test',
|
||||
'description' => 'Tests \Drupal\Core\Config\Entity\ConfigEntityStorage',
|
||||
'group' => 'Configuration',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->entityType = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getKey')
|
||||
->will($this->returnValueMap(array(
|
||||
array('id', 'id'),
|
||||
array('uuid', 'uuid'),
|
||||
)));
|
||||
$this->entityType->expects($this->any())
|
||||
->method('id')
|
||||
->will($this->returnValue('test_entity_type'));
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getConfigPrefix')
|
||||
->will($this->returnValue('the_config_prefix'));
|
||||
|
||||
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
|
||||
|
||||
$this->uuidService = $this->getMock('Drupal\Component\Uuid\UuidInterface');
|
||||
|
||||
$this->languageManager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
|
||||
$this->languageManager->expects($this->any())
|
||||
->method('getDefaultLanguage')
|
||||
->will($this->returnValue(new Language(array('langcode' => 'en'))));
|
||||
|
||||
$this->configStorage = $this->getConfigStorageStub(array());
|
||||
|
||||
$this->configFactory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface');
|
||||
|
||||
$this->entityQuery = $this->getMock('Drupal\Core\Entity\Query\QueryInterface');
|
||||
|
||||
$this->entityStorage = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigEntityStorage')
|
||||
->setConstructorArgs(array($this->entityType, $this->configFactory, $this->configStorage, $this->uuidService, $this->languageManager))
|
||||
->setMethods(array('getQuery'))
|
||||
->getMock();
|
||||
$this->entityStorage->expects($this->any())
|
||||
->method('getQuery')
|
||||
->will($this->returnValue($this->entityQuery));
|
||||
$this->entityStorage->setModuleHandler($this->moduleHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create()
|
||||
*/
|
||||
public function testCreateWithPredefinedUuid() {
|
||||
$this->entityType->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->will($this->returnValue(get_class($this->getMockEntity())));
|
||||
|
||||
$this->moduleHandler->expects($this->at(0))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_create');
|
||||
$this->moduleHandler->expects($this->at(1))
|
||||
->method('invokeAll')
|
||||
->with('entity_create');
|
||||
$this->uuidService->expects($this->never())
|
||||
->method('generate');
|
||||
|
||||
$entity = $this->entityStorage->create(array('id' => 'foo', 'uuid' => 'baz'));
|
||||
$this->assertInstanceOf('Drupal\Core\Entity\EntityInterface', $entity);
|
||||
$this->assertSame('foo', $entity->id());
|
||||
$this->assertSame('baz', $entity->uuid());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create()
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface
|
||||
*/
|
||||
public function testCreate() {
|
||||
$this->entityType->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->will($this->returnValue(get_class($this->getMockEntity())));
|
||||
|
||||
$this->moduleHandler->expects($this->at(0))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_create');
|
||||
$this->moduleHandler->expects($this->at(1))
|
||||
->method('invokeAll')
|
||||
->with('entity_create');
|
||||
$this->uuidService->expects($this->once())
|
||||
->method('generate')
|
||||
->will($this->returnValue('bar'));
|
||||
|
||||
$entity = $this->entityStorage->create(array('id' => 'foo'));
|
||||
$this->assertInstanceOf('Drupal\Core\Entity\EntityInterface', $entity);
|
||||
$this->assertSame('foo', $entity->id());
|
||||
$this->assertSame('bar', $entity->uuid());
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save()
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface
|
||||
*
|
||||
* @depends testCreate
|
||||
*/
|
||||
public function testSaveInsert(EntityInterface $entity) {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(TRUE));
|
||||
$config_object->expects($this->exactly(4))
|
||||
->method('set');
|
||||
$config_object->expects($this->once())
|
||||
->method('save');
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('get')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
$this->moduleHandler->expects($this->at(0))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_presave');
|
||||
$this->moduleHandler->expects($this->at(1))
|
||||
->method('invokeAll')
|
||||
->with('entity_presave');
|
||||
$this->moduleHandler->expects($this->at(2))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_insert');
|
||||
$this->moduleHandler->expects($this->at(3))
|
||||
->method('invokeAll')
|
||||
->with('entity_insert');
|
||||
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('condition')
|
||||
->with('uuid', 'bar')
|
||||
->will($this->returnSelf());
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$return = $this->entityStorage->save($entity);
|
||||
$this->assertSame(SAVED_NEW, $return);
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save()
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface
|
||||
*
|
||||
* @depends testSaveInsert
|
||||
*/
|
||||
public function testSaveUpdate(EntityInterface $entity) {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(FALSE));
|
||||
$config_object->expects($this->exactly(4))
|
||||
->method('set');
|
||||
$config_object->expects($this->once())
|
||||
->method('save');
|
||||
|
||||
$this->configFactory->expects($this->exactly(2))
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo'))
|
||||
->will($this->returnValue(array()));
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('get')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
$this->moduleHandler->expects($this->at(0))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_presave');
|
||||
$this->moduleHandler->expects($this->at(1))
|
||||
->method('invokeAll')
|
||||
->with('entity_presave');
|
||||
$this->moduleHandler->expects($this->at(2))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_update');
|
||||
$this->moduleHandler->expects($this->at(3))
|
||||
->method('invokeAll')
|
||||
->with('entity_update');
|
||||
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('condition')
|
||||
->with('uuid', 'bar')
|
||||
->will($this->returnSelf());
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array($entity->id())));
|
||||
|
||||
$return = $this->entityStorage->save($entity);
|
||||
$this->assertSame(SAVED_UPDATED, $return);
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save()
|
||||
*
|
||||
* @depends testSaveInsert
|
||||
*/
|
||||
public function testSaveRename(ConfigEntityInterface $entity) {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(FALSE));
|
||||
$config_object->expects($this->exactly(4))
|
||||
->method('set');
|
||||
$config_object->expects($this->once())
|
||||
->method('save');
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('rename')
|
||||
->will($this->returnValue($config_object));
|
||||
$this->configFactory->expects($this->exactly(2))
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo'))
|
||||
->will($this->returnValue(array()));
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('get')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
// Performing a rename does not change the original ID until saving.
|
||||
$this->assertSame('foo', $entity->getOriginalId());
|
||||
$entity->set('id', 'bar');
|
||||
$this->assertSame('foo', $entity->getOriginalId());
|
||||
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('condition')
|
||||
->with('uuid', 'bar')
|
||||
->will($this->returnSelf());
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array($entity->id())));
|
||||
|
||||
$return = $this->entityStorage->save($entity);
|
||||
$this->assertSame(SAVED_UPDATED, $return);
|
||||
$this->assertSame('bar', $entity->getOriginalId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save()
|
||||
*
|
||||
* @expectedException \Drupal\Core\Entity\EntityMalformedException
|
||||
* @expectedExceptionMessage The entity does not have an ID.
|
||||
*/
|
||||
public function testSaveInvalid() {
|
||||
$entity = $this->getMockEntity();
|
||||
$this->entityStorage->save($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save()
|
||||
*
|
||||
* @expectedException \Drupal\Core\Entity\EntityStorageException
|
||||
*/
|
||||
public function testSaveDuplicate() {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(FALSE));
|
||||
$config_object->expects($this->never())
|
||||
->method('set');
|
||||
$config_object->expects($this->never())
|
||||
->method('save');
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('get')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
$entity = $this->getMockEntity(array('id' => 'foo'));
|
||||
$entity->enforceIsNew();
|
||||
|
||||
$this->entityStorage->save($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save()
|
||||
*
|
||||
* @expectedException \Drupal\Core\Config\ConfigDuplicateUUIDException
|
||||
* @expectedExceptionMessage when this UUID is already used for
|
||||
*/
|
||||
public function testSaveMismatch() {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(TRUE));
|
||||
$config_object->expects($this->never())
|
||||
->method('save');
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('get')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('condition')
|
||||
->will($this->returnSelf());
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array('baz')));
|
||||
|
||||
$entity = $this->getMockEntity(array('id' => 'foo'));
|
||||
$this->entityStorage->save($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save()
|
||||
*/
|
||||
public function testSaveNoMismatch() {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(TRUE));
|
||||
$config_object->expects($this->once())
|
||||
->method('save');
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('get')
|
||||
->with('the_config_prefix.baz')
|
||||
->will($this->returnValue($config_object));
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('rename')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('condition')
|
||||
->will($this->returnSelf());
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array('baz')));
|
||||
|
||||
$entity = $this->getMockEntity(array('id' => 'foo'));
|
||||
$entity->enforceIsNew();
|
||||
$entity->setOriginalId('baz');
|
||||
$this->entityStorage->save($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::save()
|
||||
*
|
||||
* @expectedException \Drupal\Core\Config\ConfigDuplicateUUIDException
|
||||
* @expectedExceptionMessage when this entity already exists with UUID
|
||||
*/
|
||||
public function testSaveChangedUuid() {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->atLeastOnce())
|
||||
->method('isNew')
|
||||
->will($this->returnValue(FALSE));
|
||||
$config_object->expects($this->never())
|
||||
->method('save');
|
||||
$config_object->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->will($this->returnValueMap(array(
|
||||
array('', array('id' => 'foo')),
|
||||
array('id', 'foo'),
|
||||
)));
|
||||
|
||||
$this->configFactory->expects($this->at(1))
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo'))
|
||||
->will($this->returnValue(array()));
|
||||
$this->configFactory->expects($this->at(2))
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo'))
|
||||
->will($this->returnValue(array($config_object)));
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('get')
|
||||
->with('the_config_prefix.foo')
|
||||
->will($this->returnValue($config_object));
|
||||
$this->configFactory->expects($this->never())
|
||||
->method('rename')
|
||||
->will($this->returnValue($config_object));
|
||||
|
||||
$this->moduleHandler->expects($this->exactly(2))
|
||||
->method('getImplementations')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('condition')
|
||||
->will($this->returnSelf());
|
||||
$this->entityQuery->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(array('foo')));
|
||||
|
||||
$entity = $this->getMockEntity(array('id' => 'foo'));
|
||||
$this->entityType->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->will($this->returnValue(get_class($entity)));
|
||||
|
||||
$entity->set('uuid', 'baz');
|
||||
$this->entityStorage->save($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::load()
|
||||
* @covers ::postLoad()
|
||||
* @covers ::buildQuery()
|
||||
*/
|
||||
public function testLoad() {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->will($this->returnValueMap(array(
|
||||
array('', array('id' => 'foo')),
|
||||
array('id', 'foo'),
|
||||
)));
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo'))
|
||||
->will($this->returnValue(array($config_object)));
|
||||
$this->moduleHandler->expects($this->exactly(2))
|
||||
->method('getImplementations')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$this->entityType->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->will($this->returnValue(get_class($this->getMockEntity())));
|
||||
|
||||
$entity = $this->entityStorage->load('foo');
|
||||
$this->assertInstanceOf('Drupal\Core\Entity\EntityInterface', $entity);
|
||||
$this->assertSame('foo', $entity->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::loadMultiple()
|
||||
* @covers ::postLoad()
|
||||
* @covers ::buildQuery()
|
||||
*/
|
||||
public function testLoadMultipleAll() {
|
||||
$foo_config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$foo_config_object->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->will($this->returnValueMap(array(
|
||||
array('', array('id' => 'foo')),
|
||||
array('id', 'foo'),
|
||||
)));
|
||||
$bar_config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$bar_config_object->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->will($this->returnValueMap(array(
|
||||
array('', array('id' => 'bar')),
|
||||
array('id', 'bar'),
|
||||
)));
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('loadMultiple')
|
||||
->with(array())
|
||||
->will($this->returnValue(array($foo_config_object, $bar_config_object)));
|
||||
$this->moduleHandler->expects($this->exactly(2))
|
||||
->method('getImplementations')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$this->entityType->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->will($this->returnValue(get_class($this->getMockEntity())));
|
||||
|
||||
$entities = $this->entityStorage->loadMultiple();
|
||||
$expected['foo'] = 'foo';
|
||||
$expected['bar'] = 'bar';
|
||||
foreach ($entities as $id => $entity) {
|
||||
$this->assertInstanceOf('Drupal\Core\Entity\EntityInterface', $entity);
|
||||
$this->assertSame($id, $entity->id());
|
||||
$this->assertSame($expected[$id], $entity->id());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::loadMultiple()
|
||||
* @covers ::postLoad()
|
||||
* @covers ::buildQuery()
|
||||
*/
|
||||
public function testLoadMultipleIds() {
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->will($this->returnValueMap(array(
|
||||
array('', array('id' => 'foo')),
|
||||
array('id', 'foo'),
|
||||
)));
|
||||
|
||||
$this->configFactory->expects($this->once())
|
||||
->method('loadMultiple')
|
||||
->with(array('the_config_prefix.foo'))
|
||||
->will($this->returnValue(array($config_object)));
|
||||
$this->moduleHandler->expects($this->exactly(2))
|
||||
->method('getImplementations')
|
||||
->will($this->returnValue(array()));
|
||||
$this->entityType->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->will($this->returnValue(get_class($this->getMockEntity())));
|
||||
|
||||
$entities = $this->entityStorage->loadMultiple(array('foo'));
|
||||
foreach ($entities as $id => $entity) {
|
||||
$this->assertInstanceOf('Drupal\Core\Entity\EntityInterface', $entity);
|
||||
$this->assertSame($id, $entity->id());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::loadRevision()
|
||||
*/
|
||||
public function testLoadRevision() {
|
||||
$this->assertSame(FALSE, $this->entityStorage->loadRevision(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::deleteRevision()
|
||||
*/
|
||||
public function testDeleteRevision() {
|
||||
$this->assertSame(NULL, $this->entityStorage->deleteRevision(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::delete()
|
||||
*/
|
||||
public function testDelete() {
|
||||
$this->entityType->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->will($this->returnValue(get_class($this->getMockEntity())));
|
||||
|
||||
$entities = array();
|
||||
$configs = array();
|
||||
$config_map = array();
|
||||
foreach (array('foo', 'bar') as $id) {
|
||||
$entity = $this->getMockEntity(array('id' => $id));
|
||||
$entities[] = $entity;
|
||||
$config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$config_object->expects($this->once())
|
||||
->method('delete');
|
||||
$configs[] = $config_object;
|
||||
$config_map[] = array("the_config_prefix.$id", $config_object);
|
||||
}
|
||||
|
||||
$this->configFactory->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->will($this->returnValueMap($config_map));
|
||||
|
||||
$this->moduleHandler->expects($this->at(0))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_predelete');
|
||||
$this->moduleHandler->expects($this->at(1))
|
||||
->method('invokeAll')
|
||||
->with('entity_predelete');
|
||||
$this->moduleHandler->expects($this->at(2))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_predelete');
|
||||
$this->moduleHandler->expects($this->at(3))
|
||||
->method('invokeAll')
|
||||
->with('entity_predelete');
|
||||
$this->moduleHandler->expects($this->at(4))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_delete');
|
||||
$this->moduleHandler->expects($this->at(5))
|
||||
->method('invokeAll')
|
||||
->with('entity_delete');
|
||||
$this->moduleHandler->expects($this->at(6))
|
||||
->method('invokeAll')
|
||||
->with('test_entity_type_delete');
|
||||
$this->moduleHandler->expects($this->at(7))
|
||||
->method('invokeAll')
|
||||
->with('entity_delete');
|
||||
|
||||
$this->entityStorage->delete($entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::delete()
|
||||
*/
|
||||
public function testDeleteNothing() {
|
||||
$this->moduleHandler->expects($this->never())
|
||||
->method($this->anything());
|
||||
$this->configFactory->expects($this->never())
|
||||
->method('get');
|
||||
|
||||
$this->entityStorage->delete(array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an entity with specific methods mocked.
|
||||
*
|
||||
* @param array $values
|
||||
* (optional) Values to pass to the constructor.
|
||||
* @param array $methods
|
||||
* (optional) The methods to mock.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
public function getMockEntity(array $values = array(), $methods = array()) {
|
||||
$methods[] = 'onSaveOrDelete';
|
||||
$methods[] = 'onUpdateBundleEntity';
|
||||
return $this->getMockForAbstractClass('Drupal\Core\Config\Entity\ConfigEntityBase', array($values, 'test_entity_type'), '', TRUE, TRUE, TRUE, $methods);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
namespace {
|
||||
if (!defined('SAVED_NEW')) {
|
||||
define('SAVED_NEW', 1);
|
||||
}
|
||||
if (!defined('SAVED_UPDATED')) {
|
||||
define('SAVED_UPDATED', 2);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue