summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2014-03-21 11:53:32 (GMT)
committerNathaniel Catchpole2014-03-21 11:53:32 (GMT)
commit8cbab1493bc6bd5b763bec5cc0590fad575d8b14 (patch)
tree0185ebcc5cb5a2fd2362685029fa079529768f4b
parent5f61e2663aa9cd21c75ec65501371036295bbef6 (diff)
Issue #2080823 by alexpott, swentel, Wim Leers: Create API to discover content or config entities' soft dependencies and use this to present a confirm form on module uninstall.
-rw-r--r--core/core.services.yml2
-rw-r--r--core/lib/Drupal/Core/Config/ConfigInstaller.php45
-rw-r--r--core/lib/Drupal/Core/Config/ConfigManager.php74
-rw-r--r--core/lib/Drupal/Core/Config/ConfigManagerInterface.php31
-rw-r--r--core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php207
-rw-r--r--core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php104
-rw-r--r--core/lib/Drupal/Core/Config/Entity/ConfigEntityDependency.php101
-rw-r--r--core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php35
-rw-r--r--core/lib/Drupal/Core/Config/Schema/core.data_types.schema.yml21
-rw-r--r--core/lib/Drupal/Core/Extension/ModuleHandler.php9
-rw-r--r--core/modules/aggregator/config/views.view.aggregator_rss_feed.yml5
-rw-r--r--core/modules/block/config/schema/block.schema.yml3
-rw-r--r--core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml3
-rw-r--r--core/modules/block/lib/Drupal/block/Entity/Block.php10
-rw-r--r--core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php1
-rw-r--r--core/modules/block/tests/Drupal/block/Tests/BlockConfigEntityUnitTest.php121
-rw-r--r--core/modules/block/tests/modules/block_test/config/block.block.test_block.yml5
-rw-r--r--core/modules/book/config/entity.view_mode.node.print.yml3
-rw-r--r--core/modules/breakpoint/breakpoint.module100
-rw-r--r--core/modules/breakpoint/config/schema/breakpoint.schema.yml6
-rw-r--r--core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointGroupInterface.php4
-rw-r--r--core/modules/breakpoint/lib/Drupal/breakpoint/Entity/Breakpoint.php17
-rw-r--r--core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php25
-rw-r--r--core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php8
-rw-r--r--core/modules/breakpoint/tests/Drupal/breakpoint/Tests/BreakpointConfigEntityUnitTest.php124
-rw-r--r--core/modules/breakpoint/tests/Drupal/breakpoint/Tests/BreakpointGroupConfigEntityUnitTest.php158
-rw-r--r--core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php14
-rw-r--r--core/modules/comment/config/entity.view_mode.comment.full.yml3
-rw-r--r--core/modules/comment/config/system.action.comment_publish_action.yml3
-rw-r--r--core/modules/comment/config/system.action.comment_save_action.yml3
-rw-r--r--core/modules/comment/config/system.action.comment_unpublish_action.yml3
-rw-r--r--core/modules/comment/config/views.view.comments_recent.yml3
-rw-r--r--core/modules/comment/lib/Drupal/comment/Tests/Views/CommentTestBase.php1
-rw-r--r--core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php12
-rw-r--r--core/modules/config/lib/Drupal/config/Tests/ConfigDependencyTest.php170
-rw-r--r--core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php2
-rw-r--r--core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php2
-rw-r--r--core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php12
-rw-r--r--core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php19
-rw-r--r--core/modules/config/tests/config_test/lib/Drupal/config_test/TestInstallStorage.php2
-rw-r--r--core/modules/editor/config/schema/editor.schema.yml3
-rw-r--r--core/modules/editor/lib/Drupal/editor/Entity/Editor.php35
-rw-r--r--core/modules/editor/tests/Drupal/editor/Tests/EditorConfigEntityUnitTest.php171
-rw-r--r--core/modules/entity/config/schema/entity.schema.yml12
-rw-r--r--core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php39
-rw-r--r--core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php10
-rw-r--r--core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php34
-rw-r--r--core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php1
-rw-r--r--core/modules/field/config/schema/field.schema.yml6
-rw-r--r--core/modules/field/lib/Drupal/field/Entity/FieldConfig.php20
-rw-r--r--core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php22
-rw-r--r--core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php1
-rw-r--r--core/modules/field/tests/Drupal/field/Tests/FieldConfigEntityUnitTest.php97
-rw-r--r--core/modules/field/tests/Drupal/field/Tests/FieldInstanceConfigEntityUnitTest.php120
-rw-r--r--core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import.yml3
-rw-r--r--core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import_2.yml3
-rw-r--r--core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging.yml3
-rw-r--r--core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging_2.yml3
-rw-r--r--core/modules/file/config/views.view.files.yml3
-rw-r--r--core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml3
-rw-r--r--core/modules/forum/config/entity.view_display.taxonomy_term.forums.default.yml3
-rw-r--r--core/modules/forum/config/field.field.forum.forum_container.yml3
-rw-r--r--core/modules/forum/config/field.instance.taxonomy_term.forums.forum_container.yml3
-rw-r--r--core/modules/forum/config/rdf.mapping.node.forum.yml5
-rw-r--r--core/modules/forum/config/rdf.mapping.taxonomy_term.forums.yml5
-rw-r--r--core/modules/language/lib/Drupal/language/Entity/Language.php2
-rw-r--r--core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php2
-rw-r--r--core/modules/node/config/entity.view_mode.node.full.yml3
-rw-r--r--core/modules/node/config/entity.view_mode.node.rss.yml3
-rw-r--r--core/modules/node/config/entity.view_mode.node.search_index.yml (renamed from core/modules/search/config/entity.view_mode.node.search_index.yml)3
-rw-r--r--core/modules/node/config/entity.view_mode.node.search_result.yml (renamed from core/modules/search/config/entity.view_mode.node.search_result.yml)3
-rw-r--r--core/modules/node/config/entity.view_mode.node.teaser.yml3
-rw-r--r--core/modules/node/config/search.page.node_search.yml3
-rw-r--r--core/modules/node/config/system.action.node_delete_action.yml3
-rw-r--r--core/modules/node/config/system.action.node_make_sticky_action.yml3
-rw-r--r--core/modules/node/config/system.action.node_make_unsticky_action.yml3
-rw-r--r--core/modules/node/config/system.action.node_save_action.yml3
-rw-r--r--core/modules/node/config/system.action.node_unpromote_action.yml3
-rw-r--r--core/modules/node/config/system.action.node_unpublish_action.yml3
-rw-r--r--core/modules/node/config/views.view.archive.yml (renamed from core/modules/views/config/views.view.archive.yml)3
-rw-r--r--core/modules/node/config/views.view.content.yml5
-rw-r--r--core/modules/node/config/views.view.content_recent.yml7
-rw-r--r--core/modules/node/config/views.view.frontpage.yml3
-rw-r--r--core/modules/node/config/views.view.glossary.yml (renamed from core/modules/views/config/views.view.glossary.yml)4
-rw-r--r--core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php1
-rw-r--r--core/modules/node/node.module18
-rw-r--r--core/modules/rdf/config/schema/rdf.schema.yml3
-rw-r--r--core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php21
-rw-r--r--core/modules/rdf/lib/Drupal/rdf/Tests/Field/EmailFieldRdfaTest.php2
-rw-r--r--core/modules/rdf/lib/Drupal/rdf/Tests/RdfaAttributesTest.php14
-rw-r--r--core/modules/rdf/tests/Drupal/rdf/Tests/RdfMappingConfigEntityUnitTest.php162
-rw-r--r--core/modules/responsive_image/config/schema/responsive_image.schema.yml3
-rw-r--r--core/modules/responsive_image/lib/Drupal/responsive_image/Entity/ResponsiveImageMapping.php15
-rw-r--r--core/modules/responsive_image/tests/Drupal/responsive_image/Tests/PictureMappingEntityTest.php137
-rw-r--r--core/modules/search/config/schema/search.schema.yml3
-rw-r--r--core/modules/system/config/schema/system.schema.yml3
-rw-r--r--core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php69
-rw-r--r--core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php2
-rw-r--r--core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php7
-rw-r--r--core/modules/system/lib/Drupal/system/Tests/Form/RebuildTest.php2
-rw-r--r--core/modules/system/lib/Drupal/system/Tests/Module/ModuleTestBase.php2
-rw-r--r--core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php37
-rw-r--r--core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.full.yml3
-rw-r--r--core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.test.yml3
-rw-r--r--core/modules/system/tests/modules/entity_test/entity_test.install2
-rw-r--r--core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml3
-rw-r--r--core/modules/taxonomy/config/views.view.taxonomy_term.yml (renamed from core/modules/views/config/views.view.taxonomy_term.yml)4
-rw-r--r--core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php2
-rw-r--r--core/modules/tour/config/schema/tour.schema.yml3
-rw-r--r--core/modules/tour/lib/Drupal/tour/Entity/Tour.php16
-rw-r--r--core/modules/tour/lib/Drupal/tour/Tests/TourTest.php21
-rw-r--r--core/modules/tracker/lib/Drupal/tracker/Tests/TrackerNodeAccessTest.php1
-rw-r--r--core/modules/user/config/entity.form_mode.user.register.yml3
-rw-r--r--core/modules/user/config/entity.view_mode.user.compact.yml3
-rw-r--r--core/modules/user/config/entity.view_mode.user.full.yml3
-rw-r--r--core/modules/user/config/rdf.mapping.user.user.yml3
-rw-r--r--core/modules/user/config/search.page.user_search.yml3
-rw-r--r--core/modules/user/config/system.action.user_block_user_action.yml3
-rw-r--r--core/modules/user/config/system.action.user_cancel_user_action.yml3
-rw-r--r--core/modules/user/config/system.action.user_unblock_user_action.yml3
-rw-r--r--core/modules/user/config/views.view.user_admin_people.yml5
-rw-r--r--core/modules/user/config/views.view.who_s_new.yml5
-rw-r--r--core/modules/user/config/views.view.who_s_online.yml5
-rw-r--r--core/modules/views/config/schema/views.schema.yml3
-rw-r--r--core/modules/views/lib/Drupal/views/Entity/View.php35
-rw-r--r--core/modules/views/lib/Drupal/views/Tests/Entity/FieldEntityTest.php1
-rw-r--r--core/modules/views/lib/Drupal/views/Tests/Entity/ViewEntityDependenciesTest.php76
-rw-r--r--core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php1
-rw-r--r--core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php1
-rw-r--r--core/modules/views/lib/Drupal/views/Tests/ModuleTest.php1
-rw-r--r--core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php4
-rw-r--r--core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php11
-rw-r--r--core/modules/views/lib/Drupal/views/ViewExecutable.php12
-rw-r--r--core/modules/views/lib/Drupal/views/ViewStorageController.php33
-rw-r--r--core/modules/views/tests/Drupal/views/Tests/EventSubscriber/RouteSubscriberTest.php2
-rw-r--r--core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php2
-rw-r--r--core/modules/views/tests/Drupal/views/Tests/Routing/ViewPageControllerTest.php2
-rw-r--r--core/modules/views/tests/Drupal/views/Tests/ViewsTest.php2
-rw-r--r--core/modules/views_ui/config/tour.tour.views-ui.yml3
-rw-r--r--core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php33
-rw-r--r--core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php2
-rw-r--r--core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUIObjectTest.php6
-rw-r--r--core/profiles/minimal/config/block.block.stark_admin.yml5
-rw-r--r--core/profiles/minimal/config/block.block.stark_login.yml5
-rw-r--r--core/profiles/minimal/config/block.block.stark_tools.yml5
-rw-r--r--core/profiles/standard/config/block.block.bartik_breadcrumbs.yml5
-rw-r--r--core/profiles/standard/config/block.block.bartik_content.yml5
-rw-r--r--core/profiles/standard/config/block.block.bartik_footer.yml5
-rw-r--r--core/profiles/standard/config/block.block.bartik_help.yml5
-rw-r--r--core/profiles/standard/config/block.block.bartik_login.yml5
-rw-r--r--core/profiles/standard/config/block.block.bartik_powered.yml5
-rw-r--r--core/profiles/standard/config/block.block.bartik_search.yml5
-rw-r--r--core/profiles/standard/config/block.block.bartik_tools.yml5
-rw-r--r--core/profiles/standard/config/block.block.seven_breadcrumbs.yml5
-rw-r--r--core/profiles/standard/config/block.block.seven_content.yml5
-rw-r--r--core/profiles/standard/config/block.block.seven_help.yml5
-rw-r--r--core/profiles/standard/config/block.block.seven_login.yml5
-rw-r--r--core/profiles/standard/config/editor.editor.basic_html.yml5
-rw-r--r--core/profiles/standard/config/editor.editor.full_html.yml5
-rw-r--r--core/profiles/standard/config/entity.form_display.node.article.default.yml36
-rw-r--r--core/profiles/standard/config/entity.form_display.user.user.default.yml3
-rw-r--r--core/profiles/standard/config/entity.view_display.node.article.default.yml11
-rw-r--r--core/profiles/standard/config/entity.view_display.node.article.teaser.yml11
-rw-r--r--core/profiles/standard/config/entity.view_display.user.user.compact.yml5
-rw-r--r--core/profiles/standard/config/entity.view_display.user.user.default.yml3
-rw-r--r--core/profiles/standard/config/field.field.node.field_image.yml3
-rw-r--r--core/profiles/standard/config/field.field.node.field_tags.yml3
-rw-r--r--core/profiles/standard/config/field.field.user.user_picture.yml3
-rw-r--r--core/profiles/standard/config/field.instance.node.article.field_image.yml3
-rw-r--r--core/profiles/standard/config/field.instance.node.article.field_tags.yml3
-rw-r--r--core/profiles/standard/config/field.instance.user.user.user_picture.yml3
-rw-r--r--core/profiles/standard/config/rdf.mapping.comment.node__comment.yml3
-rw-r--r--core/profiles/standard/config/rdf.mapping.node.article.yml5
-rw-r--r--core/profiles/standard/config/rdf.mapping.node.page.yml5
-rw-r--r--core/profiles/standard/config/rdf.mapping.taxonomy_term.tags.yml5
-rw-r--r--core/tests/Drupal/Tests/Core/Config/Entity/ConfigDependencyManagerTest.php44
-rw-r--r--core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php264
-rw-r--r--core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityDependencyTest.php61
-rw-r--r--core/tests/Drupal/Tests/Core/Config/Entity/EntityDisplayModeBaseUnitTest.php120
-rw-r--r--core/tests/Drupal/Tests/Core/Config/Entity/Fixtures/ConfigEntityBaseWithPluginBag.php20
180 files changed, 3415 insertions, 253 deletions
diff --git a/core/core.services.yml b/core/core.services.yml
index e6ab523..97de70a 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -69,7 +69,7 @@ services:
factory_method: getActive
config.manager:
class: Drupal\Core\Config\ConfigManager
- arguments: ['@entity.manager', '@config.factory', '@config.typed', '@string_translation']
+ arguments: ['@entity.manager', '@config.factory', '@config.typed', '@string_translation', '@config.storage']
config.storage:
class: Drupal\Core\Config\CachedStorage
arguments: ['@config.cachedstorage.storage', '@cache.config']
diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
index 2bb06b3..b039b8f 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -8,6 +8,7 @@
namespace Drupal\Core\Config;
use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Config\Entity\ConfigDependencyManager;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class ConfigInstaller implements ConfigInstallerInterface {
@@ -105,25 +106,43 @@ class ConfigInstaller implements ConfigInstallerInterface {
}
if (!empty($config_to_install)) {
+ // Order the configuration to install in the order of dependencies.
+ $data = $source_storage->readMultiple($config_to_install);
+ $dependency_manager = new ConfigDependencyManager();
+ $sorted_config = $dependency_manager
+ ->setData($data)
+ ->sortAll();
+
$old_state = $this->configFactory->getOverrideState();
$this->configFactory->setOverrideState(FALSE);
- foreach ($config_to_install as $name) {
- // Only import new config.
- if ($this->activeStorage->exists($name)) {
- continue;
- }
+ // Remove configuration that already exists in the active storage.
+ $sorted_config = array_diff($sorted_config, $this->activeStorage->listAll());
+
+ foreach ($sorted_config as $name) {
$new_config = new Config($name, $this->activeStorage, $this->eventDispatcher, $this->typedConfig);
- $data = $source_storage->read($name);
- if ($data !== FALSE) {
- $new_config->setData($data);
+ if ($data[$name] !== FALSE) {
+ $new_config->setData($data[$name]);
}
if ($entity_type = $this->configManager->getEntityTypeIdByName($name)) {
- $this->configManager
+ $entity_storage = $this->configManager
->getEntityManager()
- ->getStorageController($entity_type)
- ->create($new_config->get())
- ->save();
+ ->getStorageController($entity_type);
+ // It is possible that secondary writes can occur during configuration
+ // creation. Updates of such configuration are allowed.
+ if ($this->activeStorage->exists($name)) {
+ $id = $entity_storage->getIDFromConfigName($name, $entity_storage->getEntityType()->getConfigPrefix());
+ $entity = $entity_storage->load($id);
+ foreach ($new_config->get() as $property => $value) {
+ $entity->set($property, $value);
+ }
+ $entity->save();
+ }
+ else {
+ $entity_storage
+ ->create($new_config->get())
+ ->save();
+ }
}
else {
$new_config->save();
@@ -131,6 +150,8 @@ class ConfigInstaller implements ConfigInstallerInterface {
}
$this->configFactory->setOverrideState($old_state);
}
+ // Reset all the static caches and list caches.
+ $this->configFactory->reset();
}
}
diff --git a/core/lib/Drupal/Core/Config/ConfigManager.php b/core/lib/Drupal/Core/Config/ConfigManager.php
index d52e806..418b912 100644
--- a/core/lib/Drupal/Core/Config/ConfigManager.php
+++ b/core/lib/Drupal/Core/Config/ConfigManager.php
@@ -7,6 +7,7 @@
namespace Drupal\Core\Config;
+use Drupal\Core\Config\Entity\ConfigDependencyManager;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\StringTranslation\TranslationManager;
@@ -46,6 +47,13 @@ class ConfigManager implements ConfigManagerInterface {
protected $stringTranslation;
/**
+ * The active configuration storage.
+ *
+ * @var \Drupal\Core\Config\StorageInterface
+ */
+ protected $activeStorage;
+
+ /**
* Creates ConfigManager objects.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
@@ -57,11 +65,12 @@ class ConfigManager implements ConfigManagerInterface {
* @param \Drupal\Core\StringTranslation\TranslationManager $string_translation
* The string translation service.
*/
- public function __construct(EntityManagerInterface $entity_manager, ConfigFactoryInterface $config_factory, TypedConfigManager $typed_config_manager, TranslationManager $string_translation) {
+ public function __construct(EntityManagerInterface $entity_manager, ConfigFactoryInterface $config_factory, TypedConfigManager $typed_config_manager, TranslationManager $string_translation, StorageInterface $active_storage) {
$this->entityManager = $entity_manager;
$this->configFactory = $config_factory;
$this->typedConfigManager = $typed_config_manager;
$this->stringTranslation = $string_translation;
+ $this->activeStorage = $active_storage;
}
/**
@@ -125,6 +134,17 @@ class ConfigManager implements ConfigManagerInterface {
* {@inheritdoc}
*/
public function uninstall($type, $name) {
+ // Remove all dependent configuration entities.
+ $dependent_entities = $this->findConfigEntityDependentsAsEntities($type, array($name));
+
+ // Reverse the array to that entities are removed in the correct order of
+ // dependence. For example, this ensures that field instances are removed
+ // before fields.
+ foreach (array_reverse($dependent_entities) as $entity) {
+ $entity->setUninstalling(TRUE);
+ $entity->delete();
+ }
+
$config_names = $this->configFactory->listAll($name . '.');
foreach ($config_names as $config_name) {
$this->configFactory->get($config_name)->delete();
@@ -137,4 +157,56 @@ class ConfigManager implements ConfigManagerInterface {
}
}
+ /**
+ * {@inheritdoc}
+ */
+ public function findConfigEntityDependents($type, array $names) {
+ $dependency_manager = new ConfigDependencyManager();
+ // This uses the configuration storage directly to avoid blowing the static
+ // caches in the configuration factory and the configuration entity system.
+ // Additionally this ensures that configuration entity dependency discovery
+ // has no dependencies on the config entity classes. Assume data with UUID
+ // is a config entity. Only configuration entities can be depended on so we
+ // can ignore everything else.
+ $data = array_filter($this->activeStorage->readMultiple($this->activeStorage->listAll()), function($config) {
+ return isset($config['uuid']);
+ });
+ $dependency_manager->setData($data);
+ $dependencies = array();
+ foreach ($names as $name) {
+ $dependencies = array_merge($dependencies, $dependency_manager->getDependentEntities($type, $name));
+ }
+ return $dependencies;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function findConfigEntityDependentsAsEntities($type, array $names) {
+ $dependencies = $this->findConfigEntityDependents($type, $names);
+ $entities = array();
+ $definitions = $this->entityManager->getDefinitions();
+ foreach ($dependencies as $config_name => $dependency) {
+ // Group by entity type to efficient load entities using
+ // \Drupal\Core\Entity\EntityStorageControllerInterface::loadMultiple().
+ $entity_type_id = $this->getEntityTypeIdByName($config_name);
+ // It is possible that a non-configuration entity will be returned if a
+ // simple configuration object has a UUID key. This would occur if the
+ // dependents of the system module are calculated since system.site has
+ // a UUID key.
+ if ($entity_type_id) {
+ $id = substr($config_name, strlen($definitions[$entity_type_id]->getConfigPrefix()) + 1);
+ $entities[$entity_type_id][] = $id;
+ }
+ }
+ $entities_to_return = array();
+ foreach ($entities as $entity_type_id => $entities_to_load) {
+ $storage_controller = $this->entityManager->getStorageController($entity_type_id);
+ // Remove the keys since there are potential ID clashes from different
+ // configuration entity types.
+ $entities_to_return = array_merge($entities_to_return, array_values($storage_controller->loadMultiple($entities_to_load)));
+ }
+ return $entities_to_return;
+ }
+
}
diff --git a/core/lib/Drupal/Core/Config/ConfigManagerInterface.php b/core/lib/Drupal/Core/Config/ConfigManagerInterface.php
index d78b358..b5084fe 100644
--- a/core/lib/Drupal/Core/Config/ConfigManagerInterface.php
+++ b/core/lib/Drupal/Core/Config/ConfigManagerInterface.php
@@ -68,4 +68,35 @@ interface ConfigManagerInterface {
*/
public function uninstall($type, $name);
+ /**
+ * Finds config entities that are dependent on extensions or entities.
+ *
+ * @param string $type
+ * The type of dependency being checked. Either 'module', 'theme', 'entity'.
+ * @param array $names
+ * The specific names to check. If $type equals 'module' or 'theme' then it
+ * should be a list of module names or theme names. In the case of entity it
+ * should be a list of full configuration object names.
+ *
+ * @return \Drupal\Core\Config\Entity\ConfigEntityDependency[]
+ * An array of configuration entity dependency objects.
+ */
+ public function findConfigEntityDependents($type, array $names);
+
+ /**
+ * Finds config entities that are dependent on extensions or entities.
+ *
+ * @param string $type
+ * The type of dependency being checked. Either 'module', 'theme', 'entity'.
+ * @param array $names
+ * The specific names to check. If $type equals 'module' or 'theme' then it
+ * should be a list of module names or theme names. In the case of entity it
+ * should be a list of full configuration object names.
+ *
+ * @return \Drupal\Core\Config\Entity\ConfigEntityInterface[]
+ * An array of dependencies as configuration entities.
+ */
+ public function findConfigEntityDependentsAsEntities($type, array $names);
+
+
}
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php
new file mode 100644
index 0000000..d028e05
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php
@@ -0,0 +1,207 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Config\Entity\ConfigDependencyManager.
+ */
+
+namespace Drupal\Core\Config\Entity;
+
+use Drupal\Component\Graph\Graph;
+use Drupal\Component\Utility\SortArray;
+
+/**
+ * Provides a class to discover configuration entity dependencies.
+ *
+ * Configuration entities can depend on modules, themes and other configuration
+ * entities. The dependency system is used during configuration installation to
+ * ensure that configuration entities are imported in the correct order. For
+ * example, node types are created before their fields and the fields are
+ * created before their field instances.
+ *
+ * Dependencies are stored to the configuration entity's configuration object so
+ * that they can be checked without the module that provides the configuration
+ * entity class being installed. This is important for configuration
+ * synchronization which needs to be able to validate configuration in the
+ * staging directory before the synchronization has occurred.
+ *
+ * Configuration entities determine their dependencies by implementing
+ * \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies().
+ * This method should be called from the configuration entity's implementation
+ * of \Drupal\Core\Entity\EntityInterface::preSave(). Implementations should use
+ * the helper method
+ * \Drupal\Core\Config\Entity\ConfigEntityBase::addDependency() to add
+ * dependencies. All the implementations in core call the parent method
+ * \Drupal\Core\Config\Entity\ConfigEntityBase::calculateDependencies() which
+ * resets the dependencies and provides an implementation to determine the
+ * plugin providers for configuration entities that implement
+ * \Drupal\Core\Config\Entity\EntityWithPluginBagInterface.
+ *
+ * The configuration manager service provides methods to find dependencies for
+ * a specified module, theme or configuration entity.
+ *
+ * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies()
+ * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::getConfigDependencyName()
+ * @see \Drupal\Core\Config\Entity\ConfigEntityBase::addDependency()
+ * @see \Drupal\Core\Config\ConfigInstaller::installDefaultConfig()
+ * @see \Drupal\Core\Config\Entity\ConfigEntityDependency
+ */
+class ConfigDependencyManager {
+
+ /**
+ * The config entity data.
+ *
+ * @var \Drupal\Core\Config\Entity\ConfigEntityDependency[]
+ */
+ protected $data = array();
+
+ /**
+ * The directed acyclic graph.
+ *
+ * @var array
+ */
+ protected $graph;
+
+ /**
+ * Gets dependencies.
+ *
+ * @param string $type
+ * The type of dependency being checked. Either 'module', 'theme', 'entity'.
+ * @param string $name
+ * The specific name to check. If $type equals 'module' or 'theme' then it
+ * should be a module name or theme name. In the case of entity it should be
+ * the full configuration object name.
+ *
+ * @return \Drupal\Core\Config\Entity\ConfigEntityDependency[]
+ * An array of config entity dependency objects that are dependent.
+ */
+ public function getDependentEntities($type, $name) {
+ $dependent_entities = array();
+
+ $entities_to_check = array();
+ if ($type == 'entity') {
+ $entities_to_check[] = $name;
+ }
+ else {
+ if ($type == 'module' || $type == 'theme') {
+ $dependent_entities = array_filter($this->data, function (ConfigEntityDependency $entity) use ($type, $name) {
+ return $entity->hasDependency($type, $name);
+ });
+ }
+ // If checking module or theme dependencies then discover which entities
+ // are dependent on the entities that have a direct dependency.
+ foreach ($dependent_entities as $entity) {
+ $entities_to_check[] = $entity->getConfigDependencyName();
+ }
+ }
+
+ return array_merge($dependent_entities, $this->createGraphConfigEntityDependencies($entities_to_check));
+ }
+
+ /**
+ * Sorts the dependencies in order of most dependent last.
+ *
+ * @return array
+ * The list of entities in order of most dependent last, otherwise
+ * alphabetical.
+ */
+ public function sortAll() {
+ $graph = $this->getGraph();
+ // Sort by reverse weight and alphabetically. The most dependent entities
+ // are last and entities with the same weight are alphabetically ordered.
+ uasort($graph, array($this, 'sortGraph'));
+ return array_keys($graph);
+ }
+
+ /**
+ * Sorts the dependency graph by reverse weight and alphabetically.
+ *
+ * @param array $a
+ * First item for comparison. The compared items should be associative
+ * arrays that include a 'weight' and a 'component' key.
+ * @param array $b
+ * Second item for comparison.
+ *
+ * @return int
+ * The comparison result for uasort().
+ */
+ public function sortGraph(array $a, array $b) {
+ $weight_cmp = SortArray::sortByKeyInt($a, $b, 'weight') * -1;
+
+ if ($weight_cmp === 0) {
+ return SortArray::sortByKeyString($a, $b, 'component');
+ }
+ return $weight_cmp;
+ }
+
+ /**
+ * Creates a graph of config entity dependencies.
+ *
+ * @param array $entities_to_check
+ * The configuration entity full configuration names to determine the
+ * dependencies for.
+ *
+ * @return \Drupal\Core\Config\Entity\ConfigEntityDependency[]
+ * A graph of config entity dependency objects that are dependent on the
+ * supplied entities to check.
+ */
+ protected function createGraphConfigEntityDependencies($entities_to_check) {
+ $dependent_entities = array();
+ $graph = $this->getGraph();
+
+ foreach ($entities_to_check as $entity) {
+ if (isset($graph[$entity]) && !empty($graph[$entity]['reverse_paths'])){
+ foreach ($graph[$entity]['reverse_paths'] as $dependency => $value) {
+ $dependent_entities[$dependency] = $this->data[$dependency];
+ }
+ }
+ }
+ return $dependent_entities;
+ }
+
+ /**
+ * Gets the dependency graph of all the config entities.
+ *
+ * @return array
+ * The dependency graph of all the config entities.
+ */
+ protected function getGraph() {
+ if (!isset($this->graph)) {
+ $graph = array();
+ foreach ($this->data as $entity) {
+ $graph_key = $entity->getConfigDependencyName();
+ $graph[$graph_key]['edges'] = array();
+ $dependencies = $entity->getDependencies('entity');
+ if (!empty($dependencies)) {
+ foreach ($dependencies as $dependency) {
+ $graph[$graph_key]['edges'][$dependency] = TRUE;
+ }
+ }
+ }
+ $graph_object = new Graph($graph);
+ $this->graph = $graph_object->searchAndSort();
+ }
+ return $this->graph;
+ }
+
+ /**
+ * Sets data to calculate dependencies for.
+ *
+ * The data is converted into lightweight ConfigEntityDependency objects.
+ *
+ * @param array $data
+ * Configuration data keyed by configuration object name. Typically the
+ * output of \Drupal\Core\Config\StorageInterface::loadMultiple().
+ *
+ * @return $this
+ */
+ public function setData(array $data) {
+ array_walk($data, function (&$config, $name) {
+ $config = new ConfigEntityDependency($name, $config);
+ });
+ $this->data = $data;
+ $this->graph = NULL;
+ return $this;
+ }
+
+}
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
index a02e515..b7af02b 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
@@ -64,6 +64,20 @@ abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface
private $isSyncing = FALSE;
/**
+ * Whether the config is being deleted by the uninstall process.
+ *
+ * @var bool
+ */
+ private $isUninstalling = FALSE;
+
+ /**
+ * The configuration entity's dependencies.
+ *
+ * @var array
+ */
+ protected $dependencies = array();
+
+ /**
* Overrides Entity::__construct().
*/
public function __construct(array $values, $entity_type) {
@@ -173,6 +187,20 @@ abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface
/**
* {@inheritdoc}
*/
+ public function setUninstalling($uninstalling) {
+ $this->isUninstalling = $uninstalling;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isUninstalling() {
+ return $this->isUninstalling;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function createDuplicate() {
$duplicate = parent::createDuplicate();
@@ -207,6 +235,8 @@ abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface
$name = $property->getName();
$properties[$name] = $this->get($name);
}
+ // Add protected dependencies property.
+ $properties['dependencies'] = $this->dependencies;
return $properties;
}
@@ -221,7 +251,8 @@ abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface
if ($this instanceof EntityWithPluginBagInterface) {
// Any changes to the plugin configuration must be saved to the entity's
// copy as well.
- $this->set($this->pluginConfigKey, $this->getPluginBag()->getConfiguration());
+ $plugin_bag = $this->getPluginBag();
+ $this->set($this->pluginConfigKey, $plugin_bag->getConfiguration());
}
// Ensure this entity's UUID does not exist with a different ID, regardless
@@ -241,6 +272,33 @@ abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface
throw new ConfigDuplicateUUIDException(format_string('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())));
}
}
+ if (!$this->isSyncing()) {
+ // Ensure the correct dependencies are present. If the configuration is
+ // being written during a configuration synchronisation then there is no
+ // need to recalculate the dependencies.
+ $this->calculateDependencies();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ // Dependencies should be recalculated on every save. This ensures stale
+ // dependencies are never saved.
+ $this->dependencies = array();
+ // @todo When \Drupal\Core\Config\Entity\EntityWithPluginBagInterface moves
+ // to a trait, switch to class_uses() instead.
+ if ($this instanceof EntityWithPluginBagInterface) {
+ // Configuration entities need to depend on the providers of any plugins
+ // that they store the configuration for.
+ $plugin_bag = $this->getPluginBag();
+ foreach($plugin_bag as $instance) {
+ $definition = $instance->getPluginDefinition();
+ $this->addDependency('module', $definition['provider']);
+ }
+ }
+ return $this->dependencies;
}
/**
@@ -264,4 +322,48 @@ abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface
return parent::url($rel, $options);
}
+ /**
+ * Creates a dependency.
+ *
+ * @param string $type
+ * The type of dependency being checked. Either 'module', 'theme', 'entity'.
+ * @param string $name
+ * If $type equals 'module' or 'theme' then it should be the name of the
+ * module or theme. In the case of entity it should be the full
+ * configuration object name.
+ *
+ * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::getConfigDependencyName()
+ *
+ * @return $this
+ */
+ protected function addDependency($type, $name) {
+ // A config entity is always dependent on its provider. There is no need to
+ // explicitly declare the dependency. An explicit dependency on Core, which
+ // provides some plugins, is also not needed.
+ // @see \Drupal\Core\Config\Entity\ConfigEntityDependency::hasDependency()
+ if ($type == 'module' && ($name == $this->getEntityType()->getProvider() || $name == 'Core')) {
+ return $this;
+ }
+ if (empty($this->dependencies[$type])) {
+ $this->dependencies[$type] = array($name);
+ if (count($this->dependencies) > 1) {
+ // Ensure a consistent order of type keys.
+ ksort($this->dependencies);
+ }
+ }
+ elseif (!in_array($name, $this->dependencies[$type])) {
+ $this->dependencies[$type][] = $name;
+ // Ensure a consistent order of dependency names.
+ sort($this->dependencies[$type], SORT_FLAG_CASE);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfigDependencyName() {
+ return $this->getEntityType()->getConfigPrefix() . '.' . $this->id();
+ }
+
}
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityDependency.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityDependency.php
new file mode 100644
index 0000000..604e21c
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityDependency.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Config\Entity\ConfigEntityDependency.
+ */
+
+namespace Drupal\Core\Config\Entity;
+
+/**
+ * Provides a value object to discover configuration dependencies.
+ *
+ * @see \Drupal\Core\Config\Entity\ConfigDependencyManager
+ */
+class ConfigEntityDependency {
+
+ /**
+ * The configuration entity's configuration object name.
+ *
+ * @var string
+ */
+ protected $name;
+
+ /**
+ * The configuration entity's dependencies.
+ *
+ * @var array
+ */
+ protected $dependencies;
+
+ /**
+ * Constructs the configuration entity dependency from the entity values.
+ *
+ * @param string $name
+ * The configuration entity's configuration object name.
+ * @param array $values
+ * The configuration entity's values.
+ */
+ public function __construct($name, $values) {
+ $this->name = $name;
+ if (isset($values['dependencies'])) {
+ $this->dependencies = $values['dependencies'];
+ }
+ else {
+ $this->dependencies = array();
+ }
+ }
+
+ /**
+ * Gets the configuration entity's dependencies of the supplied type.
+ *
+ * @param string $type
+ * The type of dependency to return. Either 'module', 'theme', 'entity'.
+ *
+ * @return array
+ * The list of dependencies of the supplied type.
+ */
+ public function getDependencies($type) {
+ $dependencies = array();
+ if (isset($this->dependencies[$type])) {
+ $dependencies = $this->dependencies[$type];
+ }
+ if ($type == 'module') {
+ $dependencies[] = substr($this->name, 0, strpos($this->name, '.'));
+ }
+ return $dependencies;
+ }
+
+ /**
+ * Determines if the entity is dependent on extensions or entities.
+ *
+ * @param string $type
+ * The type of dependency being checked. Either 'module', 'theme', 'entity'.
+ * @param string $name
+ * The specific name to check. If $type equals 'module' or 'theme' then it
+ * should be a module name or theme name. In the case of entity it should be
+ * the full configuration object name.
+ *
+ * @return bool
+ */
+ public function hasDependency($type, $name) {
+ // A config entity is always dependent on its provider.
+ if ($type == 'module' && strpos($this->name, $name . '.') === 0) {
+ return TRUE;
+ }
+ return isset($this->dependencies[$type]) && array_search($name, $this->dependencies[$type]) !== FALSE;
+ }
+
+ /**
+ * Gets the configuration entity's configuration dependency name.
+ *
+ * @see Drupal\Core\Config\Entity\ConfigEntityInterface::getConfigDependencyName()
+ *
+ * @return string
+ * The configuration dependency name for the entity.
+ */
+ public function getConfigDependencyName() {
+ return $this->name;
+ }
+
+}
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php
index f3943fd..0d5a000 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php
@@ -92,6 +92,25 @@ interface ConfigEntityInterface extends EntityInterface {
public function isSyncing();
/**
+ * Returns whether this entity is being changed during the uninstall process.
+ *
+ * If you are writing code that responds to a change in this entity (insert,
+ * update, delete, presave, etc.), and your code would result in a
+ * configuration change (whether related to this configuration entity, another
+ * configuration entity, or non-entity configuration) or your code would
+ * result in a change to this entity itself, you need to check and see if this
+ * entity change is part of an uninstall process, and skip executing your code
+ * if that is the case.
+ *
+ * For example, \Drupal\language\Entity\Language::preDelete() prevents the API
+ * from deleting the default language. However during an uninstall of the
+ * language module it is expected that the default language should be deleted.
+ *
+ * @return bool
+ */
+ public function isUninstalling();
+
+ /**
* Returns the value of a property.
*
* @param string $property_name
@@ -122,4 +141,20 @@ interface ConfigEntityInterface extends EntityInterface {
*/
public function toArray();
+ /**
+ * Calculates dependencies and stores them in the dependency property.
+ *
+ * @return array
+ * An array of dependencies grouped by type (module, theme, entity).
+ */
+ public function calculateDependencies();
+
+ /**
+ * Gets the configuration dependency name.
+ *
+ * @return string
+ * The configuration dependency name.
+ */
+ public function getConfigDependencyName();
+
}
diff --git a/core/lib/Drupal/Core/Config/Schema/core.data_types.schema.yml b/core/lib/Drupal/Core/Config/Schema/core.data_types.schema.yml
index 5395c16..ee8c147 100644
--- a/core/lib/Drupal/Core/Config/Schema/core.data_types.schema.yml
+++ b/core/lib/Drupal/Core/Config/Schema/core.data_types.schema.yml
@@ -136,3 +136,24 @@ route:
sequence:
- type: string
label: 'Param'
+
+# Config dependencies.
+config_dependencies:
+ type: mapping
+ label: 'Configuration dependencies'
+ mapping:
+ entity:
+ type: sequence
+ label: 'Entity dependencies'
+ sequence:
+ - type: string
+ module:
+ type: sequence
+ label: 'Module dependencies'
+ sequence:
+ - type: string
+ theme:
+ type: sequence
+ label: 'Theme dependencies'
+ sequence:
+ - type: string
diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php
index 425ed58..a20b9b9 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -759,14 +759,16 @@ class ModuleHandler implements ModuleHandlerInterface {
// Uninstall the module.
module_load_install($module);
$this->invoke($module, 'uninstall');
+
+ // Remove all configuration belonging to the module.
+ \Drupal::service('config.manager')->uninstall('module', $module);
+
+ // Remove the schema.
drupal_uninstall_schema($module);
// Remove the module's entry from the config.
$module_config->clear("enabled.$module")->save();
- // Remove all configuration belonging to the module.
- \Drupal::service('config.manager')->uninstall('module', $module);
-
// Update the module handler to remove the module.
// The current ModuleHandler instance is obsolete with the kernel rebuild
// below.
@@ -857,4 +859,5 @@ class ModuleHandler implements ModuleHandlerInterface {
}
return $dirs;
}
+
}
diff --git a/core/modules/aggregator/config/views.view.aggregator_rss_feed.yml b/core/modules/aggregator/config/views.view.aggregator_rss_feed.yml
index c15b24a..d22fdcb 100644
--- a/core/modules/aggregator/config/views.view.aggregator_rss_feed.yml
+++ b/core/modules/aggregator/config/views.view.aggregator_rss_feed.yml
@@ -144,7 +144,10 @@ display:
defaults:
arguments: true
label: 'Aggregator RSS feed'
-module: views
+module: aggregator
id: aggregator_rss_feed
tag: aggregator
langcode: en
+dependencies:
+ module:
+ - aggregator
diff --git a/core/modules/block/config/schema/block.schema.yml b/core/modules/block/config/schema/block.schema.yml
index 1ed3f49..01784bd 100644
--- a/core/modules/block/config/schema/block.schema.yml
+++ b/core/modules/block/config/schema/block.schema.yml
@@ -90,3 +90,6 @@ block.block.*:
langcode:
type: string
label: 'Default language'
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
diff --git a/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml b/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml
index ba11a62..2987629 100644
--- a/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml
+++ b/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml
@@ -3,3 +3,6 @@ label: Full
status: false
cache: true
targetEntityType: custom_block
+dependencies:
+ module:
+ - custom_block
diff --git a/core/modules/block/lib/Drupal/block/Entity/Block.php b/core/modules/block/lib/Drupal/block/Entity/Block.php
index e6d8f7e..ea3a98a 100644
--- a/core/modules/block/lib/Drupal/block/Entity/Block.php
+++ b/core/modules/block/lib/Drupal/block/Entity/Block.php
@@ -11,6 +11,7 @@ use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\block\BlockPluginBag;
use Drupal\block\BlockInterface;
use Drupal\Core\Config\Entity\EntityWithPluginBagInterface;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
/**
* Defines a Block configuration entity class.
@@ -165,4 +166,13 @@ class Block extends ConfigEntityBase implements BlockInterface, EntityWithPlugin
return strcmp($a->label(), $b->label());
}
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+ $this->addDependency('theme', $this->theme);
+ return $this->dependencies;
+ }
+
}
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php
index 36ed74a..aff9d70 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php
@@ -95,6 +95,7 @@ class BlockStorageUnitTest extends DrupalUnitTestBase {
'weight' => NULL,
'status' => TRUE,
'langcode' => language_default()->id,
+ 'dependencies' => array('module' => array('block_test'), 'theme' => array('stark')),
'theme' => 'stark',
'region' => '-1',
'plugin' => 'test_html',
diff --git a/core/modules/block/tests/Drupal/block/Tests/BlockConfigEntityUnitTest.php b/core/modules/block/tests/Drupal/block/Tests/BlockConfigEntityUnitTest.php
new file mode 100644
index 0000000..34d8373
--- /dev/null
+++ b/core/modules/block/tests/Drupal/block/Tests/BlockConfigEntityUnitTest.php
@@ -0,0 +1,121 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block\Tests\BlockConfigEntityUnitTest.
+ */
+
+namespace Drupal\block\Tests;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Tests\Core\Plugin\TestConfigurablePlugin;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\block\Entity\Block
+ *
+ * @group Drupal
+ * @group Config
+ */
+class BlockConfigEntityUnitTest extends UnitTestCase {
+
+ /**
+ * The entity type used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityType;
+
+ /**
+ * The entity manager used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityManager;
+
+ /**
+ * The ID of the type of the entity under test.
+ *
+ * @var string
+ */
+ protected $entityTypeId;
+
+ /**
+ * The UUID generator used for testing.
+ *
+ * @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $uuid;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getInfo() {
+ return array(
+ 'description' => '',
+ 'name' => '\Drupal\block\Entity\Block unit test',
+ 'group' => 'Entity',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUp() {
+ $this->entityTypeId = $this->randomName();
+
+ $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $this->entityType->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue('block'));
+
+ $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
+ $this->entityManager->expects($this->any())
+ ->method('getDefinition')
+ ->with($this->entityTypeId)
+ ->will($this->returnValue($this->entityType));
+
+ $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
+
+ $container = new ContainerBuilder();
+ $container->set('entity.manager', $this->entityManager);
+ $container->set('uuid', $this->uuid);
+ \Drupal::setContainer($container);
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependencies() {
+ $values = array('theme' => 'stark');
+ // Mock the entity under test so that we can mock getPluginBag().
+ $entity = $this->getMockBuilder('\Drupal\block\Entity\Block')
+ ->setConstructorArgs(array($values, $this->entityTypeId))
+ ->setMethods(array('getPluginBag'))
+ ->getMock();
+ // Create a configurable plugin that would add a dependency.
+ $instance_id = $this->randomName();
+ $instance = new TestConfigurablePlugin(array(), $instance_id, array('provider' => 'test'));
+
+ // Create a plugin bag to contain the instance.
+ $plugin_bag = $this->getMockBuilder('\Drupal\Core\Plugin\DefaultPluginBag')
+ ->disableOriginalConstructor()
+ ->setMethods(array('get'))
+ ->getMock();
+ $plugin_bag->expects($this->atLeastOnce())
+ ->method('get')
+ ->with($instance_id)
+ ->will($this->returnValue($instance));
+ $plugin_bag->addInstanceId($instance_id);
+
+ // Return the mocked plugin bag.
+ $entity->expects($this->once())
+ ->method('getPluginBag')
+ ->will($this->returnValue($plugin_bag));
+
+ $dependencies = $entity->calculateDependencies();
+ $this->assertContains('test', $dependencies['module']);
+ $this->assertContains('stark', $dependencies['theme']);
+ }
+
+}
diff --git a/core/modules/block/tests/modules/block_test/config/block.block.test_block.yml b/core/modules/block/tests/modules/block_test/config/block.block.test_block.yml
index 9a8383c..a9eb247 100644
--- a/core/modules/block/tests/modules/block_test/config/block.block.test_block.yml
+++ b/core/modules/block/tests/modules/block_test/config/block.block.test_block.yml
@@ -18,3 +18,8 @@ visibility:
roles: { }
node_type:
types: { }
+dependencies:
+ module:
+ - block_test
+ theme:
+ - stark
diff --git a/core/modules/book/config/entity.view_mode.node.print.yml b/core/modules/book/config/entity.view_mode.node.print.yml
index 7854ec1..512d581 100644
--- a/core/modules/book/config/entity.view_mode.node.print.yml
+++ b/core/modules/book/config/entity.view_mode.node.print.yml
@@ -3,3 +3,6 @@ label: Print
status: false
cache: true
targetEntityType: node
+dependencies:
+ module:
+ - node
diff --git a/core/modules/breakpoint/breakpoint.module b/core/modules/breakpoint/breakpoint.module
index 754d968..be06abd 100644
--- a/core/modules/breakpoint/breakpoint.module
+++ b/core/modules/breakpoint/breakpoint.module
@@ -39,106 +39,6 @@ function breakpoint_help($path, $arg) {
}
/**
- * Implements hook_themes_disabled().
- *
- * @param array $theme_list
- * An array of theme names.
- *
- * @see _breakpoint_delete_breakpoints()
- *
- * @todo: This should be removed if https://drupal.org/node/1813110 is resolved.
- */
-function breakpoint_themes_disabled($theme_list) {
- _breakpoint_delete_breakpoints($theme_list, Breakpoint::SOURCE_TYPE_THEME);
-}
-
-/**
- * Implements hook_modules_uninstalled().
- *
- * @param array $modules
- * An array of the modules that were uninstalled.
- *
- * @see _breakpoint_delete_breakpoints()
- *
- * @todo: This should be removed if https://drupal.org/node/1813110 is resolved.
- */
-function breakpoint_modules_uninstalled($modules) {
- _breakpoint_delete_breakpoints($modules, Breakpoint::SOURCE_TYPE_MODULE);
-}
-
-/**
- * Remove breakpoints from all disabled themes or uninstalled modules.
- *
- * The source type has to match the original source type, otherwise the group
- * will not be deleted. All groups created by the theme or module will be
- * deleted as well.
- *
- * @param array $list
- * A list of modules or themes that are disabled.
- * @param string $source_type
- * Either Breakpoint::SOURCE_TYPE_THEME or Breakpoint::SOURCE_TYPE_MODULE.
- */
-function _breakpoint_delete_breakpoints($list, $source_type) {
- $ids = \Drupal::configFactory()->listAll('breakpoint.breakpoint_group.' . $source_type . '.');
- $entity_manager = \Drupal::entityManager();
- $entity_type = $entity_manager->getDefinition('breakpoint_group');
-
- // Remove the breakpoint.breakpoint part of the breakpoint identifier.
- foreach ($ids as &$id) {
- $id = ConfigStorageController::getIDFromConfigName($id, $entity_type->getConfigPrefix());
- }
- $breakpoint_groups = entity_load_multiple('breakpoint_group', $ids);
-
- foreach ($breakpoint_groups as $breakpoint_group) {
- if ($breakpoint_group->sourceType == $source_type && in_array($breakpoint_group->source, $list)) {
- // Delete the automatically created breakpoint group.
- $breakpoint_group->delete();
-
- // Get all breakpoints defined by this theme/module.
- $breakpoint_ids = \Drupal::service('config.storage')->listAll('breakpoint.breakpoint.' . $source_type . '.' . $breakpoint_group->id() . '.');
- $entity_type = $entity_manager->getDefinition('breakpoint');
-
- // Remove the breakpoint.breakpoint part of the breakpoint identifier.
- foreach ($breakpoint_ids as &$breakpoint_id) {
- $breakpoint_id = ConfigStorageController::getIDFromConfigName($breakpoint_id, $entity_type->getConfigPrefix());
- }
- $breakpoints = entity_load_multiple('breakpoint', $breakpoint_ids);
-
- // Make sure we only delete breakpoints defined by this theme/module.
- foreach ($breakpoints as $breakpoint) {
- if ($breakpoint->sourceType == $source_type && $breakpoint->source == $breakpoint_group->name) {
- $breakpoint->delete();
- }
- }
- }
- }
-
- // Delete groups defined by a module/theme even if that module/theme didn't
- // define any breakpoints.
- foreach ($ids as $id) {
- // Delete all breakpoint groups defined by the theme or module.
- _breakpoint_delete_breakpoint_groups($id, $source_type);
- }
-}
-
-/**
- * Remove breakpoint groups from all disabled themes or uninstalled modules.
- *
- * @param array $group_id
- * Machine readable name of the breakpoint group.
- * @param string $source_type
- * Either Breakpoint::SOURCE_TYPE_THEME or Breakpoint::SOURCE_TYPE_MODULE.
- */
-function _breakpoint_delete_breakpoint_groups($group_id, $source_type) {
- $breakpoint_groups = entity_load_multiple('breakpoint_group');
- foreach ($breakpoint_groups as $breakpoint_group) {
- if ($breakpoint_group->sourceType == $source_type && $breakpoint_group->source == $group_id) {
- $breakpoint_group->delete();
- }
- }
-}
-
-/**
* Load one breakpoint by its identifier.
*
* @param int $id
diff --git a/core/modules/breakpoint/config/schema/breakpoint.schema.yml b/core/modules/breakpoint/config/schema/breakpoint.schema.yml
index ce21948..82eac47 100644
--- a/core/modules/breakpoint/config/schema/breakpoint.schema.yml
+++ b/core/modules/breakpoint/config/schema/breakpoint.schema.yml
@@ -39,6 +39,9 @@ breakpoint.breakpoint.*.*.*:
status:
type: boolean
label: 'Enabled'
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
breakpoint.breakpoint_group.*.*.*:
type: mapping
@@ -74,3 +77,6 @@ breakpoint.breakpoint_group.*.*.*:
status:
type: boolean
label: 'Enabled'
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointGroupInterface.php b/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointGroupInterface.php
index 3bb877b..ae4f2e9 100644
--- a/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointGroupInterface.php
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointGroupInterface.php
@@ -51,7 +51,7 @@ interface BreakpointGroupInterface extends ConfigEntityInterface {
/**
* Gets the array of breakpoints for the breakpoint group.
*
- * @return array
+ * @return \Drupal\breakpoint\Entity\BreakpointInterface[]
* The array of breakpoints for the breakpoint group.
*/
public function getBreakpoints();
@@ -62,7 +62,7 @@ interface BreakpointGroupInterface extends ConfigEntityInterface {
* @param string $id
* The breakpoint ID to get.
*
- * @return \Drupal\breakpoint\Entity\Breakpoint|boolean
+ * @return \Drupal\breakpoint\Entity\BreakpointInterface|boolean
* The breakpoint or FALSE if not in the Breakpoint group.
*/
public function getBreakpointById($id);
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/Breakpoint.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/Breakpoint.php
index 02c1945..eab45d9 100644
--- a/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/Breakpoint.php
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/Breakpoint.php
@@ -14,6 +14,7 @@ use Drupal\breakpoint\InvalidBreakpointNameException;
use Drupal\breakpoint\InvalidBreakpointSourceException;
use Drupal\breakpoint\InvalidBreakpointSourceTypeException;
use Drupal\breakpoint\InvalidBreakpointMediaQueryException;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
/**
* Defines the Breakpoint entity.
@@ -269,4 +270,20 @@ class Breakpoint extends ConfigEntityBase implements BreakpointInterface {
}
throw new InvalidBreakpointMediaQueryException('Media query is empty.');
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+ $this->dependencies = array();
+ if ($this->sourceType == static::SOURCE_TYPE_MODULE) {
+ $this->addDependency('module', $this->source);
+ }
+ elseif ($this->sourceType == static::SOURCE_TYPE_THEME) {
+ $this->addDependency('theme', $this->source);
+ }
+ return $this->dependencies;
+ }
+
}
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php
index 19b4950..738f3b2 100644
--- a/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php
@@ -11,6 +11,7 @@ use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\breakpoint\BreakpointGroupInterface;
use Drupal\breakpoint\InvalidBreakpointSourceException;
use Drupal\breakpoint\InvalidBreakpointSourceTypeException;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
/**
* Defines the BreakpointGroup entity.
@@ -91,7 +92,7 @@ class BreakpointGroup extends ConfigEntityBase implements BreakpointGroupInterfa
/**
* Overrides Drupal\config\ConfigEntityBase::__construct().
*/
- public function __construct(array $values, $entity_type) {
+ public function __construct(array $values, $entity_type = 'breakpoint_group') {
parent::__construct($values, $entity_type);
}
@@ -207,6 +208,7 @@ class BreakpointGroup extends ConfigEntityBase implements BreakpointGroupInterfa
'sourceType',
'status',
'langcode',
+ 'dependencies',
);
$properties = array();
foreach ($names as $name) {
@@ -214,4 +216,25 @@ class BreakpointGroup extends ConfigEntityBase implements BreakpointGroupInterfa
}
return $properties;
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+
+ $this->dependencies = array();
+ if ($this->sourceType == Breakpoint::SOURCE_TYPE_MODULE) {
+ $this->addDependency('module', $this->source);
+ }
+ elseif ($this->sourceType == Breakpoint::SOURCE_TYPE_THEME) {
+ $this->addDependency('theme', $this->source);
+ }
+ $breakpoints = $this->getBreakpoints();
+ foreach ($breakpoints as $breakpoint) {
+ $this->addDependency('entity', $breakpoint->getConfigDependencyName());
+ }
+ return $this->dependencies;
+ }
+
}
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php
index 153df41..5715a8e 100644
--- a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php
@@ -51,10 +51,6 @@ class BreakpointThemeTest extends BreakpointGroupTestBase {
// Verify we can load this breakpoint defined by the theme.
$this->verifyBreakpointGroup($breakpoint_group_obj);
-
- // Disable the test theme and verify the breakpoint group is deleted.
- theme_disable(array('breakpoint_test_theme'));
- $this->assertFalse(entity_load('breakpoint_group', $breakpoint_group_obj->id()), 'breakpoint_group_load: Loading a deleted breakpoint group returns false.', 'Breakpoint API');
}
/**
@@ -79,10 +75,6 @@ class BreakpointThemeTest extends BreakpointGroupTestBase {
// Verify we can load this breakpoint defined by the theme.
$this->verifyBreakpointGroup($breakpoint_group_obj);
-
- // Disable the test theme and verify the breakpoint group is deleted.
- theme_disable(array('breakpoint_test_theme'));
- $this->assertFalse(entity_load('breakpoint_group', $breakpoint_group_obj->id()), 'breakpoint_group_load: Loading a deleted breakpoint group returns false.', 'Breakpoint API');
}
}
diff --git a/core/modules/breakpoint/tests/Drupal/breakpoint/Tests/BreakpointConfigEntityUnitTest.php b/core/modules/breakpoint/tests/Drupal/breakpoint/Tests/BreakpointConfigEntityUnitTest.php
new file mode 100644
index 0000000..68ff25a
--- /dev/null
+++ b/core/modules/breakpoint/tests/Drupal/breakpoint/Tests/BreakpointConfigEntityUnitTest.php
@@ -0,0 +1,124 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\breakpoint\Tests\BreakpointConfigEntityUnitTest.
+ */
+
+namespace Drupal\breakpoint\Tests;
+
+use Drupal\breakpoint\Entity\Breakpoint;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\breakpoint\Entity\Breakpoint
+ *
+ * @group Drupal
+ * @group Config
+ * @group Breakpoint
+ */
+class BreakpointConfigEntityUnitTest extends UnitTestCase {
+
+ /**
+ * The entity under test.
+ *
+ * @var \Drupal\breakpoint\Entity\Breakpoint|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entity;
+
+ /**
+ * The entity type used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityType;
+
+ /**
+ * The entity manager used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityManager;
+
+ /**
+ * The ID of the type of the entity under test.
+ *
+ * @var string
+ */
+ protected $entityTypeId;
+
+ /**
+ * The UUID generator used for testing.
+ *
+ * @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $uuid;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getInfo() {
+ return array(
+ 'description' => '',
+ 'name' => '\Drupal\breakpoint\Entity\Breakpoint unit test',
+ 'group' => 'Entity',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUp() {
+ $this->entityTypeId = $this->randomName();
+
+ $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $this->entityType->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue('breakpoint'));
+
+ $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
+ $this->entityManager->expects($this->any())
+ ->method('getDefinition')
+ ->with($this->entityTypeId)
+ ->will($this->returnValue($this->entityType));
+
+ $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
+
+ $container = new ContainerBuilder();
+ $container->set('entity.manager', $this->entityManager);
+ $container->set('uuid', $this->uuid);
+ \Drupal::setContainer($container);
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependenciesModule() {
+ $values = array(
+ 'source' => 'test_module',
+ 'sourceType' => Breakpoint::SOURCE_TYPE_MODULE,
+ );
+ $entity = new Breakpoint($values, $this->entityTypeId);
+
+ $dependencies = $entity->calculateDependencies();
+ $this->assertArrayNotHasKey('theme', $dependencies);
+ $this->assertContains('test_module', $dependencies['module']);
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependenciesTheme() {
+ $values = array(
+ 'source' => 'test_theme',
+ 'sourceType' => Breakpoint::SOURCE_TYPE_THEME,
+ );
+ $entity = new Breakpoint($values, $this->entityTypeId);
+
+ $dependencies = $entity->calculateDependencies();
+ $this->assertArrayNotHasKey('module', $dependencies);
+ $this->assertContains('test_theme', $dependencies['theme']);
+ }
+
+}
diff --git a/core/modules/breakpoint/tests/Drupal/breakpoint/Tests/BreakpointGroupConfigEntityUnitTest.php b/core/modules/breakpoint/tests/Drupal/breakpoint/Tests/BreakpointGroupConfigEntityUnitTest.php
new file mode 100644
index 0000000..6587e90
--- /dev/null
+++ b/core/modules/breakpoint/tests/Drupal/breakpoint/Tests/BreakpointGroupConfigEntityUnitTest.php
@@ -0,0 +1,158 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\breakpoint\Tests\BreakpointGroupConfigEntityUnitTest.
+ */
+
+namespace Drupal\breakpoint\Tests;
+
+use Drupal\breakpoint\Entity\Breakpoint;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\breakpoint\Entity\BreakpointGroup
+ *
+ * @group Drupal
+ * @group Config
+ * @group Breakpoint
+ */
+class BreakpointGroupConfigEntityUnitTest extends UnitTestCase {
+
+ /**
+ * The entity under test.
+ *
+ * @var \Drupal\breakpoint\Entity\BreakpointGroup|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entity;
+
+ /**
+ * The entity type used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityType;
+
+ /**
+ * The entity manager used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityManager;
+
+ /**
+ * The ID of the type of the entity under test.
+ *
+ * @var string
+ */
+ protected $entityTypeId;
+
+ /**
+ * The UUID generator used for testing.
+ *
+ * @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $uuid;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getInfo() {
+ return array(
+ 'description' => '',
+ 'name' => '\Drupal\breakpoint\Entity\BreakpointGroup unit test',
+ 'group' => 'Entity',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUp() {
+ $this->entityTypeId = $this->randomName();
+
+ $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $this->entityType->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue('breakpoint'));
+
+ $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
+ $this->entityManager->expects($this->any())
+ ->method('getDefinition')
+ ->with($this->entityTypeId)
+ ->will($this->returnValue($this->entityType));
+
+ $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
+
+ $container = new ContainerBuilder();
+ $container->set('entity.manager', $this->entityManager);
+ $container->set('uuid', $this->uuid);
+ \Drupal::setContainer($container);
+ }
+
+ /**
+ * Sets up the entity to test.
+ */
+ public function setUpEntity($values) {
+ // Mocking the entity under test because the class contains calls to
+ // procedural code.
+ $this->entity = $this->getMockBuilder('\Drupal\breakpoint\Entity\BreakpointGroup')
+ ->setConstructorArgs(array($values, $this->entityTypeId))
+ ->setMethods(array('getBreakpoints'))
+ ->getMock();
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependenciesModule() {
+ $this->setUpEntity(
+ array(
+ 'source' => 'test_module',
+ 'sourceType' => Breakpoint::SOURCE_TYPE_MODULE,
+ )
+ );
+ $breakpoint = $this->getMock('\Drupal\breakpoint\BreakpointInterface');
+ $breakpoint->expects($this->once())
+ ->method('getConfigDependencyName')
+ ->will($this->returnValue('breakpoint.breakpoint.test'));
+
+ $this->entity->expects($this->once())
+ ->method('getBreakpoints')
+ ->will($this->returnValue(array($breakpoint)));
+
+ $dependencies = $this->entity->calculateDependencies();
+ $this->assertArrayNotHasKey('theme', $dependencies);
+ $this->assertContains('test_module', $dependencies['module']);
+ $this->assertContains('breakpoint.breakpoint.test', $dependencies['entity']);
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependenciesTheme() {
+ $this->setUpEntity(
+ array(
+ 'source' => 'test_theme',
+ 'sourceType' => Breakpoint::SOURCE_TYPE_THEME,
+ )
+ );
+
+ $breakpoint = $this->getMockBuilder('\Drupal\breakpoint\Entity\Breakpoint')
+ ->disableOriginalConstructor()->getMock();
+ $breakpoint->expects($this->once())
+ ->method('getConfigDependencyName')
+ ->will($this->returnValue('breakpoint.breakpoint.test'));
+
+ $this->entity->expects($this->once())
+ ->method('getBreakpoints')
+ ->will($this->returnValue(array($breakpoint)));
+
+ $dependencies = $this->entity->calculateDependencies();
+ $this->assertArrayNotHasKey('module', $dependencies);
+ $this->assertContains('test_theme', $dependencies['theme']);
+ $this->assertContains('breakpoint.breakpoint.test', $dependencies['entity']);
+ }
+
+}
diff --git a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php
index 7a6f3cc..55346ff 100644
--- a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php
+++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php
@@ -124,12 +124,10 @@ class CKEditorTest extends DrupalUnitTestBase {
// Change the allowed HTML tags; the "allowedContent" and "format_tags"
// settings for CKEditor should automatically be updated as well.
- $format = entity_load('filter_format', 'filtered_html');
+ $format = $editor->getFilterFormat();
$format->filters('filter_html')->settings['allowed_html'] .= '<pre> <h3>';
$format->save();
- // $editor is a Text Editor object that has a statically cached FilterFormat
- // which is now outdated. Therefore, reload it.
- $editor = entity_load('editor', $editor->id());
+
$expected_config['allowedContent']['pre'] = array('attributes' => TRUE, 'styles' => FALSE, 'classes' => TRUE);
$expected_config['allowedContent']['h3'] = array('attributes' => TRUE, 'styles' => FALSE, 'classes' => TRUE);
$expected_config['format_tags'] = 'p;h3;h4;h5;h6;pre';
@@ -138,9 +136,7 @@ class CKEditorTest extends DrupalUnitTestBase {
// Disable the filter_html filter: allow *all *tags.
$format->setFilterConfig('filter_html', array('status' => 0));
$format->save();
- // $editor is a Text Editor object that has a statically cached FilterFormat
- // which is now outdated. Therefore, reload it.
- $editor = entity_load('editor', $editor->id());
+
$expected_config['allowedContent'] = TRUE;
$expected_config['format_tags'] = 'p;h1;h2;h3;h4;h5;h6;pre';
$this->assertIdentical($expected_config, $this->ckeditor->getJSSettings($editor), 'Generated JS settings are correct for customized configuration.');
@@ -174,9 +170,7 @@ class CKEditorTest extends DrupalUnitTestBase {
),
));
$format->save();
- // $editor is a Text Editor object that has a statically cached FilterFormat
- // which is now outdated. Therefore, reload it.
- $editor = entity_load('editor', $editor->id());
+
$expected_config['allowedContent'] = array(
'p' => array(
'attributes' => TRUE,
diff --git a/core/modules/comment/config/entity.view_mode.comment.full.yml b/core/modules/comment/config/entity.view_mode.comment.full.yml
index fd623d4..c30d77d 100644
--- a/core/modules/comment/config/entity.view_mode.comment.full.yml
+++ b/core/modules/comment/config/entity.view_mode.comment.full.yml
@@ -3,3 +3,6 @@ label: 'Full comment'
status: false
cache: true
targetEntityType: comment
+dependencies:
+ module:
+ - comment
diff --git a/core/modules/comment/config/system.action.comment_publish_action.yml b/core/modules/comment/config/system.action.comment_publish_action.yml
index ae9d93a..e1e12ad 100644
--- a/core/modules/comment/config/system.action.comment_publish_action.yml
+++ b/core/modules/comment/config/system.action.comment_publish_action.yml
@@ -4,3 +4,6 @@ status: true
langcode: en
type: comment
plugin: comment_publish_action
+dependencies:
+ module:
+ - comment
diff --git a/core/modules/comment/config/system.action.comment_save_action.yml b/core/modules/comment/config/system.action.comment_save_action.yml
index e98a92a..8c605b0 100644
--- a/core/modules/comment/config/system.action.comment_save_action.yml
+++ b/core/modules/comment/config/system.action.comment_save_action.yml
@@ -4,3 +4,6 @@ status: true
langcode: en
type: comment
plugin: comment_save_action
+dependencies:
+ module:
+ - comment
diff --git a/core/modules/comment/config/system.action.comment_unpublish_action.yml b/core/modules/comment/config/system.action.comment_unpublish_action.yml
index 61b8e24..5e8e169 100644
--- a/core/modules/comment/config/system.action.comment_unpublish_action.yml
+++ b/core/modules/comment/config/system.action.comment_unpublish_action.yml
@@ -4,3 +4,6 @@ status: true
langcode: en
type: comment
plugin: comment_unpublish_action
+dependencies:
+ module:
+ - comment
diff --git a/core/modules/comment/config/views.view.comments_recent.yml b/core/modules/comment/config/views.view.comments_recent.yml
index dc16d8d..15993f8 100644
--- a/core/modules/comment/config/views.view.comments_recent.yml
+++ b/core/modules/comment/config/views.view.comments_recent.yml
@@ -234,3 +234,6 @@ module: views
id: comments_recent
tag: default
langcode: en
+dependencies:
+ module:
+ - comment
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentTestBase.php b/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentTestBase.php
index 32ffa1f..43c987f 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentTestBase.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentTestBase.php
@@ -40,6 +40,7 @@ abstract class CommentTestBase extends ViewTestBase {
$this->account2 = $this->drupalCreateUser();
$this->drupalLogin($this->account);
+ $this->drupalCreateContentType(array('type' => 'page', 'name' => t('Basic page')));
$this->container->get('comment.manager')->addDefaultField('node', 'page');
$this->node_user_posted = $this->drupalCreateNode();
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php b/core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php
index 9a39f2f..6ced3f6 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php
@@ -34,11 +34,19 @@ class WizardTest extends WizardTestBase {
}
/**
- * Tests adding a view of comments.
+ * {@inheritdoc}
*/
- public function testCommentWizard() {
+ public function setUp() {
+ parent::setUp();
+ $this->drupalCreateContentType(array('type' => 'page', 'name' => t('Basic page')));
// Add comment field to page node type.
$this->container->get('comment.manager')->addDefaultField('node', 'page');
+ }
+
+ /**
+ * Tests adding a view of comments.
+ */
+ public function testCommentWizard() {
$view = array();
$view['label'] = $this->randomName(16);
$view['id'] = strtolower($this->randomName(16));
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigDependencyTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigDependencyTest.php
new file mode 100644
index 0000000..f35d9f4
--- /dev/null
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigDependencyTest.php
@@ -0,0 +1,170 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\config\Tests\ConfigDependencyTest.
+ */
+
+namespace Drupal\config\Tests;
+
+use Drupal\simpletest\DrupalUnitTestBase;
+
+/**
+ * Unit tests for configuration controllers and objects.
+ */
+class ConfigDependencyTest extends DrupalUnitTestBase {
+
+ /**
+ * Modules to enable.
+ *
+ * @var array
+ */
+ public static $modules = array('system', 'config_test');
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Configuration dependency tests',
+ 'description' => 'Tests for configuration dependencies.',
+ 'group' => 'Configuration',
+ );
+ }
+
+ /**
+ * Tests that calculating dependencies for system module.
+ */
+ public function testNonEntity() {
+ $this->installConfig(array('system'));
+ $config_manager = \Drupal::service('config.manager');
+ $dependents = $config_manager->findConfigEntityDependents('module', array('system'));
+ $this->assertTrue(isset($dependents['system.site']), 'Simple configuration system.site has a UUID key even though it is not a configuration entity and therefore is found when looking for dependencies of the System module.');
+ // Ensure that calling
+ // \Drupal\Core\Config\ConfigManager::findConfigEntityDependentsAsEntities()
+ // does not try to load system.site as an entity.
+ $config_manager->findConfigEntityDependentsAsEntities('module', array('system'));
+ }
+
+ /**
+ * Tests creating dependencies on configuration entities.
+ */
+ public function testDependencyMangement() {
+ $config_manager = \Drupal::service('config.manager');
+ $storage = $this->container->get('entity.manager')->getStorageController('config_test');
+ // Test dependencies between modules.
+ $entity1 = $storage->create(
+ array(
+ 'id' => 'entity1',
+ 'test_dependencies' => array(
+ 'module' => array('node', 'config_test')
+ )
+ )
+ );
+ $entity1->save();
+
+ $dependents = $config_manager->findConfigEntityDependents('module', array('node'));
+ $this->assertTrue(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 has a dependency on the Node module.');
+ $dependents = $config_manager->findConfigEntityDependents('module', array('config_test'));
+ $this->assertTrue(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 has a dependency on the config_test module.');
+ $dependents = $config_manager->findConfigEntityDependents('module', array('views'));
+ $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on the Views module.');
+ // Ensure that the provider of the config entity is not actually written to
+ // the dependencies array.
+ $raw_config = \Drupal::config('config_test.dynamic.entity1');
+ $this->assertTrue(array_search('config_test', $raw_config->get('dependencies.module')) === FALSE, 'Module that the provides the configuration entity is not written to the dependencies array as this is implicit.');
+ $this->assertTrue(array_search('node', $raw_config->get('dependencies.module')) !== FALSE, 'Node module is written to the dependencies array as this has to be explicit.');
+
+ // Create additional entities to test dependencies on config entities.
+ $entity2 = $storage->create(array('id' => 'entity2', 'test_dependencies' => array('entity' => array($entity1->getConfigDependencyName()))));
+ $entity2->save();
+ $entity3 = $storage->create(array('id' => 'entity3', 'test_dependencies' => array('entity' => array($entity2->getConfigDependencyName()))));
+ $entity3->save();
+ $entity4 = $storage->create(array('id' => 'entity4', 'test_dependencies' => array('entity' => array($entity3->getConfigDependencyName()))));
+ $entity4->save();
+
+ // Test getting $entity1's dependencies as configuration dependency objects.
+ $dependents = $config_manager->findConfigEntityDependents('entity', array($entity1->getConfigDependencyName()));
+ $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on itself.');
+ $this->assertTrue(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity2 has a dependency on config_test.dynamic.entity1.');
+ $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity3 has a dependency on config_test.dynamic.entity1.');
+ $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity4 has a dependency on config_test.dynamic.entity1.');
+
+ // Test getting $entity2's dependencies as entities.
+ $dependents = $config_manager->findConfigEntityDependentsAsEntities('entity', array($entity2->getConfigDependencyName()));
+ $dependent_ids = $this->getDependentIds($dependents);
+ $this->assertFalse(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 does not have a dependency on config_test.dynamic.entity1.');
+ $this->assertFalse(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 does not have a dependency on itself.');
+ $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity3 has a dependency on config_test.dynamic.entity2.');
+ $this->assertTrue(in_array('config_test:entity4', $dependent_ids), 'config_test.dynamic.entity4 has a dependency on config_test.dynamic.entity2.');
+
+ // Test getting node module's dependencies as configuration dependency
+ // objects.
+ $dependents = $config_manager->findConfigEntityDependents('module', array('node'));
+ $this->assertTrue(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 has a dependency on the Node module.');
+ $this->assertTrue(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity2 has a dependency on the Node module.');
+ $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity3 has a dependency on the Node module.');
+ $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity4 has a dependency on the Node module.');
+
+ // Test getting node module's dependencies as configuration dependency
+ // objects after making $entity3 also dependent on node module but $entity1
+ // no longer depend on node module.
+ $entity1->test_dependencies = array();
+ $entity1->save();
+ $entity3->test_dependencies['module'] = array('node');
+ $entity3->save();
+ $dependents = $config_manager->findConfigEntityDependents('module', array('node'));
+ $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on the Node module.');
+ $this->assertFalse(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity2 does not have a dependency on the Node module.');
+ $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity3 has a dependency on the Node module.');
+ $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity4 has a dependency on the Node module.');
+
+ // Create a configuration entity of a different type with the same ID as one
+ // of the entities already created.
+ $alt_storage = $this->container->get('entity.manager')->getStorageController('config_query_test');
+ $alt_storage->create(array('id' => 'entity1', 'test_dependencies' => array('entity' => array($entity1->getConfigDependencyName()))))->save();
+ $alt_storage->create(array('id' => 'entity2', 'test_dependencies' => array('module' => array('views'))))->save();
+
+ $dependents = $config_manager->findConfigEntityDependentsAsEntities('entity', array($entity1->getConfigDependencyName()));
+ $dependent_ids = $this->getDependentIds($dependents);
+ $this->assertFalse(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 does not have a dependency on itself.');
+ $this->assertTrue(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 has a dependency on config_test.dynamic.entity1.');
+ $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity3 has a dependency on config_test.dynamic.entity1.');
+ $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity4 has a dependency on config_test.dynamic.entity1.');
+ $this->assertTrue(in_array('config_query_test:entity1', $dependent_ids), 'config_query_test.dynamic.entity1 has a dependency on config_test.dynamic.entity1.');
+ $this->assertFalse(in_array('config_query_test:entity2', $dependent_ids), 'config_query_test.dynamic.entity2 does not have a dependency on config_test.dynamic.entity1.');
+
+ $dependents = $config_manager->findConfigEntityDependentsAsEntities('module', array('node', 'views'));
+ $dependent_ids = $this->getDependentIds($dependents);
+ $this->assertFalse(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 does not have a dependency on Views or Node.');
+ $this->assertFalse(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 does not have a dependency on Views or Node.');
+ $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity3 has a dependency on Views or Node.');
+ $this->assertTrue(in_array('config_test:entity4', $dependent_ids), 'config_test.dynamic.entity4 has a dependency on Views or Node.');
+ $this->assertFalse(in_array('config_query_test:entity1', $dependent_ids), 'config_test.query.entity1 does not have a dependency on Views or Node.');
+ $this->assertTrue(in_array('config_query_test:entity2', $dependent_ids), 'config_test.query.entity2 has a dependency on Views or Node.');
+
+ $dependents = $config_manager->findConfigEntityDependentsAsEntities('module', array('config_test'));
+ $dependent_ids = $this->getDependentIds($dependents);
+ $this->assertTrue(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 has a dependency on config_test module.');
+ $this->assertTrue(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 has a dependency on config_test module.');
+ $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity3 has a dependency on config_test module.');
+ $this->assertTrue(in_array('config_test:entity4', $dependent_ids), 'config_test.dynamic.entity4 has a dependency on config_test module.');
+ $this->assertTrue(in_array('config_query_test:entity1', $dependent_ids), 'config_test.query.entity1 has a dependency on config_test module.');
+ $this->assertTrue(in_array('config_query_test:entity2', $dependent_ids), 'config_test.query.entity2 has a dependency on config_test module.');
+
+ }
+
+ /**
+ * Gets a list of identifiers from an array of configuration entities.
+ *
+ * @param \Drupal\Core\Config\Entity\ConfigEntityInterface[] $dependents
+ * An array of configuration entities.
+ *
+ * @return array
+ * An array with values of entity_type_id:ID
+ */
+ protected function getDependentIds(array $dependents) {
+ $dependent_ids = array();
+ foreach($dependents as $dependent) {
+ $dependent_ids[] = $dependent->getEntityTypeId() . ':' . $dependent->id();
+ }
+ return $dependent_ids;
+ }
+}
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php
index 89413d2..51f9182 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportUITest.php
@@ -55,9 +55,11 @@ class ConfigImportUITest extends WebTestBase {
'label' => 'New',
'weight' => 0,
'style' => '',
+ 'test_dependencies' => array(),
'status' => TRUE,
'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651',
'langcode' => language_default()->id,
+ 'dependencies' => array(),
'protected_property' => '',
);
$staging->write($dynamic_name, $original_dynamic_data);
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
index b597aa7..b01ddab 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
@@ -166,9 +166,11 @@ class ConfigImporterTest extends DrupalUnitTestBase {
'label' => 'New',
'weight' => 0,
'style' => '',
+ 'test_dependencies' => array(),
'status' => TRUE,
'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651',
'langcode' => language_default()->id,
+ 'dependencies' => array(),
'protected_property' => '',
);
$staging->write($dynamic_name, $original_dynamic_data);
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php
index 90915fc..9ba92da 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php
@@ -93,4 +93,16 @@ class ConfigOtherModuleTest extends WebTestBase {
$this->assertTrue(entity_load('config_test', 'other_module', TRUE), 'Default configuration provided by config_other_module_config has been installed.');
}
+ /**
+ * Tests uninstalling Node module removes views which are dependent on it.
+ */
+ public function testUninstall() {
+ $this->moduleHandler->install(array('views'));
+ $this->assertTrue(entity_load('view', 'frontpage', TRUE) === NULL, 'After installing Views, frontpage view which is dependant on the Node and Views modules does not exist.');
+ $this->moduleHandler->install(array('node'));
+ $this->assertTrue(entity_load('view', 'frontpage', TRUE) !== NULL, 'After installing Node, frontpage view which is dependant on the Node and Views modules exists.');
+ $this->moduleHandler->uninstall(array('node'));
+ $this->assertTrue(entity_load('view', 'frontpage', TRUE) === NULL, 'After uninstalling Node, frontpage view which is dependant on the Node and Views modules does not exist.');
+ }
+
}
diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php
index d7ac61c..3449b51 100644
--- a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php
+++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php
@@ -70,6 +70,13 @@ class ConfigTest extends ConfigEntityBase implements ConfigTestInterface {
public $style;
/**
+ * Test dependencies.
+ *
+ * @var array;
+ */
+ public $test_dependencies = array();
+
+ /**
* A protected property of the configuration entity.
*
* @var string
@@ -98,4 +105,16 @@ class ConfigTest extends ConfigEntityBase implements ConfigTestInterface {
return parent::sort($a, $b);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+ foreach ($this->test_dependencies as $type => $deps) {
+ foreach ($deps as $dep) {
+ $this->addDependency($type, $dep);
+ }
+ }
+ }
+
}
diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/TestInstallStorage.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/TestInstallStorage.php
index 954036e..cefb13f 100644
--- a/core/modules/config/tests/config_test/lib/Drupal/config_test/TestInstallStorage.php
+++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/TestInstallStorage.php
@@ -25,6 +25,8 @@ class TestInstallStorage extends InstallStorage {
if (!isset($this->folders)) {
// @todo Refactor getComponentNames() to use the extension list directly.
$listing = new ExtensionDiscovery();
+ // Test all profiles.
+ $listing->setProfileDirectories(array());
$this->folders = $this->getComponentNames('profile', array_keys($listing->scan('profile')));
$this->folders += $this->getComponentNames('module', array_keys($listing->scan('module')));
$this->folders += $this->getComponentNames('theme', array_keys($listing->scan('theme')));
diff --git a/core/modules/editor/config/schema/editor.schema.yml b/core/modules/editor/config/schema/editor.schema.yml
index 086abf6..8809800 100644
--- a/core/modules/editor/config/schema/editor.schema.yml
+++ b/core/modules/editor/config/schema/editor.schema.yml
@@ -44,3 +44,6 @@ editor.editor.*:
langcode:
type: string
label: 'Default language'
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
diff --git a/core/modules/editor/lib/Drupal/editor/Entity/Editor.php b/core/modules/editor/lib/Drupal/editor/Entity/Editor.php
index c58d2fa..07dcc4b 100644
--- a/core/modules/editor/lib/Drupal/editor/Entity/Editor.php
+++ b/core/modules/editor/lib/Drupal/editor/Entity/Editor.php
@@ -60,6 +60,11 @@ class Editor extends ConfigEntityBase implements EditorInterface {
protected $filterFormat;
/**
+ * @var \Drupal\Component\Plugin\PluginManagerInterface
+ */
+ protected $editorPluginManager;
+
+ /**
* {@inheritdoc}
*/
public function id() {
@@ -72,8 +77,7 @@ class Editor extends ConfigEntityBase implements EditorInterface {
public function __construct(array $values, $entity_type) {
parent::__construct($values, $entity_type);
- $manager = \Drupal::service('plugin.manager.editor');
- $plugin = $manager->createInstance($this->editor);
+ $plugin = $this->editorPluginManager()->createInstance($this->editor);
// Initialize settings, merging module-provided defaults.
$default_settings = $plugin->getDefaultSettings();
@@ -85,6 +89,20 @@ class Editor extends ConfigEntityBase implements EditorInterface {
/**
* {@inheritdoc}
*/
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+ // Create a dependency on the associated FilterFormat.
+ $this->addDependency('entity', $this->getFilterFormat()->getConfigDependencyName());
+ // @todo use EntityWithPluginBagInterface so configuration between config
+ // entity and dependency on provider is managed automatically.
+ $definition = $this->editorPluginManager()->createInstance($this->editor)->getPluginDefinition();
+ $this->addDependency('module', $definition['provider']);
+ return $this->dependencies;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function getFilterFormat() {
if (!$this->filterFormat) {
$this->filterFormat = \Drupal::entityManager()->getStorageController('filter_format')->load($this->format);
@@ -92,4 +110,17 @@ class Editor extends ConfigEntityBase implements EditorInterface {
return $this->filterFormat;
}
+ /**
+ * Returns the editor plugin manager.
+ *
+ * @return \Drupal\Component\Plugin\PluginManagerInterface
+ */
+ protected function editorPluginManager() {
+ if (!$this->editorPluginManager) {
+ $this->editorPluginManager = \Drupal::service('plugin.manager.editor');
+ }
+
+ return $this->editorPluginManager;
+ }
+
}
diff --git a/core/modules/editor/tests/Drupal/editor/Tests/EditorConfigEntityUnitTest.php b/core/modules/editor/tests/Drupal/editor/Tests/EditorConfigEntityUnitTest.php
new file mode 100644
index 0000000..2760e93
--- /dev/null
+++ b/core/modules/editor/tests/Drupal/editor/Tests/EditorConfigEntityUnitTest.php
@@ -0,0 +1,171 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\editor\Tests\EditorConfigEntityUnitTest.
+ */
+
+namespace Drupal\editor\Tests;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\editor\Entity\Editor;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\editor\Entity\Editor
+ *
+ * @group Drupal
+ * @group Config
+ */
+class EditorConfigEntityUnitTest extends UnitTestCase {
+
+ /**
+ * The entity type used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityType;
+
+ /**
+ * The entity manager used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityManager;
+
+ /**
+ * The ID of the type of the entity under test.
+ *
+ * @var string
+ */
+ protected $entityTypeId;
+
+ /**
+ * The UUID generator used for testing.
+ *
+ * @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $uuid;
+
+ /**
+ * The editor plugin manager used for testing.
+ *
+ * @var \Drupal\editor\Plugin\EditorManager|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $editorPluginManager;
+
+ /**
+ * The module handler used for testing.
+ *
+ * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $moduleHandler;
+
+ /**
+ * Editor plugin ID.
+ *
+ * @var string
+ */
+ protected $editorId;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getInfo() {
+ return array(
+ 'description' => '',
+ 'name' => '\Drupal\editor\Entity\Editor unit test',
+ 'group' => 'Entity',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUp() {
+ $this->editorId = $this->randomName();
+ $this->entityTypeId = $this->randomName();
+
+ $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $this->entityType->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue('editor'));
+
+ $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
+ $this->entityManager->expects($this->any())
+ ->method('getDefinition')
+ ->with($this->entityTypeId)
+ ->will($this->returnValue($this->entityType));
+
+ $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
+
+ $this->editorPluginManager = $this->getMockBuilder('Drupal\editor\Plugin\EditorManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->moduleHandler = $this->getMock('\Drupal\Core\Extension\ModuleHandlerInterface');
+ $this->moduleHandler->expects($this->once())
+ ->method('invokeAll')
+ ->with('editor_default_settings', array($this->editorId))
+ ->will($this->returnValue(array()));
+
+ $this->moduleHandler->expects($this->once())
+ ->method('alter')
+ ->with('editor_default_settings', array(), $this->editorId)
+ ->will($this->returnValue(array()));
+
+ $container = new ContainerBuilder();
+ $container->set('entity.manager', $this->entityManager);
+ $container->set('uuid', $this->uuid);
+ $container->set('plugin.manager.editor', $this->editorPluginManager);
+ $container->set('module_handler', $this->moduleHandler);
+ \Drupal::setContainer($container);
+
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependencies() {
+ $format_id = 'filter.format.test';
+ $values = array('editor' => $this->editorId, 'format' => $format_id);
+
+ $plugin = $this->getMockBuilder('Drupal\editor\Plugin\EditorPluginInterface')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $plugin->expects($this->once())
+ ->method('getPluginDefinition')
+ ->will($this->returnValue(array('provider' => 'test_module')));
+ $plugin->expects($this->once())
+ ->method('getDefaultSettings')
+ ->will($this->returnValue(array()));
+
+ $this->editorPluginManager->expects($this->any())
+ ->method('createInstance')
+ ->with($this->editorId)
+ ->will($this->returnValue($plugin));
+
+ $entity = new Editor($values, $this->entityTypeId);
+
+ $filter_format = $this->getMock('Drupal\Core\Config\Entity\ConfigEntityInterface');
+ $filter_format->expects($this->once())
+ ->method('getConfigDependencyName')
+ ->will($this->returnValue('filter.format.test'));
+
+ $storage = $this->getMock('Drupal\Core\Entity\EntityStorageControllerInterface');
+ $storage->expects($this->once())
+ ->method('load')
+ ->with($format_id)
+ ->will($this->returnValue($filter_format));
+
+ $this->entityManager->expects($this->once())
+ ->method('getStorageController')
+ ->with('filter_format')
+ ->will($this->returnValue($storage));
+
+ $dependencies = $entity->calculateDependencies();
+ $this->assertContains('test_module', $dependencies['module']);
+ $this->assertContains('filter.format.test', $dependencies['entity']);
+ }
+
+}
diff --git a/core/modules/entity/config/schema/entity.schema.yml b/core/modules/entity/config/schema/entity.schema.yml
index 6334cb4..0c2d73d 100644
--- a/core/modules/entity/config/schema/entity.schema.yml
+++ b/core/modules/entity/config/schema/entity.schema.yml
@@ -25,6 +25,9 @@ entity.view_mode.*.*:
langcode:
type: string
label: 'Default language'
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
entity.form_mode.*.*:
type: mapping
@@ -51,6 +54,9 @@ entity.form_mode.*.*:
langcode:
type: string
label: 'Default language'
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
# Overview configuration information for view mode or form mode displays.
entity.view_display.*.*.*:
@@ -86,6 +92,9 @@ entity.view_display.*.*.*:
sequence:
- type: boolean
label: 'Value'
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
# Overview configuration information for form mode displays.
entity.form_display.*.*.*:
@@ -115,6 +124,9 @@ entity.form_display.*.*.*:
status:
type: boolean
label: 'Enabled'
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
# Default schema for entity display field with undefined type.
entity_view_display.field.*:
diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
index fd3ddfe..1a2bc5e 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
@@ -11,6 +11,7 @@ use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\Core\Entity\EntityStorageControllerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Entity\Display\EntityDisplayInterface;
+use Drupal\field\Field;
/**
* Provides a common base class for entity view and form displays.
@@ -143,6 +144,43 @@ abstract class EntityDisplayBase extends ConfigEntityBase implements EntityDispl
public function preSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) {
// Sort elements by weight before saving.
uasort($this->content, 'Drupal\Component\Utility\SortArray::sortByWeightElement');
+ parent::preSave($storage_controller, $update);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+ $target_entity_type = \Drupal::entityManager()->getDefinition($this->targetEntityType);
+
+ $bundle_entity_type_id = $target_entity_type->getBundleEntityType();
+ if ($bundle_entity_type_id != 'bundle') {
+ // If the target entity type uses entities to manage its bundles then
+ // depend on the bundle entity.
+ $bundle_entity = \Drupal::entityManager()->getStorageController($bundle_entity_type_id)->load($this->bundle);
+ $this->addDependency('entity', $bundle_entity->getConfigDependencyName());
+ }
+ // Create dependencies on both hidden and visible fields.
+ $fields = $this->content + $this->hidden;
+ foreach ($fields as $field_name => $component) {
+ $field_instance = Field::fieldInfo()->getInstance($this->targetEntityType, $this->bundle, $field_name);
+ if ($field_instance) {
+ $this->addDependency('entity', $field_instance->getConfigDependencyName());
+ }
+ // Create a dependency on the module that provides the formatter or
+ // widget.
+ if (isset($component['type'])) {
+ $definition = $this->pluginManager->getDefinition($component['type']);
+ $this->addDependency('module', $definition['provider']);
+ }
+ }
+ // Depend on configured modes.
+ if ($this->mode != 'default') {
+ $mode_entity = \Drupal::entityManager()->getStorageController($this->displayContext . '_mode')->load($target_entity_type->id() . '.' . $this->mode);
+ $this->addDependency('entity', $mode_entity->getConfigDependencyName());
+ }
+ return $this->dependencies;
}
/**
@@ -168,6 +206,7 @@ abstract class EntityDisplayBase extends ConfigEntityBase implements EntityDispl
'content',
'hidden',
'status',
+ 'dependencies'
);
$properties = array();
foreach ($names as $name) {
diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php
index 6705f03..29ddcfb 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php
@@ -75,4 +75,14 @@ abstract class EntityDisplayModeBase extends ConfigEntityBase implements EntityD
return $this->targetEntityType;
}
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+ $target_entity_type = \Drupal::entityManager()->getDefinition($this->targetEntityType);
+ $this->addDependency('module', $target_entity_type->getProvider());
+ return $this->dependencies;
+ }
+
}
diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php
index b78131b..31ea4e8 100644
--- a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php
+++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php
@@ -14,7 +14,7 @@ use Drupal\simpletest\DrupalUnitTestBase;
*/
class EntityDisplayTest extends DrupalUnitTestBase {
- public static $modules = array('entity', 'field', 'entity_test', 'user', 'text');
+ public static $modules = array('entity', 'field', 'entity_test', 'user', 'text', 'entity_test');
public static function getInfo() {
return array(
@@ -76,9 +76,12 @@ class EntityDisplayTest extends DrupalUnitTestBase {
// Check that CreateCopy() creates a new component that can be correclty
// saved.
+ entity_create('view_mode', array('id' => $display->targetEntityType . '.other_view_mode', 'targetEntityType' => $display->targetEntityType))->save();
$new_display = $display->createCopy('other_view_mode');
$new_display->save();
$new_display = entity_load('entity_view_display', $new_display->id());
+ $dependencies = $new_display->calculateDependencies();
+ $this->assertEqual(array('entity' => array('entity.view_mode.entity_test.other_view_mode')), $dependencies);
$this->assertEqual($new_display->targetEntityType, $display->targetEntityType);
$this->assertEqual($new_display->bundle, $display->bundle);
$this->assertEqual($new_display->mode, 'other_view_mode');
@@ -188,16 +191,10 @@ class EntityDisplayTest extends DrupalUnitTestBase {
$this->assertEqual($formatter->getPluginId(), 'field_test_multiple');
$this->assertFalse(isset($formatter->randomValue));
- // Check that specifying an unknown formatter (e.g. case of a disabled
- // module) gets stored as is in the display, but results in the default
- // formatter being used.
- $display->setComponent($field_name, array(
- 'type' => 'unknown_formatter',
- ));
- $options = $display->getComponent($field_name);
- $this->assertEqual($options['type'], 'unknown_formatter');
- $formatter = $display->getRenderer($field_name);
- $this->assertEqual($formatter->getPluginId(), $default_formatter);
+ // Check that the display has dependencies on the field and the module that
+ // provides the formatter.
+ $dependencies = $display->calculateDependencies();
+ $this->assertEqual(array('entity' => array('field.instance.entity_test.entity_test.test_field'), 'module' => array('field_test')), $dependencies);
}
/**
@@ -287,6 +284,20 @@ class EntityDisplayTest extends DrupalUnitTestBase {
$this->assertEqual('article_rename', $new_form_display->bundle);
$this->assertEqual('node.article_rename.default', $new_form_display->id);
+ $expected_dependencies = array(
+ 'entity' => array('field.instance.node.article_rename.body', 'node.type.article_rename'),
+ 'module' => array('text')
+ );
+ // Check that the display has dependencies on the bundle, fields and the
+ // modules that provide the formatters.
+ $dependencies = $new_display->calculateDependencies();
+ $this->assertEqual($expected_dependencies, $dependencies);
+
+ // Check that the form display has dependencies on the bundle, fields and
+ // the modules that provide the formatters.
+ $dependencies = $new_form_display->calculateDependencies();
+ $this->assertEqual($expected_dependencies, $dependencies);
+
// Delete the bundle.
$type->delete();
$display = entity_load('entity_view_display', 'node.article_rename.default');
@@ -317,6 +328,7 @@ class EntityDisplayTest extends DrupalUnitTestBase {
$instance->save();
// Create default and teaser entity display.
+ entity_create('view_mode', array('id' => 'entity_test.teaser', 'targetEntityType' => 'entity_test'))->save();
entity_create('entity_view_display', array(
'targetEntityType' => 'entity_test',
'bundle' => 'entity_test',
diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php
index 9dad54d..eb0477f 100644
--- a/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php
+++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php
@@ -199,6 +199,7 @@ class EntityFormDisplayTest extends DrupalUnitTestBase {
$instance->save();
// Create default and compact entity display.
+ entity_create('form_mode', array('id' => 'entity_test.compact', 'targetEntityType' => 'entity_test'))->save();
entity_create('entity_form_display', array(
'targetEntityType' => 'entity_test',
'bundle' => 'entity_test',
diff --git a/core/modules/field/config/schema/field.schema.yml b/core/modules/field/config/schema/field.schema.yml
index e1fe2c0..3871ee2 100644
--- a/core/modules/field/config/schema/field.schema.yml
+++ b/core/modules/field/config/schema/field.schema.yml
@@ -56,6 +56,9 @@ field.field.*.*:
sequence:
- type: string
label: 'Column'
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
field.instance.*.*.*:
type: mapping
@@ -104,6 +107,9 @@ field.instance.*.*.*:
field_type:
type: string
label: 'Field type'
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
entity_form_display.field.hidden:
type: entity_field_form_display_base
diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php b/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php
index 96e2cd1..20ff0de 100644
--- a/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php
+++ b/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php
@@ -252,6 +252,7 @@ class FieldConfig extends ConfigEntityBase implements FieldConfigInterface {
'cardinality',
'translatable',
'indexes',
+ 'dependencies',
);
$properties = array();
foreach ($names as $name) {
@@ -273,10 +274,14 @@ class FieldConfig extends ConfigEntityBase implements FieldConfigInterface {
unset($this->schema);
if ($this->isNew()) {
- return $this->preSaveNew($storage_controller);
+ $this->preSaveNew($storage_controller);
}
else {
- return $this->preSaveUpdated($storage_controller);
+ $this->preSaveUpdated($storage_controller);
+ }
+ if (!$this->isSyncing()) {
+ // Ensure the correct dependencies are present.
+ $this->calculateDependencies();
}
}
@@ -328,6 +333,16 @@ class FieldConfig extends ConfigEntityBase implements FieldConfigInterface {
}
/**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+ // Ensure the field is dependent on the providing module.
+ $this->addDependency('module', $this->module);
+ return $this->dependencies;
+ }
+
+ /**
* Prepares saving an updated field definition.
*
* @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
@@ -415,6 +430,7 @@ class FieldConfig extends ConfigEntityBase implements FieldConfigInterface {
$deleted_fields[$field->uuid] = $config;
}
}
+
$state->set('field.field.deleted', $deleted_fields);
}
diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php
index 61add25..2b8e87f 100644
--- a/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php
+++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php
@@ -12,6 +12,7 @@ use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageControllerInterface;
use Drupal\Core\Field\FieldDefinition;
use Drupal\Core\Field\TypedData\FieldItemDataDefinition;
+use Drupal\field\Field;
use Drupal\field\FieldException;
use Drupal\field\FieldInstanceConfigInterface;
@@ -235,7 +236,7 @@ class FieldInstanceConfig extends ConfigEntityBase implements FieldInstanceConfi
// 'uuid' entry is present too, so that leftover 'field_uuid' entries
// present in config files imported as "default module config" are ignored.
if (isset($values['field_uuid']) && isset($values['uuid'])) {
- $field = field_info_field_by_id($values['field_uuid']);
+ $field = Field::fieldInfo()->getFieldById($values['field_uuid']);
if (!$field) {
throw new FieldException(format_string('Attempt to create an instance of unknown field @uuid', array('@uuid' => $values['field_uuid'])));
}
@@ -245,7 +246,7 @@ class FieldInstanceConfig extends ConfigEntityBase implements FieldInstanceConfi
// easier DX on creation of new instances (either through programmatic
// creation / or through import of default config files).
elseif (isset($values['field_name']) && isset($values['entity_type'])) {
- $field = field_info_field($values['entity_type'], $values['field_name']);
+ $field = Field::fieldInfo()->getField($values['entity_type'], $values['field_name']);
if (!$field) {
throw new FieldException(format_string('Attempt to create an instance of field @field_name that does not exist on entity type @entity_type.', array('@field_name' => $values['field_name'], '@entity_type' => $values['entity_type'])));
}
@@ -304,6 +305,7 @@ class FieldInstanceConfig extends ConfigEntityBase implements FieldInstanceConfi
'default_value',
'default_value_function',
'settings',
+ 'dependencies',
);
$properties = array();
foreach ($names as $name) {
@@ -353,6 +355,20 @@ class FieldInstanceConfig extends ConfigEntityBase implements FieldInstanceConfi
// Notify the entity storage controller.
$entity_manager->getStorageController($this->entity_type)->onInstanceUpdate($this);
}
+ if (!$this->isSyncing()) {
+ // Ensure the correct dependencies are present.
+ $this->calculateDependencies();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+ // Manage dependencies.
+ $this->addDependency('entity', $this->field->getConfigDependencyName());
+ return $this->dependencies;
}
/**
@@ -409,7 +425,7 @@ class FieldInstanceConfig extends ConfigEntityBase implements FieldInstanceConfi
$fields_to_delete = array();
foreach ($instances as $instance) {
$field = $instance->getField();
- if (!$instance->deleted && empty($instance->noFieldDelete) && count($field->getBundles()) == 0) {
+ if (!$instance->deleted && empty($instance->noFieldDelete) && !$instance->isUninstalling() && count($field->getBundles()) == 0) {
// Key by field UUID to avoid deleting the same field twice.
$fields_to_delete[$instance->field_uuid] = $field;
}
diff --git a/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php b/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php
index 90c8e56..88001f0 100644
--- a/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php
@@ -104,6 +104,7 @@ class DisplayApiTest extends FieldUnitTestBase {
->setComponent($this->field_name, $this->display_options['default'])
->save();
// Create a display for the teaser view mode.
+ entity_create('view_mode', array('id' => 'entity_test.teaser', 'targetEntityType' => 'entity_test'))->save();
entity_get_display($instance['entity_type'], $instance['bundle'], 'teaser')
->setComponent($this->field_name, $this->display_options['teaser'])
->save();
diff --git a/core/modules/field/tests/Drupal/field/Tests/FieldConfigEntityUnitTest.php b/core/modules/field/tests/Drupal/field/Tests/FieldConfigEntityUnitTest.php
new file mode 100644
index 0000000..59f3359
--- /dev/null
+++ b/core/modules/field/tests/Drupal/field/Tests/FieldConfigEntityUnitTest.php
@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field\Tests\FieldConfigEntityUnitTest.
+ */
+
+namespace Drupal\field\Tests;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\field\Entity\FieldConfig;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\field\Entity\FieldConfig
+ *
+ * @group Drupal
+ * @group Config
+ */
+class FieldConfigEntityUnitTest extends UnitTestCase {
+
+ /**
+ * The entity type used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityType;
+
+ /**
+ * The entity manager used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityManager;
+
+ /**
+ * The ID of the type of the entity under test.
+ *
+ * @var string
+ */
+ protected $entityTypeId;
+
+ /**
+ * The UUID generator used for testing.
+ *
+ * @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $uuid;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getInfo() {
+ return array(
+ 'description' => '',
+ 'name' => '\Drupal\field\Entity\FieldConfig unit test',
+ 'group' => 'Entity',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUp() {
+ $this->entityTypeId = $this->randomName();
+
+ $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $this->entityType->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue('entity'));
+
+ $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
+ $this->entityManager->expects($this->any())
+ ->method('getDefinition')
+ ->with($this->entityTypeId)
+ ->will($this->returnValue($this->entityType));
+
+ $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
+
+ $container = new ContainerBuilder();
+ $container->set('entity.manager', $this->entityManager);
+ $container->set('uuid', $this->uuid);
+ \Drupal::setContainer($container);
+
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependencies() {
+ $values = array('name' => 'test_field', 'type' => 'test_field_type', 'entity_type' => 'test_entity_type', 'module' => 'test_module');
+ $entity = new FieldConfig($values, $this->entityTypeId);
+ $dependencies = $entity->calculateDependencies();
+ $this->assertContains('test_module', $dependencies['module']);
+ }
+
+}
diff --git a/core/modules/field/tests/Drupal/field/Tests/FieldInstanceConfigEntityUnitTest.php b/core/modules/field/tests/Drupal/field/Tests/FieldInstanceConfigEntityUnitTest.php
new file mode 100644
index 0000000..9bde1ec
--- /dev/null
+++ b/core/modules/field/tests/Drupal/field/Tests/FieldInstanceConfigEntityUnitTest.php
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field\Tests\FieldInstanceConfigEntityUnitTest.
+ */
+
+namespace Drupal\field\Tests;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\field\Entity\FieldInstanceConfig;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\field\Entity\FieldInstanceConfig
+ *
+ * @group Drupal
+ * @group Config
+ */
+class FieldInstanceConfigEntityUnitTest extends UnitTestCase {
+
+ /**
+ * The entity type used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityType;
+
+ /**
+ * The entity manager used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityManager;
+
+ /**
+ * The ID of the type of the entity under test.
+ *
+ * @var string
+ */
+ protected $entityTypeId;
+
+ /**
+ * The UUID generator used for testing.
+ *
+ * @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $uuid;
+
+ /**
+ * The field info provider.
+ *
+ * @var \Drupal\field\FieldInfo|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $fieldInfo;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getInfo() {
+ return array(
+ 'description' => '',
+ 'name' => '\Drupal\field\Entity\FieldInstanceConfig unit test',
+ 'group' => 'Entity',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUp() {
+ $this->entityTypeId = $this->randomName();
+
+ $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $this->entityType->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue('entity'));
+
+ $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
+ $this->entityManager->expects($this->any())
+ ->method('getDefinition')
+ ->with($this->entityTypeId)
+ ->will($this->returnValue($this->entityType));
+
+ $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
+
+ $this->fieldInfo = $this->getMockBuilder('\Drupal\field\FieldInfo')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $container = new ContainerBuilder();
+ $container->set('entity.manager', $this->entityManager);
+ $container->set('uuid', $this->uuid);
+ $container->set('field.info', $this->fieldInfo);
+ \Drupal::setContainer($container);
+
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependencies() {
+ $field = $this->getMock('\Drupal\field\FieldConfigInterface');
+ // The field name property is public and accessed this way in the field
+ // instance config entity constructor.
+ $field->name = 'test_field';
+ $field->expects($this->once())
+ ->method('getConfigDependencyName')
+ ->will($this->returnValue('field.field.test_entity_type.test_field'));
+ $this->fieldInfo->expects($this->any())
+ ->method('getField')
+ ->with('test_entity_type', 'test_field')
+ ->will($this->returnValue($field));
+ $values = array('field_name' => 'test_field', 'entity_type' => 'test_entity_type', $this->entityTypeId, 'bundle' => 'test_bundle');
+ $entity = new FieldInstanceConfig($values, $this->entityTypeId);
+ $dependencies = $entity->calculateDependencies();
+ $this->assertContains('field.field.test_entity_type.test_field', $dependencies['entity']);
+ }
+
+}
diff --git a/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import.yml b/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import.yml
index 20b5662..28036f9 100644
--- a/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import.yml
+++ b/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import.yml
@@ -12,3 +12,6 @@ translatable: false
indexes:
format:
- format
+dependencies:
+ module:
+ - text
diff --git a/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import_2.yml b/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import_2.yml
index a94a715..4c2042b 100644
--- a/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import_2.yml
+++ b/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import_2.yml
@@ -12,3 +12,6 @@ translatable: false
indexes:
format:
- format
+dependencies:
+ module:
+ - text
diff --git a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging.yml b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging.yml
index 127a97a..f4b6e1a 100644
--- a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging.yml
+++ b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging.yml
@@ -13,3 +13,6 @@ translatable: '0'
indexes:
format:
- format
+dependencies:
+ module:
+ - text
diff --git a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging_2.yml b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging_2.yml
index 017e9db..8bb4272 100644
--- a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging_2.yml
+++ b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging_2.yml
@@ -13,3 +13,6 @@ translatable: '0'
indexes:
format:
- format
+dependencies:
+ module:
+ - text
diff --git a/core/modules/file/config/views.view.files.yml b/core/modules/file/config/views.view.files.yml
index ea17b1e..cc7d114 100644
--- a/core/modules/file/config/views.view.files.yml
+++ b/core/modules/file/config/views.view.files.yml
@@ -1050,3 +1050,6 @@ module: file
id: files
tag: default
langcode: en
+dependencies:
+ module:
+ - file
diff --git a/core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml b/core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml
index 91ea8ec..ff9133f 100644
--- a/core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml
+++ b/core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml
@@ -8,3 +8,6 @@ content:
weight: -5
description:
weight: 0
+dependencies:
+ entity:
+ - taxonomy.vocabulary.forums
diff --git a/core/modules/forum/config/entity.view_display.taxonomy_term.forums.default.yml b/core/modules/forum/config/entity.view_display.taxonomy_term.forums.default.yml
index 4e3733a..cefa753 100644
--- a/core/modules/forum/config/entity.view_display.taxonomy_term.forums.default.yml
+++ b/core/modules/forum/config/entity.view_display.taxonomy_term.forums.default.yml
@@ -8,3 +8,6 @@ content:
weight: 0
hidden: { }
status: true
+dependencies:
+ entity:
+ - taxonomy.vocabulary.forums
diff --git a/core/modules/forum/config/field.field.forum.forum_container.yml b/core/modules/forum/config/field.field.forum.forum_container.yml
index 4c20672..af5ebf2 100644
--- a/core/modules/forum/config/field.field.forum.forum_container.yml
+++ b/core/modules/forum/config/field.field.forum.forum_container.yml
@@ -14,3 +14,6 @@ locked: true
cardinality: 1
translatable: false
indexes: { }
+dependencies:
+ module:
+ - options
diff --git a/core/modules/forum/config/field.instance.taxonomy_term.forums.forum_container.yml b/core/modules/forum/config/field.instance.taxonomy_term.forums.forum_container.yml
index 66feae9..e91a93b 100644
--- a/core/modules/forum/config/field.instance.taxonomy_term.forums.forum_container.yml
+++ b/core/modules/forum/config/field.instance.taxonomy_term.forums.forum_container.yml
@@ -13,3 +13,6 @@ default_value:
default_value_function: ''
settings: { }
field_type: list_boolean
+dependencies:
+ entity:
+ - field.field.forum.forum_container
diff --git a/core/modules/forum/config/rdf.mapping.node.forum.yml b/core/modules/forum/config/rdf.mapping.node.forum.yml
index fc47f15..7db68c7 100644
--- a/core/modules/forum/config/rdf.mapping.node.forum.yml
+++ b/core/modules/forum/config/rdf.mapping.node.forum.yml
@@ -31,3 +31,8 @@ fieldMappings:
callable: 'Drupal\rdf\SchemaOrgDataConverter::interactionCount'
arguments:
interaction_type: 'UserComments'
+dependencies:
+ entity:
+ - node.type.forum
+ module:
+ - node
diff --git a/core/modules/forum/config/rdf.mapping.taxonomy_term.forums.yml b/core/modules/forum/config/rdf.mapping.taxonomy_term.forums.yml
index aaaf536..be766eb 100644
--- a/core/modules/forum/config/rdf.mapping.taxonomy_term.forums.yml
+++ b/core/modules/forum/config/rdf.mapping.taxonomy_term.forums.yml
@@ -11,3 +11,8 @@ fieldMappings:
description:
properties:
- 'schema:description'
+dependencies:
+ entity:
+ - taxonomy.vocabulary.forums
+ module:
+ - taxonomy
diff --git a/core/modules/language/lib/Drupal/language/Entity/Language.php b/core/modules/language/lib/Drupal/language/Entity/Language.php
index c7ad236..e168aa5 100644
--- a/core/modules/language/lib/Drupal/language/Entity/Language.php
+++ b/core/modules/language/lib/Drupal/language/Entity/Language.php
@@ -96,7 +96,7 @@ class Language extends ConfigEntityBase implements LanguageInterface {
public static function preDelete(EntityStorageControllerInterface $storage_controller, array $entities) {
$default_language = \Drupal::service('language.default')->get();
foreach ($entities as $entity) {
- if ($entity->id() == $default_language->id) {
+ if ($entity->id() == $default_language->id && !$entity->isUninstalling()) {
throw new DeleteDefaultLanguageException('Can not delete the default language');
}
}
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php
index f7c64bf..c4c5be2 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php
@@ -131,7 +131,7 @@ class LocaleConfigTranslationTest extends WebTestBase {
// Enable the image module.
$this->drupalPostForm('admin/modules', array('modules[Field types][image][enable]' => "1"), t('Save configuration'));
- $this->resetAll();
+ $this->rebuildContainer();
$string = $this->storage->findString(array('source' => 'Medium (220x220)', 'context' => '', 'type' => 'configuration'));
$this->assertTrue($string, 'Configuration strings have been created upon installation.');
diff --git a/core/modules/node/config/entity.view_mode.node.full.yml b/core/modules/node/config/entity.view_mode.node.full.yml
index fce4bf4..3a8654a 100644
--- a/core/modules/node/config/entity.view_mode.node.full.yml
+++ b/core/modules/node/config/entity.view_mode.node.full.yml
@@ -3,3 +3,6 @@ label: 'Full content'
status: false
cache: true
targetEntityType: node
+dependencies:
+ module:
+ - node
diff --git a/core/modules/node/config/entity.view_mode.node.rss.yml b/core/modules/node/config/entity.view_mode.node.rss.yml
index 3e7414c..6a79ca5 100644
--- a/core/modules/node/config/entity.view_mode.node.rss.yml
+++ b/core/modules/node/config/entity.view_mode.node.rss.yml
@@ -3,3 +3,6 @@ label: RSS
status: false
cache: true
targetEntityType: node
+dependencies:
+ module:
+ - node
diff --git a/core/modules/search/config/entity.view_mode.node.search_index.yml b/core/modules/node/config/entity.view_mode.node.search_index.yml
index af5fd59..54385d9 100644
--- a/core/modules/search/config/entity.view_mode.node.search_index.yml
+++ b/core/modules/node/config/entity.view_mode.node.search_index.yml
@@ -3,3 +3,6 @@ label: 'Search index'
status: false
cache: true
targetEntityType: node
+dependencies:
+ module:
+ - node
diff --git a/core/modules/search/config/entity.view_mode.node.search_result.yml b/core/modules/node/config/entity.view_mode.node.search_result.yml
index 178a11c..9d5c913 100644
--- a/core/modules/search/config/entity.view_mode.node.search_result.yml
+++ b/core/modules/node/config/entity.view_mode.node.search_result.yml
@@ -3,3 +3,6 @@ label: 'Search result'
status: false
cache: true
targetEntityType: node
+dependencies:
+ module:
+ - node
diff --git a/core/modules/node/config/entity.view_mode.node.teaser.yml b/core/modules/node/config/entity.view_mode.node.teaser.yml
index 875d61f..be00b8d 100644
--- a/core/modules/node/config/entity.view_mode.node.teaser.yml
+++ b/core/modules/node/config/entity.view_mode.node.teaser.yml
@@ -3,3 +3,6 @@ label: Teaser
status: true
cache: true
targetEntityType: node
+dependencies:
+ module:
+ - node
diff --git a/core/modules/node/config/search.page.node_search.yml b/core/modules/node/config/search.page.node_search.yml
index e4ea66e..440c135 100644
--- a/core/modules/node/config/search.page.node_search.yml
+++ b/core/modules/node/config/search.page.node_search.yml
@@ -7,3 +7,6 @@ weight: -10
plugin: node_search
configuration:
rankings: { }
+dependencies:
+ module:
+ - node
diff --git a/core/modules/node/config/system.action.node_delete_action.yml b/core/modules/node/config/system.action.node_delete_action.yml
index deceb87..af4ce28 100644
--- a/core/modules/node/config/system.action.node_delete_action.yml
+++ b/core/modules/node/config/system.action.node_delete_action.yml
@@ -4,3 +4,6 @@ status: true
langcode: en
type: node
plugin: node_delete_action
+dependencies:
+ module:
+ - node
diff --git a/core/modules/node/config/system.action.node_make_sticky_action.yml b/core/modules/node/config/system.action.node_make_sticky_action.yml
index 104f92c..04276c0 100644
--- a/core/modules/node/config/system.action.node_make_sticky_action.yml
+++ b/core/modules/node/config/system.action.node_make_sticky_action.yml
@@ -4,3 +4,6 @@ status: true
langcode: en
type: node
plugin: node_make_sticky_action
+dependencies:
+ module:
+ - node
diff --git a/core/modules/node/config/system.action.node_make_unsticky_action.yml b/core/modules/node/config/system.action.node_make_unsticky_action.yml
index 2207e7d..03a99c5 100644
--- a/core/modules/node/config/system.action.node_make_unsticky_action.yml
+++ b/core/modules/node/config/system.action.node_make_unsticky_action.yml
@@ -4,3 +4,6 @@ status: true
langcode: en
type: node
plugin: node_make_unsticky_action
+dependencies:
+ module:
+ - node
diff --git a/core/modules/node/config/system.action.node_save_action.yml b/core/modules/node/config/system.action.node_save_action.yml
index 0864be5..4dc2073 100644
--- a/core/modules/node/config/system.action.node_save_action.yml
+++ b/core/modules/node/config/system.action.node_save_action.yml
@@ -4,3 +4,6 @@ status: true
langcode: en
type: node
plugin: node_save_action
+dependencies:
+ module:
+ - node
diff --git a/core/modules/node/config/system.action.node_unpromote_action.yml b/core/modules/node/config/system.action.node_unpromote_action.yml
index 2b9cc1f..21c0ae8 100644
--- a/core/modules/node/config/system.action.node_unpromote_action.yml
+++ b/core/modules/node/config/system.action.node_unpromote_action.yml
@@ -4,3 +4,6 @@ status: true
langcode: en
type: node
plugin: node_unpromote_action
+dependencies:
+ module:
+ - node
diff --git a/core/modules/node/config/system.action.node_unpublish_action.yml b/core/modules/node/config/system.action.node_unpublish_action.yml
index 1b70c4f..2e01fae 100644
--- a/core/modules/node/config/system.action.node_unpublish_action.yml
+++ b/core/modules/node/config/system.action.node_unpublish_action.yml
@@ -4,3 +4,6 @@ status: true
langcode: en
type: node
plugin: node_unpublish_action
+dependencies:
+ module:
+ - node
diff --git a/core/modules/views/config/views.view.archive.yml b/core/modules/node/config/views.view.archive.yml
index d64c243..1151b1a 100644
--- a/core/modules/views/config/views.view.archive.yml
+++ b/core/modules/node/config/views.view.archive.yml
@@ -171,3 +171,6 @@ module: node
id: archive
tag: default
langcode: en
+dependencies:
+ module:
+ - node
diff --git a/core/modules/node/config/views.view.content.yml b/core/modules/node/config/views.view.content.yml
index cb0ec4f..074c5b5 100644
--- a/core/modules/node/config/views.view.content.yml
+++ b/core/modules/node/config/views.view.content.yml
@@ -349,6 +349,7 @@ display:
hide_alter_empty: true
link_to_node: false
comments: false
+ optional: true
plugin_id: history_user_timestamp
provider: history
filters:
@@ -558,3 +559,7 @@ module: node
id: content
tag: default
langcode: en
+dependencies:
+ module:
+ - node
+ - user
diff --git a/core/modules/node/config/views.view.content_recent.yml b/core/modules/node/config/views.view.content_recent.yml
index 45edb2f..09993b7 100644
--- a/core/modules/node/config/views.view.content_recent.yml
+++ b/core/modules/node/config/views.view.content_recent.yml
@@ -207,6 +207,7 @@ display:
hide_alter_empty: true
link_to_node: false
comments: false
+ optional: true
plugin_id: history_user_timestamp
provider: history
name:
@@ -462,7 +463,11 @@ display:
link_url: admin/content
block_category: 'Lists (Views)'
label: 'Recent content'
-module: views
+module: node
id: content_recent
tag: default
langcode: en
+dependencies:
+ module:
+ - node
+ - user
diff --git a/core/modules/node/config/views.view.frontpage.yml b/core/modules/node/config/views.view.frontpage.yml
index 9efe139..a6928ab 100644
--- a/core/modules/node/config/views.view.frontpage.yml
+++ b/core/modules/node/config/views.view.frontpage.yml
@@ -238,3 +238,6 @@ module: node
id: frontpage
tag: default
langcode: en
+dependencies:
+ module:
+ - node
diff --git a/core/modules/views/config/views.view.glossary.yml b/core/modules/node/config/views.view.glossary.yml
index 882012e..0edc991 100644
--- a/core/modules/views/config/views.view.glossary.yml
+++ b/core/modules/node/config/views.view.glossary.yml
@@ -379,3 +379,7 @@ module: node
id: glossary
tag: default
langcode: en
+dependencies:
+ module:
+ - node
+ - user
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php
index 74cd9c7..ee9f7cd 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php
@@ -35,6 +35,7 @@ class NodeAccessPagerTest extends WebTestBase {
parent::setUp();
node_access_rebuild();
+ $this->drupalCreateContentType(array('type' => 'page', 'name' => t('Basic page')));
$this->container->get('comment.manager')->addDefaultField('node', 'page');
$this->web_user = $this->drupalCreateUser(array('access content', 'access comments', 'node test view'));
}
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index c97851e..7603db3 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -446,12 +446,18 @@ function node_add_body_field(NodeTypeInterface $type, $label = 'Body') {
'type' => 'text_default',
))
->save();
- entity_get_display('node', $type->type, 'teaser')
- ->setComponent('body', array(
- 'label' => 'hidden',
- 'type' => 'text_summary_or_trimmed',
- ))
- ->save();
+
+ // The teaser view mode is created by the Standard profile and therefore
+ // might not exist.
+ $view_modes = entity_get_view_modes('node');
+ if (isset($view_modes['teaser'])) {
+ entity_get_display('node', $type->type, 'teaser')
+ ->setComponent('body', array(
+ 'label' => 'hidden',
+ 'type' => 'text_summary_or_trimmed',
+ ))
+ ->save();
+ }
}
return $instance;
diff --git a/core/modules/rdf/config/schema/rdf.schema.yml b/core/modules/rdf/config/schema/rdf.schema.yml
index 570d602..ae43ef1 100644
--- a/core/modules/rdf/config/schema/rdf.schema.yml
+++ b/core/modules/rdf/config/schema/rdf.schema.yml
@@ -26,3 +26,6 @@ rdf.mapping.*.*:
label: 'Field mappings'
sequence:
- type: rdf_field_mapping
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
diff --git a/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php b/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php
index f2d3257..4c5284f 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php
@@ -149,12 +149,33 @@ class RdfMapping extends ConfigEntityBase implements RdfMappingInterface {
foreach ($names as $name) {
$properties[$name] = $this->get($name);
}
+ if (!empty($this->dependencies)) {
+ // Add protected dependencies property if set.
+ $properties['dependencies'] = $this->dependencies;
+ }
return $properties;
}
/**
* {@inheritdoc}
*/
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+ $entity_type = \Drupal::entityManager()->getDefinition($this->targetEntityType);
+ $this->addDependency('module', $entity_type->getProvider());
+ $bundle_entity_type_id = $entity_type->getBundleEntityType();
+ if ($bundle_entity_type_id != 'bundle') {
+ // If the target entity type uses entities to manage its bundles then
+ // depend on the bundle entity.
+ $bundle_entity = \Drupal::entityManager()->getStorageController($bundle_entity_type_id)->load($this->bundle);
+ $this->addDependency('entity', $bundle_entity->getConfigDependencyName());
+ }
+ return $this->dependencies;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) {
parent::postSave($storage_controller, $update);
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/Field/EmailFieldRdfaTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/Field/EmailFieldRdfaTest.php
index 32e060b..4a3550d 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/Field/EmailFieldRdfaTest.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/Field/EmailFieldRdfaTest.php
@@ -53,7 +53,7 @@ class EmailFieldRdfaTest extends FieldRdfaTestBase {
*/
public function testAllFormatters() {
// Test the plain formatter.
- $this->assertFormatterRdfa('text_plain', 'http://schema.org/email', $this->testValue);
+ $this->assertFormatterRdfa('string', 'http://schema.org/email', $this->testValue);
// Test the mailto formatter.
$this->assertFormatterRdfa('email_mailto', 'http://schema.org/email', $this->testValue);
}
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaAttributesTest.php
index 03500bd..726e78b 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaAttributesTest.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaAttributesTest.php
@@ -135,9 +135,8 @@ class RdfaAttributesTest extends DrupalUnitTestBase {
* The data to pass into the datatype callback, if specified.
*/
protected function _testAttributes($expected_attributes, $field_mapping, $data = NULL) {
- $this->saveMapping($field_mapping);
-
$mapping = rdf_get_mapping('node', 'article')
+ ->setFieldMapping('field_test', $field_mapping)
->getPreparedFieldMapping('field_test');
$attributes = rdf_rdfa_attributes($mapping, $data);
ksort($expected_attributes);
@@ -145,15 +144,4 @@ class RdfaAttributesTest extends DrupalUnitTestBase {
$this->assertEqual($expected_attributes, $attributes);
}
- /**
- * Helper function to save mapping using config system.
- *
- * @param array $field_mapping
- * The field mapping.
- */
- protected function saveMapping($field_mapping) {
- rdf_get_mapping('node', 'article')
- ->setFieldMapping('field_test', $field_mapping)
- ->save();
- }
}
diff --git a/core/modules/rdf/tests/Drupal/rdf/Tests/RdfMappingConfigEntityUnitTest.php b/core/modules/rdf/tests/Drupal/rdf/Tests/RdfMappingConfigEntityUnitTest.php
new file mode 100644
index 0000000..1572d9c
--- /dev/null
+++ b/core/modules/rdf/tests/Drupal/rdf/Tests/RdfMappingConfigEntityUnitTest.php
@@ -0,0 +1,162 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\rdf\Tests\RdfMappingEntityUnitTest.
+ */
+
+namespace Drupal\rdf\Tests;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Tests\UnitTestCase;
+use Drupal\rdf\Entity\RdfMapping;
+
+/**
+ * @coversDefaultClass \Drupal\rdf\Entity\RdfMapping
+ *
+ * @group Drupal
+ * @group Config
+ */
+class RdfMappingEntityUnitTest extends UnitTestCase {
+
+ /**
+ * The entity type used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityType;
+
+ /**
+ * The entity manager used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityManager;
+
+ /**
+ * The ID of the type of the entity under test.
+ *
+ * @var string
+ */
+ protected $entityTypeId;
+
+ /**
+ * The UUID generator used for testing.
+ *
+ * @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $uuid;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getInfo() {
+ return array(
+ 'description' => '',
+ 'name' => '\Drupal\field\Entity\RdfMapping unit test',
+ 'group' => 'Entity',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUp() {
+ $this->entityTypeId = $this->randomName();
+
+ $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $this->entityType->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue('entity'));
+
+ $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
+
+ $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
+
+ $container = new ContainerBuilder();
+ $container->set('entity.manager', $this->entityManager);
+ $container->set('uuid', $this->uuid);
+ \Drupal::setContainer($container);
+
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependencies() {
+ $target_entity_type_id = $this->randomName(16);
+
+ $target_entity_type = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $target_entity_type->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue('test_module'));
+ $values = array('targetEntityType' => $target_entity_type_id);
+ $target_entity_type->expects($this->any())
+ ->method('getBundleEntityType')
+ ->will($this->returnValue('bundle'));
+
+ $this->entityManager->expects($this->at(0))
+ ->method('getDefinition')
+ ->with($target_entity_type_id)
+ ->will($this->returnValue($target_entity_type));
+ $this->entityManager->expects($this->at(1))
+ ->method('getDefinition')
+ ->with($this->entityTypeId)
+ ->will($this->returnValue($this->entityType));
+
+ $entity = new RdfMapping($values, $this->entityTypeId);
+ $dependencies = $entity->calculateDependencies();
+ $this->assertArrayNotHasKey('entity', $dependencies);
+ $this->assertContains('test_module', $dependencies['module']);
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependenciesWithEntityBundle() {
+ $target_entity_type_id = $this->randomName(16);
+ $target_entity_type = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $target_entity_type->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue('test_module'));
+ $bundle_id = $this->randomName(10);
+ $values = array('targetEntityType' => $target_entity_type_id , 'bundle' => $bundle_id);
+
+ $bundle_entity_type_id = $this->randomName(17);
+ $bundle_entity = $this->getMock('\Drupal\Core\Config\Entity\ConfigEntityInterface');
+ $bundle_entity
+ ->expects($this->once())
+ ->method('getConfigDependencyName')
+ ->will($this->returnValue('test_module.type.' . $bundle_id));
+
+ $target_entity_type->expects($this->any())
+ ->method('getBundleEntityType')
+ ->will($this->returnValue($bundle_entity_type_id));
+
+ $this->entityManager->expects($this->at(0))
+ ->method('getDefinition')
+ ->with($target_entity_type_id)
+ ->will($this->returnValue($target_entity_type));
+ $this->entityManager->expects($this->at(1))
+ ->method('getDefinition')
+ ->with($this->entityTypeId)
+ ->will($this->returnValue($this->entityType));
+
+ $storage = $this->getMock('Drupal\Core\Entity\EntityStorageControllerInterface');
+ $storage->expects($this->once())
+ ->method('load')
+ ->with($bundle_id)
+ ->will($this->returnValue($bundle_entity));
+
+ $this->entityManager->expects($this->once())
+ ->method('getStorageController')
+ ->with($bundle_entity_type_id)
+ ->will($this->returnValue($storage));
+
+ $entity = new RdfMapping($values, $this->entityTypeId);
+ $dependencies = $entity->calculateDependencies();
+ $this->assertContains('test_module.type.' . $bundle_id, $dependencies['entity']);
+ $this->assertContains('test_module', $dependencies['module']);
+ }
+
+}
diff --git a/core/modules/responsive_image/config/schema/responsive_image.schema.yml b/core/modules/responsive_image/config/schema/responsive_image.schema.yml
index 55a6290..4cdb149 100644
--- a/core/modules/responsive_image/config/schema/responsive_image.schema.yml
+++ b/core/modules/responsive_image/config/schema/responsive_image.schema.yml
@@ -37,6 +37,9 @@ responsive_image.mappings.*:
langcode:
type: string
label: 'Default language'
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
entity_view_display.field.responsive_image:
type: entity_field_view_display_base
diff --git a/core/modules/responsive_image/lib/Drupal/responsive_image/Entity/ResponsiveImageMapping.php b/core/modules/responsive_image/lib/Drupal/responsive_image/Entity/ResponsiveImageMapping.php
index 19b8bcb..408e417 100644
--- a/core/modules/responsive_image/lib/Drupal/responsive_image/Entity/ResponsiveImageMapping.php
+++ b/core/modules/responsive_image/lib/Drupal/responsive_image/Entity/ResponsiveImageMapping.php
@@ -78,6 +78,21 @@ class ResponsiveImageMapping extends ConfigEntityBase implements ResponsiveImage
}
/**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+ if (isset($this->breakpointGroup)) {
+ // @todo Implement toArray() so we do not have reload the
+ // entity since this property is changed in
+ // \Drupal\responsive_image\Entity\ResponsiveImageMapping::save().
+ $breakpoint_group = \Drupal::entityManager()->getStorageController('breakpoint_group')->load($this->breakpointGroup);
+ $this->addDependency('entity', $breakpoint_group->getConfigDependencyName());
+ }
+ return $this->dependencies;
+ }
+
+ /**
* Overrides Drupal\Core\Entity::save().
*/
public function save() {
diff --git a/core/modules/responsive_image/tests/Drupal/responsive_image/Tests/PictureMappingEntityTest.php b/core/modules/responsive_image/tests/Drupal/responsive_image/Tests/PictureMappingEntityTest.php
new file mode 100644
index 0000000..f14c2fe
--- /dev/null
+++ b/core/modules/responsive_image/tests/Drupal/responsive_image/Tests/PictureMappingEntityTest.php
@@ -0,0 +1,137 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\responsive_image\Tests\ResponsiveImageMappingEntityTest.
+ */
+
+namespace Drupal\picture\Tests;
+
+use Drupal\responsive_image\Entity\ResponsiveImageMapping;
+use Drupal\Tests\UnitTestCase;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+
+/**
+ * @coversDefaultClass \Drupal\picture\Entity\PictureMapping
+ *
+ * @group Drupal
+ * @group Config
+ */
+class ResponsiveImageMappingEntityTest extends UnitTestCase {
+
+ /**
+ * The entity type used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityType;
+
+ /**
+ * The entity manager used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityManager;
+
+ /**
+ * The ID of the type of the entity under test.
+ *
+ * @var string
+ */
+ protected $entityTypeId;
+
+ /**
+ * The UUID generator used for testing.
+ *
+ * @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $uuid;
+
+ /**
+ * The ID of the breakpoint group used for testing.
+ *
+ * @var string
+ */
+ protected $breakpointGroupId;
+
+ /**
+ * The breakpoint group used for testing.
+ *
+ * @var \Drupal\breakpoint\Entity\BreakpointGroup|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $breakpointGroup;
+
+ /**
+ * The breakpoint group storage controller used for testing.
+ *
+ * @var \Drupal\Core\Config\Entity\ConfigStorageControllerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $breakpointGroupStorageController;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getInfo() {
+ return array(
+ 'description' => '',
+ 'name' => '\Drupal\responsive_image\Entity\ResponsiveImageMapping unit test',
+ 'group' => 'Picture',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUp() {
+ $this->entityTypeId = $this->randomName();
+ $this->provider = $this->randomName();
+ $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $this->entityType->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue($this->provider));
+
+ $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
+ $this->entityManager->expects($this->any())
+ ->method('getDefinition')
+ ->with($this->entityTypeId)
+ ->will($this->returnValue($this->entityType));
+
+ $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
+
+ $this->breakpointGroupId = $this->randomName(9);
+ $this->breakpointGroup = $this->getMock('Drupal\breakpoint\Entity\BreakpointGroup', array(), array(array('id' => $this->breakpointGroupId)));
+
+ $this->breakpointGroupStorageController = $this->getMock('\Drupal\Core\Config\Entity\ConfigStorageControllerInterface');
+ $this->breakpointGroupStorageController
+ ->expects($this->any())
+ ->method('load')
+ ->with($this->breakpointGroupId)
+ ->will($this->returnValue($this->breakpointGroup));
+
+ $this->entityManager->expects($this->any())
+ ->method('getStorageController')
+ ->will($this->returnValue($this->breakpointGroupStorageController));
+
+ $container = new ContainerBuilder();
+ $container->set('entity.manager', $this->entityManager);
+ $container->set('uuid', $this->uuid);
+ \Drupal::setContainer($container);
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependencies() {
+ $picture_mapping = new ResponsiveImageMapping(array(), $this->entityTypeId);
+ // Set the breakpoint group after creating the entity to avoid the calls
+ // in the constructor.
+ $picture_mapping->breakpointGroup = $this->breakpointGroupId;
+ $this->breakpointGroup->expects($this->once())
+ ->method('getConfigDependencyName')
+ ->will($this->returnValue('breakpoint.breakpoint_group.' . $this->breakpointGroupId));
+
+ $dependencies = $picture_mapping->calculateDependencies();
+ $this->assertContains('breakpoint.breakpoint_group.' . $this->breakpointGroupId, $dependencies['entity']);
+ }
+
+}
diff --git a/core/modules/search/config/schema/search.schema.yml b/core/modules/search/config/schema/search.schema.yml
index 68e6877..e560c37 100644
--- a/core/modules/search/config/schema/search.schema.yml
+++ b/core/modules/search/config/schema/search.schema.yml
@@ -94,3 +94,6 @@ search.page.*:
label: 'Plugin'
configuration:
type: search.plugin.[%parent.plugin]
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml
index 6b82e60..157805c 100644
--- a/core/modules/system/config/schema/system.schema.yml
+++ b/core/modules/system/config/schema/system.schema.yml
@@ -337,6 +337,9 @@ system.action.*:
label: 'Plugin'
configuration:
type: action.configuration.[plugin]
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
system.file:
type: mapping
diff --git a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php
index 738dda2..70fe125 100644
--- a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php
@@ -7,6 +7,8 @@
namespace Drupal\system\Form;
+use Drupal\Core\Config\ConfigManagerInterface;
+use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Form\ConfirmFormBase;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -33,6 +35,20 @@ class ModulesUninstallConfirmForm extends ConfirmFormBase {
protected $keyValueExpirable;
/**
+ * The configuration manager.
+ *
+ * @var \Drupal\Core\Config\ConfigManagerInterface
+ */
+ protected $configManager;
+
+ /**
+ * The entity manager.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface
+ */
+ protected $entityManager;
+
+ /**
* An array of modules to uninstall.
*
* @var array
@@ -46,10 +62,16 @@ class ModulesUninstallConfirmForm extends ConfirmFormBase {
* The module handler.
* @param \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface $key_value_expirable
* The key value expirable factory.
+ * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
+ * The configuration manager.
+ * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+ * The entity manager.
*/
- public function __construct(ModuleHandlerInterface $module_handler, KeyValueStoreExpirableInterface $key_value_expirable) {
+ public function __construct(ModuleHandlerInterface $module_handler, KeyValueStoreExpirableInterface $key_value_expirable, ConfigManagerInterface $config_manager, EntityManagerInterface $entity_manager) {
$this->moduleHandler = $module_handler;
$this->keyValueExpirable = $key_value_expirable;
+ $this->configManager = $config_manager;
+ $this->entityManager = $entity_manager;
}
/**
@@ -58,7 +80,9 @@ class ModulesUninstallConfirmForm extends ConfirmFormBase {
public static function create(ContainerInterface $container) {
return new static(
$container->get('module_handler'),
- $container->get('keyvalue.expirable')->get('modules_uninstall')
+ $container->get('keyvalue.expirable')->get('modules_uninstall'),
+ $container->get('config.manager'),
+ $container->get('entity.manager')
);
}
@@ -121,6 +145,47 @@ class ModulesUninstallConfirmForm extends ConfirmFormBase {
}, $this->modules),
);
+ $form['entities'] = array(
+ '#type' => 'details',
+ '#title' => $this->t('Configuration deletions'),
+ '#description' => $this->t('The listed configuration will be deleted.'),
+ '#collapsible' => TRUE,
+ '#collapsed' => TRUE,
+ '#access' => FALSE,
+ );
+
+ // Get the dependent entities.
+ $entity_types = array();
+ $dependent_entities = $this->configManager->findConfigEntityDependentsAsEntities('module', $this->modules);
+ foreach ($dependent_entities as $entity) {
+ $entity_type_id = $entity->getEntityTypeId();
+ if (!isset($form['entities'][$entity_type_id])) {
+ $entity_type = $this->entityManager->getDefinition($entity_type_id);
+ // Store the ID and label to sort the entity types and entities later.
+ $label = $entity_type->getLabel();
+ $entity_types[$entity_type_id] = $label;
+ $form['entities'][$entity_type_id] = array(
+ '#theme' => 'item_list',
+ '#title' => $label,
+ '#items' => array(),
+ );
+ }
+ $form['entities'][$entity_type_id]['#items'][] = $entity->label();
+ }
+ if (!empty($dependent_entities)) {
+ $form['entities']['#access'] = TRUE;
+
+ // Add a weight key to the entity type sections.
+ asort($entity_types, SORT_FLAG_CASE);
+ $weight = 0;
+ foreach ($entity_types as $entity_type_id => $label) {
+ $form['entities'][$entity_type_id]['#weight'] = $weight;
+ // Sort the list of entity labels alphabetically.
+ sort($form['entities'][$entity_type_id]['#items'], SORT_FLAG_CASE);
+ $weight++;
+ }
+ }
+
return parent::buildForm($form, $form_state);
}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php b/core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php
index 93b3b28..5eb13e5 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php
@@ -48,7 +48,7 @@ class MultiFormTest extends AjaxTestBase {
'bundle' => 'page',
))->save();
entity_get_form_display('node', 'page', 'default')
- ->setComponent($field_name, array('type' => 'text_default'))
+ ->setComponent($field_name, array('type' => 'text_textfield'))
->save();
// Login a user who can create 'page' nodes.
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php
index aa6f6ec..1d49a02 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php
@@ -79,8 +79,9 @@ class EntityCrudHookTest extends EntityUnitTestBase {
*/
public function testBlockHooks() {
$entity = entity_create('block', array(
- 'id' => 'stark.test_html',
+ 'id' => 'stark_test_html',
'plugin' => 'test_html',
+ 'theme' => 'stark',
));
$this->assertHookMessageOrder(array(
@@ -134,6 +135,10 @@ class EntityCrudHookTest extends EntityUnitTestBase {
public function testCommentHooks() {
$account = $this->createUser();
$this->enableModules(array('entity', 'filter'));
+ entity_create('node_type', array(
+ 'type' => 'article',
+ 'name' => 'Article',
+ ))->save();
$this->container->get('comment.manager')->addDefaultField('node', 'article', 'comment', CommentItemInterface::OPEN);
$node = entity_create('node', array(
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/RebuildTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/RebuildTest.php
index 478db04..1f91e80 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/RebuildTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/RebuildTest.php
@@ -86,7 +86,7 @@ class RebuildTest extends WebTestBase {
);
entity_create('field_instance_config', $instance)->save();
entity_get_form_display('node', 'page', 'default')
- ->setComponent($field_name, array('type' => 'text_test'))
+ ->setComponent($field_name, array('type' => 'text_textfield'))
->save();
// Log in a user who can create 'page' nodes.
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/ModuleTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Module/ModuleTestBase.php
index b644c19..12ee30c 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/ModuleTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/ModuleTestBase.php
@@ -193,6 +193,6 @@ abstract class ModuleTestBase extends WebTestBase {
->countQuery()
->execute()
->fetchField();
- $this->assertTrue($count > 0, format_string('watchdog table contains @count rows for @message', array('@count' => $count, '@message' => $message)));
+ $this->assertTrue($count > 0, format_string('watchdog table contains @count rows for @message', array('@count' => $count, '@message' => format_string($message, $variables))));
}
}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php
index 2f6443e..bbb4399 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php
@@ -7,6 +7,7 @@
namespace Drupal\system\Tests\Module;
+use Drupal\Component\Utility\String;
use Drupal\simpletest\WebTestBase;
/**
@@ -19,7 +20,7 @@ class UninstallTest extends WebTestBase {
*
* @var array
*/
- public static $modules = array('module_test', 'user');
+ public static $modules = array('module_test', 'user', 'views', 'node');
public static function getInfo() {
return array(
@@ -42,12 +43,44 @@ class UninstallTest extends WebTestBase {
}
/**
- * Tests the Uninstall page.
+ * Tests the Uninstall page and Uninstall confirmation page.
*/
function testUninstallPage() {
$account = $this->drupalCreateUser(array('administer modules'));
$this->drupalLogin($account);
$this->drupalGet('admin/modules/uninstall');
$this->assertTitle(t('Uninstall') . ' | Drupal');
+
+ // Uninstall module_test.
+ $edit = array();
+ $edit['uninstall[module_test]'] = TRUE;
+ $this->drupalPostForm('admin/modules/uninstall', $edit, t('Uninstall'));
+ $this->assertNoText(\Drupal::translation()->translate('Configuration deletions'), 'No configuration deletions listed on the module install confirmation page.');
+ $this->drupalPostForm(NULL, NULL, t('Uninstall'));
+ $this->assertText(t('The selected modules have been uninstalled.'), 'Modules status has been updated.');
+
+ // Uninstall node testing that the configuration that will be deleted is
+ // listed.
+ $node_dependencies = \Drupal::service('config.manager')->findConfigEntityDependentsAsEntities('module', array('node'));
+ $edit = array();
+ $edit['uninstall[node]'] = TRUE;
+ $this->drupalPostForm('admin/modules/uninstall', $edit, t('Uninstall'));
+ $this->assertText(\Drupal::translation()->translate('Configuration deletions'), 'Configuration deletions listed on the module install confirmation page.');
+
+ $entity_types = array();
+ foreach ($node_dependencies as $entity) {
+ $label = $entity->label();
+ $this->assertText($label, String::format('The entity label "!label" found.', array('!label' => $label)));
+ $entity_types[] = $entity->getEntityTypeId();
+ }
+ $entity_types = array_unique($entity_types);
+ foreach ($entity_types as $entity_type_id) {
+ $entity_type = \Drupal::entityManager()->getDefinition($entity_type_id);
+ // Add h3's since the entity type label is often repeated in the entity
+ // labels.
+ $this->assertRaw('<h3>' . $entity_type->getLabel() . '</h3>');
+ }
+ $this->drupalPostForm(NULL, NULL, t('Uninstall'));
+ $this->assertText(t('The selected modules have been uninstalled.'), 'Modules status has been updated.');
}
}
diff --git a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.full.yml b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.full.yml
index 412942c..321b372 100644
--- a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.full.yml
+++ b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.full.yml
@@ -3,3 +3,6 @@ label: Full
status: false
cache: true
targetEntityType: entity_test
+dependencies:
+ module:
+ - entity_test
diff --git a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.test.yml b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.test.yml
index baeed36..37534a3 100644
--- a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.test.yml
+++ b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.test.yml
@@ -3,3 +3,6 @@ label: Test
status: false
cache: false
targetEntityType: entity_test
+dependencies:
+ module:
+ - entity_test
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.install b/core/modules/system/tests/modules/entity_test/entity_test.install
index 3df5396..9e48029 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.install
+++ b/core/modules/system/tests/modules/entity_test/entity_test.install
@@ -32,7 +32,7 @@ function entity_test_install() {
))->save();
entity_get_form_display($entity_type, $entity_type, 'default')
- ->setComponent('field_test_text', array('type' => 'text_text'))
+ ->setComponent('field_test_text', array('type' => 'text_textfield'))
->save();
}
}
diff --git a/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml b/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml
index fb7b59c..50b1854 100644
--- a/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml
+++ b/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml
@@ -3,3 +3,6 @@ label: 'Taxonomy term page'
status: false
cache: true
targetEntityType: taxonomy_term
+dependencies:
+ module:
+ - taxonomy
diff --git a/core/modules/views/config/views.view.taxonomy_term.yml b/core/modules/taxonomy/config/views.view.taxonomy_term.yml
index beac139..10ce059 100644
--- a/core/modules/views/config/views.view.taxonomy_term.yml
+++ b/core/modules/taxonomy/config/views.view.taxonomy_term.yml
@@ -246,3 +246,7 @@ module: taxonomy
id: taxonomy_term
tag: default
langcode: en
+dependencies:
+ module:
+ - node
+ - taxonomy
diff --git a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php
index d1ff5d20..8e37920 100644
--- a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php
+++ b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php
@@ -64,7 +64,7 @@ class TextPlainUnitTest extends DrupalUnitTestBase {
'text_processing' => FALSE,
);
- $this->formatter_type = 'text_plain';
+ $this->formatter_type = 'string';
$this->formatter_settings = array();
$this->field = entity_create('field_config', array(
diff --git a/core/modules/tour/config/schema/tour.schema.yml b/core/modules/tour/config/schema/tour.schema.yml
index 9ac1082..0c8f4e3 100644
--- a/core/modules/tour/config/schema/tour.schema.yml
+++ b/core/modules/tour/config/schema/tour.schema.yml
@@ -34,6 +34,9 @@ tour.tour.*:
sequence:
- type: tour.tip.[plugin]
label: 'Tour tip'
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
tour.tip:
type: mapping
diff --git a/core/modules/tour/lib/Drupal/tour/Entity/Tour.php b/core/modules/tour/lib/Drupal/tour/Entity/Tour.php
index 5837e9a..3a473d7 100644
--- a/core/modules/tour/lib/Drupal/tour/Entity/Tour.php
+++ b/core/modules/tour/lib/Drupal/tour/Entity/Tour.php
@@ -8,6 +8,7 @@
namespace Drupal\tour\Entity;
use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
use Drupal\tour\TipsBag;
use Drupal\tour\TourInterface;
@@ -168,4 +169,19 @@ class Tour extends ConfigEntityBase implements TourInterface {
unset($this->keyedRoutes);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+
+ foreach($this->tipsBag as $instance) {
+ $definition = $instance->getPluginDefinition();
+ $this->addDependency('module', $definition['provider']);
+ }
+
+ $this->addDependency('module', $this->module);
+ return $this->dependencies;
+ }
+
}
diff --git a/core/modules/tour/lib/Drupal/tour/Tests/TourTest.php b/core/modules/tour/lib/Drupal/tour/Tests/TourTest.php
index 00e049c..d5a4be1 100644
--- a/core/modules/tour/lib/Drupal/tour/Tests/TourTest.php
+++ b/core/modules/tour/lib/Drupal/tour/Tests/TourTest.php
@@ -124,10 +124,11 @@ class TourTest extends TourTestBasic {
language_save(new Language(array('id' => 'en')));
// Programmatically create a tour for use through the remainder of the test.
- entity_create('tour', array(
+ $tour = entity_create('tour', array(
'id' => 'tour-entity-create-test-en',
'label' => 'Tour test english',
'langcode' => 'en',
+ 'module' => 'system',
'routes' => array(
array('route_name' => 'tour_test.1'),
),
@@ -142,8 +143,24 @@ class TourTest extends TourTestBasic {
'data-id' => 'tour-code-test-1',
),
),
+ 'tour-code-test-2' => array(
+ 'id' => 'tour-code-test-2',
+ 'plugin' => 'image',
+ 'label' => 'The awesome image',
+ 'url' => 'http://local/image.png',
+ 'weight' => 1,
+ 'attributes' => array(
+ 'data-id' => 'tour-code-test-2'
+ ),
+ ),
),
- ))->save();
+ ));
+ $tour->save();
+
+ // Ensure that a tour entity has the expected dependencies based on plugin
+ // providers and the module named in the configuration entity.
+ $dependencies = $tour->calculateDependencies();
+ $this->assertEqual($dependencies['module'], array('system', 'tour_test'));
$this->drupalGet('tour-test-1');
diff --git a/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerNodeAccessTest.php b/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerNodeAccessTest.php
index 207becc..c50eed2 100644
--- a/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerNodeAccessTest.php
+++ b/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerNodeAccessTest.php
@@ -33,6 +33,7 @@ class TrackerNodeAccessTest extends WebTestBase {
public function setUp() {
parent::setUp();
node_access_rebuild();
+ $this->drupalCreateContentType(array('type' => 'page'));
$this->container->get('comment.manager')->addDefaultField('node', 'page', 'comment', CommentItemInterface::OPEN);
\Drupal::state()->set('node_access_test.private', TRUE);
}
diff --git a/core/modules/user/config/entity.form_mode.user.register.yml b/core/modules/user/config/entity.form_mode.user.register.yml
index c720f19..06919cd 100644
--- a/core/modules/user/config/entity.form_mode.user.register.yml
+++ b/core/modules/user/config/entity.form_mode.user.register.yml
@@ -2,3 +2,6 @@ id: user.register
label: Register
status: true
targetEntityType: user
+dependencies:
+ module:
+ - user
diff --git a/core/modules/user/config/entity.view_mode.user.compact.yml b/core/modules/user/config/entity.view_mode.user.compact.yml
index 4522e10..6e0b13d 100644
--- a/core/modules/user/config/entity.view_mode.user.compact.yml
+++ b/core/modules/user/config/entity.view_mode.user.compact.yml
@@ -3,3 +3,6 @@ label: Compact
status: true
cache: true
targetEntityType: user
+dependencies:
+ module:
+ - user
diff --git a/core/modules/user/config/entity.view_mode.user.full.yml b/core/modules/user/config/entity.view_mode.user.full.yml
index a282b0c..2f0f250 100644
--- a/core/modules/user/config/entity.view_mode.user.full.yml
+++ b/core/modules/user/config/entity.view_mode.user.full.yml
@@ -3,3 +3,6 @@ label: 'User account'
status: false
cache: true
targetEntityType: user
+dependencies:
+ module:
+ - user
diff --git a/core/modules/user/config/rdf.mapping.user.user.yml b/core/modules/user/config/rdf.mapping.user.user.yml
index ad082a9..f052a1a 100644
--- a/core/modules/user/config/rdf.mapping.user.user.yml
+++ b/core/modules/user/config/rdf.mapping.user.user.yml
@@ -7,3 +7,6 @@ fieldMappings:
name:
properties:
- 'schema:name'
+dependencies:
+ module:
+ - user
diff --git a/core/modules/user/config/search.page.user_search.yml b/core/modules/user/config/search.page.user_search.yml
index bb130c2..50b0113 100644
--- a/core/modules/user/config/search.page.user_search.yml
+++ b/core/modules/user/config/search.page.user_search.yml
@@ -5,3 +5,6 @@ langcode: en
path: user
plugin: user_search
configuration: { }
+dependencies:
+ module:
+ - user
diff --git a/core/modules/user/config/system.action.user_block_user_action.yml b/core/modules/user/config/system.action.user_block_user_action.yml
index 57b69e9..d7e15c6 100644
--- a/core/modules/user/config/system.action.user_block_user_action.yml
+++ b/core/modules/user/config/system.action.user_block_user_action.yml
@@ -4,3 +4,6 @@ status: true
langcode: en
type: user
plugin: user_block_user_action
+dependencies:
+ module:
+ - user
diff --git a/core/modules/user/config/system.action.user_cancel_user_action.yml b/core/modules/user/config/system.action.user_cancel_user_action.yml
index 875ecee..bcc03ed 100644
--- a/core/modules/user/config/system.action.user_cancel_user_action.yml
+++ b/core/modules/user/config/system.action.user_cancel_user_action.yml
@@ -4,3 +4,6 @@ status: true
langcode: en
type: user
plugin: user_cancel_user_action
+dependencies:
+ module:
+ - user
diff --git a/core/modules/user/config/system.action.user_unblock_user_action.yml b/core/modules/user/config/system.action.user_unblock_user_action.yml
index 749e61b..0d313ea 100644
--- a/core/modules/user/config/system.action.user_unblock_user_action.yml
+++ b/core/modules/user/config/system.action.user_unblock_user_action.yml
@@ -4,3 +4,6 @@ status: true
langcode: en
type: user
plugin: user_unblock_user_action
+dependencies:
+ module:
+ - user
diff --git a/core/modules/user/config/views.view.user_admin_people.yml b/core/modules/user/config/views.view.user_admin_people.yml
index 849697a..89d1e4e 100644
--- a/core/modules/user/config/views.view.user_admin_people.yml
+++ b/core/modules/user/config/views.view.user_admin_people.yml
@@ -952,7 +952,10 @@ display:
defaults:
show_admin_links: false
label: People
-module: views
+module: user
id: user_admin_people
tag: default
langcode: und
+dependencies:
+ module:
+ - user
diff --git a/core/modules/user/config/views.view.who_s_new.yml b/core/modules/user/config/views.view.who_s_new.yml
index 4653796..f5bee58 100644
--- a/core/modules/user/config/views.view.who_s_new.yml
+++ b/core/modules/user/config/views.view.who_s_new.yml
@@ -167,7 +167,10 @@ display:
relationships: { }
arguments: { }
label: 'Who''s new'
-module: views
+module: user
id: who_s_new
tag: default
langcode: en
+dependencies:
+ module:
+ - user
diff --git a/core/modules/user/config/views.view.who_s_online.yml b/core/modules/user/config/views.view.who_s_online.yml
index 040e2f9..efe344f 100644
--- a/core/modules/user/config/views.view.who_s_online.yml
+++ b/core/modules/user/config/views.view.who_s_online.yml
@@ -198,7 +198,10 @@ display:
block_description: 'Who''s online'
display_description: 'A list of users that are currently logged in.'
label: 'Who''s online block'
-module: views
+module: user
id: who_s_online
tag: default
langcode: en
+dependencies:
+ module:
+ - user
diff --git a/core/modules/views/config/schema/views.schema.yml b/core/modules/views/config/schema/views.schema.yml
index a9a7eaf..a2ad5c0 100644
--- a/core/modules/views/config/schema/views.schema.yml
+++ b/core/modules/views/config/schema/views.schema.yml
@@ -117,3 +117,6 @@ views.view.*:
label: 'Position'
display_options:
type: views.display.[%parent.display_plugin]
+ dependencies:
+ type: config_dependencies
+ label: 'Dependencies'
diff --git a/core/modules/views/lib/Drupal/views/Entity/View.php b/core/modules/views/lib/Drupal/views/Entity/View.php
index 80c75b0..097059a 100644
--- a/core/modules/views/lib/Drupal/views/Entity/View.php
+++ b/core/modules/views/lib/Drupal/views/Entity/View.php
@@ -22,7 +22,6 @@ use Drupal\views\ViewExecutable;
* id = "view",
* label = @Translation("View"),
* controllers = {
- * "storage" = "Drupal\views\ViewStorageController",
* "access" = "Drupal\views\ViewAccessController"
* },
* admin_permission = "administer views",
@@ -258,6 +257,7 @@ class View extends ConfigEntityBase implements ViewStorageInterface {
'tag',
'uuid',
'langcode',
+ 'dependencies',
);
$properties = array();
foreach ($names as $name) {
@@ -269,6 +269,39 @@ class View extends ConfigEntityBase implements ViewStorageInterface {
/**
* {@inheritdoc}
*/
+ public function calculateDependencies() {
+ parent::calculateDependencies();
+
+ // Ensure that the view is dependant on the module that implements the view.
+ $this->addDependency('module', $this->module);
+ // Ensure that the view is dependant on the module that provides the schema
+ // for the base table.
+ $schema = drupal_get_schema($this->base_table);
+ if ($this->module != $schema['module']) {
+ $this->addDependency('module', $schema['module']);
+ }
+
+ $handler_types = array();
+ foreach (ViewExecutable::viewsHandlerTypes() as $type) {
+ $handler_types[] = $type['plural'];
+ }
+ foreach ($this->get('display') as $display) {
+ foreach ($handler_types as $handler_type) {
+ if (!empty($display['display_options'][$handler_type])) {
+ foreach ($display['display_options'][$handler_type] as $handler) {
+ if (isset($handler['provider']) && empty($handler['optional'])) {
+ $this->addDependency('module', $handler['provider']);
+ }
+ }
+ }
+ }
+ }
+ return $this->dependencies;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) {
parent::postSave($storage_controller, $update);
diff --git a/core/modules/views/lib/Drupal/views/Tests/Entity/FieldEntityTest.php b/core/modules/views/lib/Drupal/views/Tests/Entity/FieldEntityTest.php
index d828383..9d9a03a 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Entity/FieldEntityTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Entity/FieldEntityTest.php
@@ -46,6 +46,7 @@ class FieldEntityTest extends ViewTestBase {
$account = entity_create('user', array('name' => $this->randomName(), 'bundle' => 'user'));
$account->save();
+ $this->drupalCreateContentType(array('type' => 'page'));
$this->container->get('comment.manager')->addDefaultField('node', 'page');
// Force a flush of the in-memory storage.
$this->container->get('views.views_data')->clear();
diff --git a/core/modules/views/lib/Drupal/views/Tests/Entity/ViewEntityDependenciesTest.php b/core/modules/views/lib/Drupal/views/Tests/Entity/ViewEntityDependenciesTest.php
new file mode 100644
index 0000000..082f352
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Tests/Entity/ViewEntityDependenciesTest.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\views\Tests\Entity\ViewEntityDependenciesTest.
+ */
+
+namespace Drupal\views\Tests\Entity;
+
+use Drupal\views\Tests\ViewTestBase;
+use Drupal\views\Views;
+
+/**
+ * Tests \Drupal\views\Entity\View::calculateDependencies().
+ */
+class ViewEntityDependenciesTest extends ViewTestBase {
+
+ /**
+ * Views used by this test.
+ *
+ * @var array
+ */
+ public static $testViews = array('test_field_get_entity');
+
+ /**
+ * Modules to enable.
+ *
+ * @var array
+ */
+ public static $modules = array('node', 'comment');
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'View dependencies test',
+ 'description' => 'Tests the calculation of dependencies for views.',
+ 'group' => 'Views module integration',
+ );
+ }
+
+ /**
+ * Tests the calculateDependencies method.
+ */
+ public function testCalculateDependencies() {
+ // The view is a view of comments, their nodes and their authors, so there
+ // are three layers of entities.
+ $account = entity_create('user', array('name' => $this->randomName(), 'bundle' => 'user'));
+ $account->save();
+ $this->drupalCreateContentType(array('type' => 'page'));
+ $this->container->get('comment.manager')->addDefaultField('node', 'page');
+ // Force a flush of the in-memory storage.
+ $this->container->get('views.views_data')->clear();
+
+ $node = entity_create('node', array('uid' => $account->id(), 'type' => 'page'));
+ $node->save();
+ $comment = entity_create('comment', array(
+ 'uid' => $account->id(),
+ 'entity_id' => $node->id(),
+ 'entity_type' => 'node',
+ 'field_name' => 'comment'
+ ));
+ $comment->save();
+
+ $view = Views::getView('test_field_get_entity');
+
+ $expected_dependencies = array(
+ 'module' => array(
+ 'comment',
+ 'node',
+ 'user',
+ )
+ );
+ $dependencies = $view->calculateDependencies();
+ $this->assertEqual($expected_dependencies, $dependencies);
+ }
+
+}
diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php
index 5f73592..a7dc428 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php
@@ -53,6 +53,7 @@ class HandlerAllTest extends HandlerTestBase {
* Tests most of the handlers.
*/
public function testHandlers() {
+ $this->drupalCreateContentType(array('type' => 'article'));
$this->container->get('comment.manager')->addDefaultField('node', 'article');
$object_types = array_keys(ViewExecutable::viewsHandlerTypes());
diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php
index fc5eeed..5c145fa 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php
@@ -41,6 +41,7 @@ class HandlerTest extends ViewTestBase {
protected function setUp() {
parent::setUp();
+ $this->drupalCreateContentType(array('type' => 'page'));
$this->container->get('comment.manager')->addDefaultField('node', 'page');
$this->enableViewsTestModule();
}
diff --git a/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php b/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php
index 79bce4b..f43edbc 100644
--- a/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php
@@ -152,6 +152,7 @@ class ModuleTest extends ViewUnitTestBase {
*/
public function testLoadFunctions() {
$this->enableModules(array('node'));
+ $this->installConfig(array('node'));
$controller = $this->container->get('entity.manager')->getStorageController('view');
// Test views_view_is_enabled/disabled.
diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php b/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php
index 0d7f19e..6c97e99 100644
--- a/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php
@@ -88,6 +88,10 @@ class ViewExecutableTest extends ViewUnitTestBase {
$this->installSchema('node', array('node', 'node_field_data'));
$this->installSchema('comment', array('comment', 'comment_entity_statistics'));
$this->installConfig(array('field'));
+ entity_create('node_type', array(
+ 'type' => 'page',
+ 'name' => 'Page',
+ ))->save();
$this->container->get('comment.manager')->addDefaultField('node', 'page');
parent::setUpFixtures();
diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php b/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php
index d0cea34..ba14380 100644
--- a/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php
@@ -8,7 +8,7 @@
namespace Drupal\views\Tests;
use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\views\ViewStorageController;
+use Drupal\Core\Config\Entity\ConfigStorageController;
use Drupal\views\Entity\View;
use Drupal\views\Plugin\views\display\Page;
use Drupal\views\Plugin\views\display\DefaultDisplay;
@@ -16,10 +16,10 @@ use Drupal\views\Plugin\views\display\Feed;
use Drupal\views\Views;
/**
- * Tests the functionality of View and ViewStorageController.
+ * Tests the functionality of View and ConfigStorageController.
*
* @see \Drupal\views\Entity\View
- * @see \Drupal\views\ViewStorageController
+ * @see \Drupal\Core\Config\Entity\ConfigStorageController
*/
class ViewStorageTest extends ViewUnitTestBase {
@@ -50,7 +50,7 @@ class ViewStorageTest extends ViewUnitTestBase {
/**
* The configuration entity storage controller.
*
- * @var \Drupal\views\ViewStorageController
+ * @var \Drupal\Core\Config\Entity\ConfigStorageController
*/
protected $controller;
@@ -80,9 +80,6 @@ class ViewStorageTest extends ViewUnitTestBase {
// Confirm that an info array has been returned.
$this->assertTrue($this->entityType instanceof EntityTypeInterface, 'The View info array is loaded.');
- // Confirm we have the correct controller class.
- $this->assertTrue($this->controller instanceof ViewStorageController, 'The correct controller is loaded.');
-
// CRUD tests.
$this->loadTests();
$this->createTests();
diff --git a/core/modules/views/lib/Drupal/views/ViewExecutable.php b/core/modules/views/lib/Drupal/views/ViewExecutable.php
index 3761ed8..af8f86d 100644
--- a/core/modules/views/lib/Drupal/views/ViewExecutable.php
+++ b/core/modules/views/lib/Drupal/views/ViewExecutable.php
@@ -2239,4 +2239,16 @@ class ViewExecutable extends DependencySerialization {
return FALSE;
}
+ /**
+ * Calculates dependencies for the view.
+ *
+ * @see \Drupal\views\Entity\View::calculateDependencies()
+ *
+ * @return array
+ * An array of dependencies grouped by type (module, theme, entity).
+ */
+ public function calculateDependencies() {
+ return $this->storage->calculateDependencies();
+ }
+
}
diff --git a/core/modules/views/lib/Drupal/views/ViewStorageController.php b/core/modules/views/lib/Drupal/views/ViewStorageController.php
deleted file mode 100644
index a418fb1..0000000
--- a/core/modules/views/lib/Drupal/views/ViewStorageController.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\views\ViewStorageController.
- */
-
-namespace Drupal\views;
-
-use Drupal\Core\Config\Entity\ConfigStorageController;
-use Drupal\Core\Entity\EntityInterface;
-
-/**
- * Defines the storage controller class for View entities.
- */
-class ViewStorageController extends ConfigStorageController {
-
- /**
- * {@inheritdoc}
- */
- public function loadMultiple(array $ids = NULL) {
- $entities = parent::loadMultiple($ids);
-
- // Only return views for enabled modules.
- return array_filter($entities, function ($entity) {
- if (\Drupal::moduleHandler()->moduleExists($entity->get('module'))) {
- return TRUE;
- }
- return FALSE;
- });
- }
-
-}
diff --git a/core/modules/views/tests/Drupal/views/Tests/EventSubscriber/RouteSubscriberTest.php b/core/modules/views/tests/Drupal/views/Tests/EventSubscriber/RouteSubscriberTest.php
index e5d6c69..cccd842 100644
--- a/core/modules/views/tests/Drupal/views/Tests/EventSubscriber/RouteSubscriberTest.php
+++ b/core/modules/views/tests/Drupal/views/Tests/EventSubscriber/RouteSubscriberTest.php
@@ -61,7 +61,7 @@ class RouteSubscriberTest extends UnitTestCase {
protected function setUp() {
$this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
- $this->viewStorageController = $this->getMockBuilder('\Drupal\views\ViewStorageController')
+ $this->viewStorageController = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigStorageController')
->disableOriginalConstructor()
->getMock();
$this->entityManager->expects($this->any())
diff --git a/core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php b/core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php
index 15d4d6e..51254b5 100644
--- a/core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php
+++ b/core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php
@@ -101,7 +101,7 @@ class ViewsBlockTest extends UnitTestCase {
->with($this->view)
->will($this->returnValue($this->executable));
- $this->storageController = $this->getMockBuilder('Drupal\views\ViewStorageController')
+ $this->storageController = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigStorageController')
->disableOriginalConstructor()
->getMock();
diff --git a/core/modules/views/tests/Drupal/views/Tests/Routing/ViewPageControllerTest.php b/core/modules/views/tests/Drupal/views/Tests/Routing/ViewPageControllerTest.php
index 2cdd6e1..0daf925 100644
--- a/core/modules/views/tests/Drupal/views/Tests/Routing/ViewPageControllerTest.php
+++ b/core/modules/views/tests/Drupal/views/Tests/Routing/ViewPageControllerTest.php
@@ -53,7 +53,7 @@ class ViewPageControllerTest extends UnitTestCase {
}
protected function setUp() {
- $this->storageController = $this->getMockBuilder('Drupal\views\ViewStorageController')
+ $this->storageController = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigStorageController')
->disableOriginalConstructor()
->getMock();
$this->executableFactory = $this->getMockBuilder('Drupal\views\ViewExecutableFactory')
diff --git a/core/modules/views/tests/Drupal/views/Tests/ViewsTest.php b/core/modules/views/tests/Drupal/views/Tests/ViewsTest.php
index 9466c0b..1ebf244 100644
--- a/core/modules/views/tests/Drupal/views/Tests/ViewsTest.php
+++ b/core/modules/views/tests/Drupal/views/Tests/ViewsTest.php
@@ -35,7 +35,7 @@ class ViewsTest extends UnitTestCase {
$this->view = new View(array('id' => 'test_view'), 'view');
- $view_storage_controller = $this->getMockBuilder('Drupal\views\ViewStorageController')
+ $view_storage_controller = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigStorageController')
->disableOriginalConstructor()
->getMock();
$view_storage_controller->expects($this->once())
diff --git a/core/modules/views_ui/config/tour.tour.views-ui.yml b/core/modules/views_ui/config/tour.tour.views-ui.yml
index 76c9302..8695a75 100644
--- a/core/modules/views_ui/config/tour.tour.views-ui.yml
+++ b/core/modules/views_ui/config/tour.tour.views-ui.yml
@@ -87,3 +87,6 @@ tips:
location: left
attributes:
data-id: views-display-extra-actions
+dependencies:
+ module:
+ - views_ui
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
index 5fca58f..009e8e4 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
@@ -149,6 +149,13 @@ class ViewUI implements ViewStorageInterface {
private $isSyncing = FALSE;
/**
+ * Whether the config is being deleted through the uninstall process.
+ *
+ * @var bool
+ */
+ private $isUninstalling = FALSE;
+
+ /**
* Constructs a View UI object.
*
* @param \Drupal\views\ViewStorageInterface $storage
@@ -207,11 +214,25 @@ class ViewUI implements ViewStorageInterface {
/**
* {@inheritdoc}
*/
+ public function setUninstalling($isUninstalling) {
+ $this->isUninstalling = $isUninstalling;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function isSyncing() {
return $this->isSyncing;
}
/**
+ * {@inheritdoc}
+ */
+ public function isUninstalling() {
+ return $this->isUninstalling;
+ }
+
+ /**
* Basic submit handler applicable to all 'standard' forms.
*
* This submit handler determines whether the user wants the submitted changes
@@ -1179,4 +1200,16 @@ class ViewUI implements ViewStorageInterface {
return $this->storage->hasLinkTemplate($key);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfigDependencyName() {
+ }
+
}
diff --git a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php
index 534f824..62a1586 100644
--- a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php
+++ b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php
@@ -30,7 +30,7 @@ class ViewListControllerTest extends UnitTestCase {
* @see \Drupal\views_ui\ViewListController::getDisplaysList().
*/
public function testBuildRowEntityList() {
- $storage_controller = $this->getMockBuilder('Drupal\views\ViewStorageController')
+ $storage_controller = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigStorageController')
->disableOriginalConstructor()
->getMock();
$display_manager = $this->getMockBuilder('\Drupal\views\Plugin\ViewsPluginManager')
diff --git a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUIObjectTest.php b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUIObjectTest.php
index b8256a5..7cbf7b9 100644
--- a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUIObjectTest.php
+++ b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUIObjectTest.php
@@ -47,7 +47,11 @@ class ViewUIObjectTest extends UnitTestCase {
// EntityInterface::isNew() is missing from the list of methods, because it
// calls id(), which breaks the ->expect($this->once()) call. Call it later.
// EntityInterface::isSyncing() is only called during syncing process.
- if ($reflection_method->getName() != 'isNew' && $reflection_method->getName() != 'isSyncing') {
+ // EntityInterface::isUninstalling() is only called during uninstallation
+ // process. ConfigEntityInterface::getConfigDependencyName() and
+ // ConfigEntityInterface::calculateDependencies() are only used for
+ // dependency management.
+ if (!in_array($reflection_method->getName(), ['isNew', 'isSyncing', 'isUninstalling', 'getConfigDependencyName', 'calculateDependencies'])) {
if (count($reflection_method->getParameters()) == 0) {
$method_args[$reflection_method->getName()] = array();
}
diff --git a/core/profiles/minimal/config/block.block.stark_admin.yml b/core/profiles/minimal/config/block.block.stark_admin.yml
index f3c1735..68bee15 100644
--- a/core/profiles/minimal/config/block.block.stark_admin.yml
+++ b/core/profiles/minimal/config/block.block.stark_admin.yml
@@ -18,3 +18,8 @@ visibility:
roles: { }
node_type:
types: { }
+dependencies:
+ module:
+ - system
+ theme:
+ - stark
diff --git a/core/profiles/minimal/config/block.block.stark_login.yml b/core/profiles/minimal/config/block.block.stark_login.yml
index 4ca8266..fb1301f 100644
--- a/core/profiles/minimal/config/block.block.stark_login.yml
+++ b/core/profiles/minimal/config/block.block.stark_login.yml
@@ -18,3 +18,8 @@ visibility:
roles: { }
node_type:
types: { }
+dependencies:
+ module:
+ - user
+ theme:
+ - stark
diff --git a/core/profiles/minimal/config/block.block.stark_tools.yml b/core/profiles/minimal/config/block.block.stark_tools.yml
index a452643..9d53bc3 100644
--- a/core/profiles/minimal/config/block.block.stark_tools.yml
+++ b/core/profiles/minimal/config/block.block.stark_tools.yml
@@ -18,3 +18,8 @@ visibility:
roles: { }
node_type:
types: { }
+dependencies:
+ module:
+ - system
+ theme:
+ - stark
diff --git a/core/profiles/standard/config/block.block.bartik_breadcrumbs.yml b/core/profiles/standard/config/block.block.bartik_breadcrumbs.yml
index 3465368..b8c9eb0 100644
--- a/core/profiles/standard/config/block.block.bartik_breadcrumbs.yml
+++ b/core/profiles/standard/config/block.block.bartik_breadcrumbs.yml
@@ -20,3 +20,8 @@ visibility:
types:
article: '0'
page: '0'
+dependencies:
+ module:
+ - system
+ theme:
+ - bartik
diff --git a/core/profiles/standard/config/block.block.bartik_content.yml b/core/profiles/standard/config/block.block.bartik_content.yml
index 8146a54..f7362e6 100644
--- a/core/profiles/standard/config/block.block.bartik_content.yml
+++ b/core/profiles/standard/config/block.block.bartik_content.yml
@@ -20,3 +20,8 @@ visibility:
types:
article: '0'
page: '0'
+dependencies:
+ module:
+ - system
+ theme:
+ - bartik
diff --git a/core/profiles/standard/config/block.block.bartik_footer.yml b/core/profiles/standard/config/block.block.bartik_footer.yml
index 76f9508..07bdba5 100644
--- a/core/profiles/standard/config/block.block.bartik_footer.yml
+++ b/core/profiles/standard/config/block.block.bartik_footer.yml
@@ -20,3 +20,8 @@ visibility:
types:
article: '0'
page: '0'
+dependencies:
+ module:
+ - system
+ theme:
+ - bartik
diff --git a/core/profiles/standard/config/block.block.bartik_help.yml b/core/profiles/standard/config/block.block.bartik_help.yml
index 5806db7..6ee1371 100644
--- a/core/profiles/standard/config/block.block.bartik_help.yml
+++ b/core/profiles/standard/config/block.block.bartik_help.yml
@@ -20,3 +20,8 @@ visibility:
types:
article: '0'
page: '0'
+dependencies:
+ module:
+ - system
+ theme:
+ - bartik
diff --git a/core/profiles/standard/config/block.block.bartik_login.yml b/core/profiles/standard/config/block.block.bartik_login.yml
index 7fc17cb..235fa04 100644
--- a/core/profiles/standard/config/block.block.bartik_login.yml
+++ b/core/profiles/standard/config/block.block.bartik_login.yml
@@ -20,3 +20,8 @@ visibility:
types:
article: '0'
page: '0'
+dependencies:
+ module:
+ - user
+ theme:
+ - bartik
diff --git a/core/profiles/standard/config/block.block.bartik_powered.yml b/core/profiles/standard/config/block.block.bartik_powered.yml
index 0e3ebab..a0257a2 100644
--- a/core/profiles/standard/config/block.block.bartik_powered.yml
+++ b/core/profiles/standard/config/block.block.bartik_powered.yml
@@ -20,3 +20,8 @@ visibility:
types:
article: '0'
page: '0'
+dependencies:
+ module:
+ - system
+ theme:
+ - bartik
diff --git a/core/profiles/standard/config/block.block.bartik_search.yml b/core/profiles/standard/config/block.block.bartik_search.yml
index f68adbc..dc39361 100644
--- a/core/profiles/standard/config/block.block.bartik_search.yml
+++ b/core/profiles/standard/config/block.block.bartik_search.yml
@@ -20,3 +20,8 @@ visibility:
types:
article: '0'
page: '0'
+dependencies:
+ module:
+ - search
+ theme:
+ - bartik
diff --git a/core/profiles/standard/config/block.block.bartik_tools.yml b/core/profiles/standard/config/block.block.bartik_tools.yml
index 257990d..cfe490d 100644
--- a/core/profiles/standard/config/block.block.bartik_tools.yml
+++ b/core/profiles/standard/config/block.block.bartik_tools.yml
@@ -20,3 +20,8 @@ visibility:
types:
article: '0'
page: '0'
+dependencies:
+ module:
+ - system
+ theme:
+ - bartik
diff --git a/core/profiles/standard/config/block.block.seven_breadcrumbs.yml b/core/profiles/standard/config/block.block.seven_breadcrumbs.yml
index b56f633..b48f4b4 100644
--- a/core/profiles/standard/config/block.block.seven_breadcrumbs.yml
+++ b/core/profiles/standard/config/block.block.seven_breadcrumbs.yml
@@ -20,3 +20,8 @@ visibility:
types:
article: '0'
page: '0'
+dependencies:
+ module:
+ - system
+ theme:
+ - seven
diff --git a/core/profiles/standard/config/block.block.seven_content.yml b/core/profiles/standard/config/block.block.seven_content.yml
index 23a6568..1f44d0e 100644
--- a/core/profiles/standard/config/block.block.seven_content.yml
+++ b/core/profiles/standard/config/block.block.seven_content.yml
@@ -20,3 +20,8 @@ visibility:
types:
article: '0'
page: '0'
+dependencies:
+ module:
+ - system
+ theme:
+ - seven
diff --git a/core/profiles/standard/config/block.block.seven_help.yml b/core/profiles/standard/config/block.block.seven_help.yml
index 77918e5..2f3121f 100644
--- a/core/profiles/standard/config/block.block.seven_help.yml
+++ b/core/profiles/standard/config/block.block.seven_help.yml
@@ -20,3 +20,8 @@ visibility:
types:
article: '0'
page: '0'
+dependencies:
+ module:
+ - system
+ theme:
+ - seven
diff --git a/core/profiles/standard/config/block.block.seven_login.yml b/core/profiles/standard/config/block.block.seven_login.yml
index 239bd36..8eae9f4 100644
--- a/core/profiles/standard/config/block.block.seven_login.yml
+++ b/core/profiles/standard/config/block.block.seven_login.yml
@@ -20,3 +20,8 @@ visibility:
types:
article: '0'
page: '0'
+dependencies:
+ module:
+ - user
+ theme:
+ - seven
diff --git a/core/profiles/standard/config/editor.editor.basic_html.yml b/core/profiles/standard/config/editor.editor.basic_html.yml
index 155c5fb..fdf6e96 100644
--- a/core/profiles/standard/config/editor.editor.basic_html.yml
+++ b/core/profiles/standard/config/editor.editor.basic_html.yml
@@ -41,3 +41,8 @@ image_upload:
height: 0
status: true
langcode: en
+dependencies:
+ entity:
+ - filter.format.basic_html
+ module:
+ - ckeditor
diff --git a/core/profiles/standard/config/editor.editor.full_html.yml b/core/profiles/standard/config/editor.editor.full_html.yml
index cd17f03..66df850 100644
--- a/core/profiles/standard/config/editor.editor.full_html.yml
+++ b/core/profiles/standard/config/editor.editor.full_html.yml
@@ -53,3 +53,8 @@ image_upload:
height: 0
status: true
langcode: en
+dependencies:
+ entity:
+ - filter.format.full_html
+ module:
+ - ckeditor
diff --git a/core/profiles/standard/config/entity.form_display.node.article.default.yml b/core/profiles/standard/config/entity.form_display.node.article.default.yml
index ff157a9..32fcba1 100644
--- a/core/profiles/standard/config/entity.form_display.node.article.default.yml
+++ b/core/profiles/standard/config/entity.form_display.node.article.default.yml
@@ -2,25 +2,45 @@ id: node.article.default
targetEntityType: node
bundle: article
mode: default
-status: true
content:
+ title:
+ type: text_textfield
+ weight: 0
+ settings:
+ size: 60
+ placeholder: ''
body:
type: text_textarea_with_summary
- weight: 0
+ weight: 1
settings:
rows: 9
summary_rows: 3
placeholder: ''
+ comment:
+ type: comment_default
+ weight: 2
+ settings: { }
field_tags:
type: taxonomy_autocomplete
- weight: -4
- settings:
- size: 60
- autocomplete_route_name: taxonomy.autocomplete
- placeholder: ''
+ weight: 3
+ settings: { }
field_image:
type: image_image
+ weight: 4
settings:
progress_indicator: throbber
preview_image_style: thumbnail
- weight: -1
+hidden: { }
+status: true
+dependencies:
+ entity:
+ - field.instance.node.article.body
+ - field.instance.node.article.comment
+ - field.instance.node.article.field_image
+ - field.instance.node.article.field_tags
+ - node.type.article
+ module:
+ - comment
+ - image
+ - taxonomy
+ - text
diff --git a/core/profiles/standard/config/entity.form_display.user.user.default.yml b/core/profiles/standard/config/entity.form_display.user.user.default.yml
index 13dc334..a9c9197 100644
--- a/core/profiles/standard/config/entity.form_display.user.user.default.yml
+++ b/core/profiles/standard/config/entity.form_display.user.user.default.yml
@@ -10,3 +10,6 @@ content:
preview_image_style: thumbnail
weight: -1
status: true
+dependencies:
+ module:
+ - image
diff --git a/core/profiles/standard/config/entity.view_display.node.article.default.yml b/core/profiles/standard/config/entity.view_display.node.article.default.yml
index 6d76c36..c4f2c85 100644
--- a/core/profiles/standard/config/entity.view_display.node.article.default.yml
+++ b/core/profiles/standard/config/entity.view_display.node.article.default.yml
@@ -21,3 +21,14 @@ content:
image_style: large
image_link: ''
weight: -1
+dependencies:
+ entity:
+ - field.instance.node.article.body
+ - field.instance.node.article.field_image
+ - field.instance.node.article.field_tags
+ - node.type.article
+ module:
+ - comment
+ - image
+ - taxonomy
+ - text
diff --git a/core/profiles/standard/config/entity.view_display.node.article.teaser.yml b/core/profiles/standard/config/entity.view_display.node.article.teaser.yml
index 75bf6d0..a88fc06 100644
--- a/core/profiles/standard/config/entity.view_display.node.article.teaser.yml
+++ b/core/profiles/standard/config/entity.view_display.node.article.teaser.yml
@@ -22,3 +22,14 @@ content:
image_style: medium
image_link: content
weight: -1
+dependencies:
+ entity:
+ - entity.view_mode.node.teaser
+ - field.instance.node.article.body
+ - field.instance.node.article.field_image
+ - field.instance.node.article.field_tags
+ - node.type.article
+ module:
+ - image
+ - taxonomy
+ - text
diff --git a/core/profiles/standard/config/entity.view_display.user.user.compact.yml b/core/profiles/standard/config/entity.view_display.user.user.compact.yml
index f9e85b3..1c7e4e9 100644
--- a/core/profiles/standard/config/entity.view_display.user.user.compact.yml
+++ b/core/profiles/standard/config/entity.view_display.user.user.compact.yml
@@ -13,3 +13,8 @@ content:
hidden:
member_for: true
status: true
+dependencies:
+ entity:
+ - entity.view_mode.user.compact
+ module:
+ - image
diff --git a/core/profiles/standard/config/entity.view_display.user.user.default.yml b/core/profiles/standard/config/entity.view_display.user.user.default.yml
index fe9e3eb..f39700b 100644
--- a/core/profiles/standard/config/entity.view_display.user.user.default.yml
+++ b/core/profiles/standard/config/entity.view_display.user.user.default.yml
@@ -11,3 +11,6 @@ content:
image_link: content
weight: 0
status: true
+dependencies:
+ module:
+ - image
diff --git a/core/profiles/standard/config/field.field.node.field_image.yml b/core/profiles/standard/config/field.field.node.field_image.yml
index b397ecd..a0b1966 100644
--- a/core/profiles/standard/config/field.field.node.field_image.yml
+++ b/core/profiles/standard/config/field.field.node.field_image.yml
@@ -32,3 +32,6 @@ indexes:
- target_id
status: true
langcode: und
+dependencies:
+ module:
+ - image
diff --git a/core/profiles/standard/config/field.field.node.field_tags.yml b/core/profiles/standard/config/field.field.node.field_tags.yml
index 55eac77..7018e87 100644
--- a/core/profiles/standard/config/field.field.node.field_tags.yml
+++ b/core/profiles/standard/config/field.field.node.field_tags.yml
@@ -16,3 +16,6 @@ indexes:
- target_id
status: true
langcode: und
+dependencies:
+ module:
+ - taxonomy
diff --git a/core/profiles/standard/config/field.field.user.user_picture.yml b/core/profiles/standard/config/field.field.user.user_picture.yml
index ecbe2c4..7becb75 100644
--- a/core/profiles/standard/config/field.field.user.user_picture.yml
+++ b/core/profiles/standard/config/field.field.user.user_picture.yml
@@ -32,3 +32,6 @@ translatable: false
indexes:
target_id:
- target_id
+dependencies:
+ module:
+ - image
diff --git a/core/profiles/standard/config/field.instance.node.article.field_image.yml b/core/profiles/standard/config/field.instance.node.article.field_image.yml
index 69d8593..11cbbd4 100644
--- a/core/profiles/standard/config/field.instance.node.article.field_image.yml
+++ b/core/profiles/standard/config/field.instance.node.article.field_image.yml
@@ -26,3 +26,6 @@ settings:
status: true
langcode: und
field_type: image
+dependencies:
+ entity:
+ - field.field.node.field_image
diff --git a/core/profiles/standard/config/field.instance.node.article.field_tags.yml b/core/profiles/standard/config/field.instance.node.article.field_tags.yml
index ed4e166..ed175f7 100644
--- a/core/profiles/standard/config/field.instance.node.article.field_tags.yml
+++ b/core/profiles/standard/config/field.instance.node.article.field_tags.yml
@@ -10,3 +10,6 @@ default_value_function: ''
settings: { }
status: true
langcode: und
+dependencies:
+ entity:
+ - field.field.node.field_tags
diff --git a/core/profiles/standard/config/field.instance.user.user.user_picture.yml b/core/profiles/standard/config/field.instance.user.user.user_picture.yml
index f31efe6..6469300 100644
--- a/core/profiles/standard/config/field.instance.user.user.user_picture.yml
+++ b/core/profiles/standard/config/field.instance.user.user.user_picture.yml
@@ -26,3 +26,6 @@ settings:
alt_field_required: false
title_field_required: false
field_type: image
+dependencies:
+ entity:
+ - field.field.user.user_picture
diff --git a/core/profiles/standard/config/rdf.mapping.comment.node__comment.yml b/core/profiles/standard/config/rdf.mapping.comment.node__comment.yml
index 42d8f34..70f25b1 100644
--- a/core/profiles/standard/config/rdf.mapping.comment.node__comment.yml
+++ b/core/profiles/standard/config/rdf.mapping.comment.node__comment.yml
@@ -24,3 +24,6 @@ fieldMappings:
properties:
- 'schema:author'
mapping_type: 'rel'
+dependencies:
+ module:
+ - comment
diff --git a/core/profiles/standard/config/rdf.mapping.node.article.yml b/core/profiles/standard/config/rdf.mapping.node.article.yml
index a87edaf..10147e7 100644
--- a/core/profiles/standard/config/rdf.mapping.node.article.yml
+++ b/core/profiles/standard/config/rdf.mapping.node.article.yml
@@ -40,3 +40,8 @@ fieldMappings:
field_tags:
properties:
- 'schema:about'
+dependencies:
+ entity:
+ - node.type.article
+ module:
+ - node
diff --git a/core/profiles/standard/config/rdf.mapping.node.page.yml b/core/profiles/standard/config/rdf.mapping.node.page.yml
index 967449c..8a5d377 100644
--- a/core/profiles/standard/config/rdf.mapping.node.page.yml
+++ b/core/profiles/standard/config/rdf.mapping.node.page.yml
@@ -31,3 +31,8 @@ fieldMappings:
callable: 'Drupal\rdf\SchemaOrgDataConverter::interactionCount'
arguments:
interaction_type: 'UserComments'
+dependencies:
+ entity:
+ - node.type.page
+ module:
+ - node
diff --git a/core/profiles/standard/config/rdf.mapping.taxonomy_term.tags.yml b/core/profiles/standard/config/rdf.mapping.taxonomy_term.tags.yml
index 051795c..60bf174 100644
--- a/core/profiles/standard/config/rdf.mapping.taxonomy_term.tags.yml
+++ b/core/profiles/standard/config/rdf.mapping.taxonomy_term.tags.yml
@@ -10,3 +10,8 @@ fieldMappings:
description:
properties:
- 'schema:description'
+dependencies:
+ entity:
+ - taxonomy.vocabulary.tags
+ module:
+ - taxonomy
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigDependencyManagerTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigDependencyManagerTest.php
new file mode 100644
index 0000000..489fa28
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigDependencyManagerTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Drupal\Tests\Core\Config;
+
+use Drupal\Tests\UnitTestCase;
+use Drupal\Core\Config\Entity\ConfigDependencyManager;
+
+/**
+ * Tests the ConfigDependencyManager class.
+ *
+ * @group Drupal
+ * @group Config
+ */
+class ConfigDependencyManagerTest extends UnitTestCase {
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'ConfigDependencyManager test',
+ 'description' => 'Tests the ConfigDependencyManager class.',
+ 'group' => 'Configuration'
+ );
+ }
+
+ public function testNoConfiguration() {
+ $dep_manger = new ConfigDependencyManager();
+ $this->assertEmpty($dep_manger->getDependentEntities('entity', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84'));
+ }
+
+ public function testNoConfigEntities() {
+ $dep_manger = new ConfigDependencyManager();
+ $dep_manger->setData(array(
+ 'simple.config' => array(
+ 'key' => 'value',
+ ),
+ ));
+ $this->assertEmpty($dep_manger->getDependentEntities('entity', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84'));
+
+ // Configuration is always dependent on its provider.
+ $dependencies = $dep_manger->getDependentEntities('module', 'simple');
+ $this->assertArrayHasKey('simple.config', $dependencies);
+ $this->assertCount(1, $dependencies);
+ }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
new file mode 100644
index 0000000..a80fc64
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
@@ -0,0 +1,264 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Config\Entity\ConfigEntityBaseUnitTest.
+ */
+
+namespace Drupal\Tests\Core\Config\Entity;
+
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Component\Plugin\PluginBase;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Config\Entity\ConfigEntityBase
+ *
+ * @group Drupal
+ * @group Config
+ */
+class ConfigEntityBaseUnitTest extends UnitTestCase {
+
+ /**
+ * The entity under test.
+ *
+ * @var \Drupal\Core\Config\Entity\ConfigEntityBase|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entity;
+
+ /**
+ * The entity type used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityType;
+
+ /**
+ * The entity manager used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityManager;
+
+ /**
+ * The ID of the type of the entity under test.
+ *
+ * @var string
+ */
+ protected $entityTypeId;
+
+ /**
+ * The UUID generator used for testing.
+ *
+ * @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $uuid;
+
+ /**
+ * The provider of the entity type.
+ *
+ * @var string
+ */
+ protected $provider;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getInfo() {
+ return array(
+ 'description' => '',
+ 'name' => '\Drupal\Core\Config\Entity\ConfigEntityBase unit test',
+ 'group' => 'Entity',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUp() {
+ $values = array();
+ $this->entityTypeId = $this->randomName();
+ $this->provider = $this->randomName();
+ $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $this->entityType->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue($this->provider));
+
+ $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
+ $this->entityManager->expects($this->any())
+ ->method('getDefinition')
+ ->with($this->entityTypeId)
+ ->will($this->returnValue($this->entityType));
+
+ $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
+
+ $container = new ContainerBuilder();
+ $container->set('entity.manager', $this->entityManager);
+ $container->set('uuid', $this->uuid);
+ \Drupal::setContainer($container);
+
+ $this->entity = $this->getMockForAbstractClass('\Drupal\Core\Config\Entity\ConfigEntityBase', array($values, $this->entityTypeId));
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependencies() {
+ // Calculating dependencies will reset the dependencies array.
+ $this->entity->set('dependencies', array('module' => array('node')));
+ $this->assertEmpty($this->entity->calculateDependencies());
+ }
+
+ /**
+ * @covers ::preSave
+ */
+ public function testPreSaveDuringSync() {
+ $query = $this->getMock('\Drupal\Core\Entity\Query\QueryInterface');
+ $storage = $this->getMock('\Drupal\Core\Config\Entity\ConfigStorageControllerInterface');
+
+ $query->expects($this->any())
+ ->method('execute')
+ ->will($this->returnValue(array()));
+ $query->expects($this->any())
+ ->method('condition')
+ ->will($this->returnValue($query));
+ $storage->expects($this->any())
+ ->method('getQuery')
+ ->will($this->returnValue($query));
+ $storage->expects($this->any())
+ ->method('loadUnchanged')
+ ->will($this->returnValue($this->entity));
+
+ // Saving an entity will not reset the dependencies array during config
+ // synchronization.
+ $this->entity->set('dependencies', array('module' => array('node')));
+ $this->entity->preSave($storage);
+ $this->assertEmpty($this->entity->get('dependencies'));
+
+ $this->entity->setSyncing(TRUE);
+ $this->entity->set('dependencies', array('module' => array('node')));
+ $this->entity->preSave($storage);
+ $dependencies = $this->entity->get('dependencies');
+ $this->assertContains('node', $dependencies['module']);
+ }
+
+ /**
+ * @covers ::addDependency
+ */
+ public function testAddDependency() {
+ $method = new \ReflectionMethod('\Drupal\Core\Config\Entity\ConfigEntityBase', 'addDependency');
+ $method->setAccessible(TRUE);
+ $method->invoke($this->entity, 'module', $this->provider);
+ $method->invoke($this->entity, 'module', 'Core');
+ $method->invoke($this->entity, 'module', 'node');
+ $dependencies = $this->entity->get('dependencies');
+ $this->assertNotContains($this->provider, $dependencies['module']);
+ $this->assertNotContains('Core', $dependencies['module']);
+ $this->assertContains('node', $dependencies['module']);
+
+ // Test sorting of dependencies.
+ $method->invoke($this->entity, 'module', 'action');
+ $dependencies = $this->entity->get('dependencies');
+ $this->assertEquals(array('action', 'node'), $dependencies['module']);
+
+ // Test sorting of dependency types.
+ $method->invoke($this->entity, 'entity', 'system.action.id');
+ $dependencies = $this->entity->get('dependencies');
+ $this->assertEquals(array('entity', 'module'), array_keys($dependencies));
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependenciesWithPluginBag() {
+ $values = array();
+ $this->entity = $this->getMockBuilder('\Drupal\Tests\Core\Config\Entity\Fixtures\ConfigEntityBaseWithPluginBag')
+ ->setConstructorArgs(array($values, $this->entityTypeId))
+ ->setMethods(array('getPluginBag'))
+ ->getMock();
+
+ // Create a configurable plugin that would add a dependency.
+ $instance_id = $this->randomName();
+ $instance = new TestConfigurablePlugin(array(), $instance_id, array('provider' => 'test'));
+
+ // Create a plugin bag to contain the instance.
+ $pluginBag = $this->getMockBuilder('\Drupal\Core\Plugin\DefaultPluginBag')
+ ->disableOriginalConstructor()
+ ->setMethods(array('get'))
+ ->getMock();
+ $pluginBag->expects($this->atLeastOnce())
+ ->method('get')
+ ->with($instance_id)
+ ->will($this->returnValue($instance));
+ $pluginBag->addInstanceId($instance_id);
+
+ // Return the mocked plugin bag.
+ $this->entity->expects($this->once())
+ ->method('getPluginBag')
+ ->will($this->returnValue($pluginBag));
+
+ $dependencies = $this->entity->calculateDependencies();
+ $this->assertContains('test', $dependencies['module']);
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependenciesWithPluginBagSameProviderAsEntityType() {
+ $values = array();
+ $this->entity = $this->getMockBuilder('\Drupal\Tests\Core\Config\Entity\Fixtures\ConfigEntityBaseWithPluginBag')
+ ->setConstructorArgs(array($values, $this->entityTypeId))
+ ->setMethods(array('getPluginBag'))
+ ->getMock();
+
+ // Create a configurable plugin that will not add a dependency since it is
+ // provider matches the provider of the entity type.
+ $instance_id = $this->randomName();
+ $instance = new TestConfigurablePlugin(array(), $instance_id, array('provider' => $this->provider));
+
+ // Create a plugin bag to contain the instance.
+ $pluginBag = $this->getMockBuilder('\Drupal\Core\Plugin\DefaultPluginBag')
+ ->disableOriginalConstructor()
+ ->setMethods(array('get'))
+ ->getMock();
+ $pluginBag->expects($this->atLeastOnce())
+ ->method('get')
+ ->with($instance_id)
+ ->will($this->returnValue($instance));
+ $pluginBag->addInstanceId($instance_id);
+
+ // Return the mocked plugin bag.
+ $this->entity->expects($this->once())
+ ->method('getPluginBag')
+ ->will($this->returnValue($pluginBag));
+
+ $this->assertEmpty($this->entity->calculateDependencies());
+ }
+
+}
+
+class TestConfigurablePlugin extends PluginBase implements ConfigurablePluginInterface {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfiguration() {
+ return $this->configuration;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setConfiguration(array $configuration) {
+ $this->configuration = $configuration;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function defaultConfiguration() {
+ return array();
+ }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityDependencyTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityDependencyTest.php
new file mode 100644
index 0000000..a653730
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityDependencyTest.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace Drupal\Tests\Core\Config;
+
+use Drupal\Tests\UnitTestCase;
+use Drupal\Core\Config\Entity\ConfigEntityDependency;
+
+/**
+ * Tests the ConfigEntityDependency class.
+ *
+ * @group Drupal
+ * @group Config
+ */
+class ConfigEntityDependencyTest extends UnitTestCase {
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'ConfigEntityDependency test',
+ 'description' => 'Tests the ConfigEntityDependency class.',
+ 'group' => 'Configuration'
+ );
+ }
+
+ public function testEmptyDependencies() {
+ $dep = new ConfigEntityDependency('config_test.dynamic.entity_id', array());
+
+ $this->assertEquals('config_test.dynamic.entity_id', $dep->getConfigDependencyName());
+ $this->assertEquals(array(), $dep->getDependencies('theme'));
+ $this->assertEquals(array(), $dep->getDependencies('entity'));
+ $this->assertEquals(array('config_test'), $dep->getDependencies('module'));
+ $this->assertTrue($dep->hasDependency('module', 'config_test'));
+ $this->assertFalse($dep->hasDependency('module', 'views'));
+ }
+
+ public function testWithDependencies() {
+ $values = array(
+ 'uuid' => '60db47f4-54fb-4c86-a439-5769fbda4bd1',
+ 'dependencies' => array(
+ 'module' => array(
+ 'node',
+ 'views'
+ ),
+ 'entity' => array(
+ 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84',
+ ),
+ ),
+ );
+ $dep = new ConfigEntityDependency('config_test.dynamic.entity_id', $values);
+
+ $this->assertEquals(array(), $dep->getDependencies('theme'));
+ $this->assertEquals(array('config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84'), $dep->getDependencies('entity'));
+ $this->assertEquals(array('node', 'views', 'config_test'), $dep->getDependencies('module'));
+ $this->assertTrue($dep->hasDependency('module', 'config_test'));
+ $this->assertTrue($dep->hasDependency('module', 'views'));
+ $this->assertTrue($dep->hasDependency('module', 'node'));
+ $this->assertFalse($dep->hasDependency('module', 'block'));
+ $this->assertTrue($dep->hasDependency('entity', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84'));
+ $this->assertFalse($dep->hasDependency('entity', 'config_test.dynamic.another_id:7dfa5cb7-2248-4d52-8c00-cd8e02d1e78e'));
+ }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/EntityDisplayModeBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/EntityDisplayModeBaseUnitTest.php
new file mode 100644
index 0000000..314e044
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/EntityDisplayModeBaseUnitTest.php
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Config\Entity\EntityDisplayModeBaseUnitTest.
+ */
+
+namespace Drupal\Tests\Core\Config\Entity;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\entity\EntityDisplayModeBase
+ *
+ * @group Drupal
+ * @group Config
+ */
+class EntityDisplayModeBaseUnitTest extends UnitTestCase {
+
+ /**
+ * The entity under test.
+ *
+ * @var \Drupal\entity\EntityDisplayModeBase|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entity;
+
+ /**
+ * The entity type used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityInfo;
+
+ /**
+ * The entity manager used for testing.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityManager;
+
+ /**
+ * The ID of the type of the entity under test.
+ *
+ * @var string
+ */
+ protected $entityType;
+
+ /**
+ * The UUID generator used for testing.
+ *
+ * @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $uuid;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getInfo() {
+ return array(
+ 'description' => '',
+ 'name' => '\Drupal\entity\EntityDisplayModeBase unit test',
+ 'group' => 'Entity',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUp() {
+ $this->entityType = $this->randomName();
+
+ $this->entityInfo = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $this->entityInfo->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue('entity'));
+
+ $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
+
+ $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
+
+ $container = new ContainerBuilder();
+ $container->set('entity.manager', $this->entityManager);
+ $container->set('uuid', $this->uuid);
+ \Drupal::setContainer($container);
+
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDependencies() {
+ $target_entity_type_id = $this->randomName(16);
+
+ $target_entity_type = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+ $target_entity_type->expects($this->any())
+ ->method('getProvider')
+ ->will($this->returnValue('test_module'));
+ $values = array('targetEntityType' => $target_entity_type_id);
+
+ $this->entityManager->expects($this->at(0))
+ ->method('getDefinition')
+ ->with($target_entity_type_id)
+ ->will($this->returnValue($target_entity_type));
+ $this->entityManager->expects($this->at(1))
+ ->method('getDefinition')
+ ->with($this->entityType)
+ ->will($this->returnValue($this->entityInfo));
+
+ $this->entity = $this->getMockBuilder('\Drupal\entity\EntityDisplayModeBase')
+ ->setConstructorArgs(array($values, $this->entityType))
+ ->setMethods(array('getFilterFormat'))
+ ->getMock();
+
+ $dependencies = $this->entity->calculateDependencies();
+ $this->assertContains('test_module', $dependencies['module']);
+
+ }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/Fixtures/ConfigEntityBaseWithPluginBag.php b/core/tests/Drupal/Tests/Core/Config/Entity/Fixtures/ConfigEntityBaseWithPluginBag.php
new file mode 100644
index 0000000..85a7f10
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/Fixtures/ConfigEntityBaseWithPluginBag.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Config\Entity\Fixtures\ConfigEntityBaseWithPluginBag.
+ */
+
+namespace Drupal\Tests\Core\Config\Entity\Fixtures;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\Core\Config\Entity\EntityWithPluginBagInterface;
+
+/**
+ * Enables testing of dependency calculation.
+ *
+ * @see \Drupal\Tests\Core\Config\Entity\ConfigEntityBaseUnitTest::testCalculateDependenciesWithPluginBag()
+ * @see \Drupal\Core\Config\Entity\ConfigEntityBase::calculateDependencies()
+ */
+abstract class ConfigEntityBaseWithPluginBag extends ConfigEntityBase implements EntityWithPluginBagInterface {
+}