diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php index 39f8d8a..42dbf18 100644 --- a/core/lib/Drupal/Core/Config/ConfigInstaller.php +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php @@ -131,6 +131,8 @@ public function installDefaultConfig($type, $name) { } $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 65a7846..03c19b8 100644 --- a/core/lib/Drupal/Core/Config/ConfigManager.php +++ b/core/lib/Drupal/Core/Config/ConfigManager.php @@ -7,6 +7,8 @@ namespace Drupal\Core\Config; +use Drupal\Component\Utility\Unicode; +use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\StringTranslation\TranslationManager; @@ -135,4 +137,43 @@ function uninstall($type, $name) { $this->typedConfigManager->clearCachedDefinitions(); } } + + /** + * {@inheritdoc} + */ + public function findConfigEntityDependents($type, $name) { + // Create a list of all config entity types. + /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface[] $config_entity_types */ + $config_entity_types = array_filter($this->entityManager->getDefinitions(), function (EntityTypeInterface $entity_type) { + return $entity_type->isSubClassOf('\Drupal\Core\Config\Entity\ConfigEntityInterface'); + }); + + // Find all the entities for all the types. + $entities = array(); + foreach($config_entity_types as $config_entity_type) { + $found = $this->configFactory->listAll($config_entity_type->getConfigPrefix(). '.'); + if (!empty($found)) { + array_walk($found, function (&$id) use ($config_entity_type) { + $id = Unicode::substr($id, Unicode::strlen($config_entity_type->getConfigPrefix()) + 1); + }); + $entities[$config_entity_type->id()] = $found; + } + } + + // Load all the entities and check the dependency. + $dependent_entities = array(); + // No graph needed. + if ($type = 'module' || $type = 'theme') { + foreach ($entities as $entity_type_id => $entities_to_load) { + $controller = $this->entityManager->getStorageController($entity_type_id); + $dependent_entities[$entity_type_id] = array_filter($controller->loadMultiple($entities_to_load), function (ConfigEntityInterface $entity) use ($type, $name) { + return $entity->hasDependency($type, $name); + }); + } + } + + // Remove entities types with no dependent entities. + return array_filter($dependent_entities); + } + } diff --git a/core/lib/Drupal/Core/Config/ConfigManagerInterface.php b/core/lib/Drupal/Core/Config/ConfigManagerInterface.php index e63108d..4cc5b6c 100644 --- a/core/lib/Drupal/Core/Config/ConfigManagerInterface.php +++ b/core/lib/Drupal/Core/Config/ConfigManagerInterface.php @@ -68,4 +68,19 @@ public function createSnapshot(StorageInterface $source_storage, StorageInterfac */ public function uninstall($type, $name); + /** + * Finds config entities that are dependent on the supplied extension or entity. + * + * @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 the name of the module or theme. In the case of entity it + * should be entity_type:uuid. + * + * @return array + * Arrays of dependent configuration entity keyed by entity type. + */ + public function findConfigEntityDependents($type, $name); + } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index cd870f2..cd89a79 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -43,6 +43,13 @@ private $isSyncing = FALSE; /** + * The configuration entity's dependencies. + * + * @var array + */ + protected $dependencies = array(); + + /** * Overrides Entity::__construct(). */ public function __construct(array $values, $entity_type) { @@ -176,6 +183,10 @@ public function getExportProperties() { $name = $property->getName(); $properties[$name] = $this->get($name); } + if (!empty($this->dependencies)) { + // Add protected dependencies property if set. + $properties['dependencies'] = $this->dependencies; + } return $properties; } @@ -225,4 +236,31 @@ public function url($rel = 'edit-form', $options = array()) { return parent::url($rel, $options); } + /** + * {@inheritdoc} + */ + public function hasDependency($type, $name) { + // A config entity is always dependent on it's provider. + if ($type == 'module' && $name == $this->getEntityType()->getProvider()) { + return TRUE; + } + return isset($this->dependencies[$type]) && !empty($this->dependencies[$type][$name]); + } + + /** + * {@inheritdoc} + */ + public function createDependency($type, $name) { + $this->dependencies[$type][$name] = TRUE; + return $this; + } + + /** + * {@inheritdoc} + */ + public function removeDependency($type, $name) { + unset($this->dependencies[$type][$name]); + return $this; + } + } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php index 5aa737d..44d0e62 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php @@ -122,4 +122,44 @@ public function set($property_name, $value); */ public function getExportProperties(); + /** + * Checks if the configuration entity has a dependency. + * + * @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 the name of the module or theme. In the case of entity it + * should be entity_type:uuid. + * + * @return bool + * TRUE if the configuration is dependent. + */ + public function hasDependency($type, $name); + + /** + * 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 entity_type:uuid. + * + * @return $this + */ + public function createDependency($type, $name); + + /** + * Removes 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 entity_type:uuid. + * + * @return $this + */ + public function removeDependency($type, $name); } diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php index 001e278..96e71a2 100644 --- a/core/lib/Drupal/Core/Extension/ModuleHandler.php +++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php @@ -721,6 +721,13 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) { // Allow modules to react prior to the uninstallation of a module. $this->invokeAll('module_preuninstall', array($module)); + // Remove all dependent configuration entities. + $dependent_entities = $this->findConfigEntityDependents(array($module)); + foreach ($dependent_entities as $entity_type_id => $entities) { + $controller = \Drupal::entityManager()->getStorageController($entity_type_id); + $controller->delete($entities); + } + // Uninstall the module. module_load_install($module); $this->invoke($module, 'uninstall'); @@ -820,4 +827,16 @@ public function getModuleDirectories() { } return $dirs; } + + /** + * {@inheritdoc} + */ + public function findConfigEntityDependents(array $modules) { + $dependents = array(); + foreach ($modules as $module) { + $dependents = NestedArray::mergeDeep($dependents, \Drupal::service('config.manager')->findConfigEntityDependents('module', $module)); + } + return $dependents; + } + } diff --git a/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php b/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php index a74f9cd..9ba4088 100644 --- a/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php +++ b/core/lib/Drupal/Core/Extension/ModuleHandlerInterface.php @@ -306,4 +306,16 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE); */ public function getModuleDirectories(); + /** + * Finds config entities that are dependent on the a list of modules. + * + * @see \Drupal\Core\Config\ConfigManager::findConfigEntityDependents() + * + * @param array $modules + * The list of modules to check. + * + * @return array + * Arrays of dependent configuration entity keyed by entity type. + */ + public function findConfigEntityDependents(array $modules); } diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php index 19ebaff..2322324 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php @@ -272,4 +272,19 @@ function testCRUDUI() { } + public function testDependencyManagement () { + // Verify properties on a newly created entity. + $config_test = entity_create('config_test', $expected = array( + 'id' => $this->randomName(), + 'label' => $this->randomString(), + 'style' => $this->randomName(), + )); + $config_test->createDependency('module', 'node'); + $config_test->save(); + + // Test that dependencies are maintained. + $config_test = entity_load('config_test', $config_test->id()); + $this->assertTrue($config_test->hasDependency('module', 'node')); + $this->assertFalse($config_test->hasDependency('module', 'views')); + } } diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php index df6c96d..9b09219 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php @@ -100,4 +100,18 @@ protected function testGetOriginalId() { $this->assertIdentical($entity->getOriginalId(), $id); } + /** + * Tests setDependency(), hasDependency() and removeDependency(). + */ + protected function testDependencyMangement() { + $entity = $this->storage->create(array()); + $entity->createDependency('module', 'node'); + $this->assertTrue($entity->hasDependency('module', 'node')); + $this->assertTrue($entity->hasDependency('module', 'config_test')); + $this->assertFalse($entity->hasDependency('module', 'views')); + $entity->removeDependency('module', 'node'); + $this->assertFalse($entity->hasDependency('module', 'node')); + $this->assertTrue($entity->hasDependency('module', 'config_test')); + } + } diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php index 90915fc..5d3b423 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php @@ -93,4 +93,11 @@ public function testInstallConfigEnityModuleFirst() { $this->assertTrue(entity_load('config_test', 'other_module', TRUE), 'Default configuration provided by config_other_module_config has been installed.'); } + public function testUninstall() { + $this->moduleHandler->install(array('views')); + $this->assertTrue(entity_load('view', 'frontpage', TRUE) !== NULL, 'Frontpage view which is dependant on the Node module exists.'); + $this->moduleHandler->uninstall(array('node')); + $this->assertTrue(entity_load('view', 'frontpage', TRUE) === NULL, 'Frontpage view which is dependant on the Node module does not exist.'); + } + } diff --git a/core/modules/language/lib/Drupal/language/Entity/Language.php b/core/modules/language/lib/Drupal/language/Entity/Language.php index 63e8542..ed5c0bd 100644 --- a/core/modules/language/lib/Drupal/language/Entity/Language.php +++ b/core/modules/language/lib/Drupal/language/Entity/Language.php @@ -105,11 +105,35 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { * @throws \RuntimeException */ public static function preDelete(EntityStorageControllerInterface $storage_controller, array $entities) { - $default_language = \Drupal::service('language.default')->get(); + $default_language = static::getDefaultLanguage(); foreach ($entities as $entity) { if ($entity->id() == $default_language->id) { throw new DeleteDefaultLanguageException('Can not delete the default language'); } } } + + /** + * {@inheritdoc} + */ + public function hasDependency($type, $name) { + // Default languages can not be removed so do not allow them to be dependent + // on anything. This gets around the fact that uninstalling language would + // attempt to delete the default language which would cause the exception in + // \Drupal\language\Entity\Language::preDelete() to be thrown. + if ($this->id() == $this->getDefaultLanguage()->id) { + return FALSE; + } + return parent::hasDependency($type, $name); + } + + /** + * Gets the default language. + * + * @return \Drupal\Core\Language\Language + */ + protected static function getDefaultLanguage() { + return \Drupal::service('language.default')->get(); + } + } diff --git a/core/modules/views/config/views.view.archive.yml b/core/modules/node/config/views.view.archive.yml similarity index 100% rename from core/modules/views/config/views.view.archive.yml rename to core/modules/node/config/views.view.archive.yml diff --git a/core/modules/views/config/views.view.glossary.yml b/core/modules/node/config/views.view.glossary.yml similarity index 100% rename from core/modules/views/config/views.view.glossary.yml rename to core/modules/node/config/views.view.glossary.yml diff --git a/core/modules/views/config/views.view.tracker.yml b/core/modules/node/config/views.view.tracker.yml similarity index 100% rename from core/modules/views/config/views.view.tracker.yml rename to core/modules/node/config/views.view.tracker.yml diff --git a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php index 738dda2..880515d 100644 --- a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php +++ b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php @@ -121,6 +121,31 @@ public function buildForm(array $form, array &$form_state) { }, $this->modules), ); + $form['entities'] = array( + '#type' => 'details', + '#title' => $this->t('Further information'), + '#description' => $this->t('The listed entities will be deleted.'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#access' => FALSE, + ); + + // Get the dependent entities. + $dependent_entities = $this->moduleHandler->findConfigEntityDependents($this->modules); + if (!empty($dependent_entities)) { + $form['entities']['#access'] = TRUE; + } + foreach ($dependent_entities as $entity_type_id =>$entities) { + $entity_type = \Drupal::entityManager()->getDefinition($entity_type_id); + $form['entities'][$entity_type_id] = array( + '#theme' => 'item_list', + '#title' => $entity_type->getLabel(), + '#items' => array_map(function ($entity) { + return $entity->label(); + }, $entities), + ); + } + return parent::buildForm($form, $form_state); } diff --git a/core/modules/views/config/views.view.taxonomy_term.yml b/core/modules/taxonomy/config/views.view.taxonomy_term.yml similarity index 100% rename from core/modules/views/config/views.view.taxonomy_term.yml rename to core/modules/taxonomy/config/views.view.taxonomy_term.yml diff --git a/core/modules/views/lib/Drupal/views/Entity/View.php b/core/modules/views/lib/Drupal/views/Entity/View.php index f96fbd0..2d7f241 100644 --- a/core/modules/views/lib/Drupal/views/Entity/View.php +++ b/core/modules/views/lib/Drupal/views/Entity/View.php @@ -22,7 +22,7 @@ * id = "view", * label = @Translation("View"), * controllers = { - * "storage" = "Drupal\views\ViewStorageController", + * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "access" = "Drupal\views\ViewAccessController" * }, * admin_permission = "administer views", @@ -372,4 +372,14 @@ public function mergeDefaultDisplaysOptions() { $this->set('display', $displays); } + /** + * {@inheritdoc} + */ + public function hasDependency($type, $name) { + if ($type == 'module' && $this->module == $name) { + return TRUE; + } + return parent::hasDependency($type, $name); + } + } diff --git a/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php b/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php index 8c31874..ed194cf 100644 --- a/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php @@ -151,6 +151,7 @@ public function customErrorHandler($error_level, $message, $filename, $line, $co */ 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/ViewStorageTest.php b/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php index ba67b0a..37d5ca7 100644 --- a/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php @@ -8,17 +8,17 @@ 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; use Drupal\views\Plugin\views\display\Feed; /** - * 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 { @@ -49,7 +49,7 @@ class ViewStorageTest extends ViewUnitTestBase { /** * The configuration entity storage controller. * - * @var \Drupal\views\ViewStorageController + * @var \Drupal\Core\Config\Entity\ConfigStorageController */ protected $controller; @@ -80,7 +80,7 @@ function testConfigurationEntityCRUD() { $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.'); + $this->assertTrue($this->controller instanceof ConfigStorageController, 'The correct controller is loaded.'); // CRUD tests. $this->loadTests(); 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 @@ -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 @@ public static function getInfo() { 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 @@ protected function setUp() { ->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 @@ public static function getInfo() { } 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 @@ protected function setUp() { $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/lib/Drupal/views_ui/ViewUI.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php index b63b76d..21d56c3 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php @@ -1178,4 +1178,22 @@ public function hasLinkTemplate($key) { return $this->storage->hasLinkTemplate($key); } + /** + * {@inheritdoc} + */ + public function hasDependency($type, $name){ + } + + /** + * {@inheritdoc} + */ + public function createDependency($type, $name){ + } + + /** + * {@inheritdoc} + */ + public function removeDependency($type, $name){ + } + } 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 @@ public static function getInfo() { * @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')