diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 9a0d713..ac60a08 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1721,6 +1721,7 @@ function theme_links($variables) { } // Handle title-only text items. else { + debug($key); // Merge in default array properties into $link. $link += array( 'html' => FALSE, diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityListController.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityListController.php index b363cc4..2cfb551 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityListController.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityListController.php @@ -27,40 +27,4 @@ public function load() { return $entities; } - /** - * {@inheritdoc} - */ - public function getOperations(EntityInterface $entity) { - $operations = parent::getOperations($entity); - $uri = $entity->uri(); - - // Ensure the edit operation exists since it is access controlled. - if (isset($operations['edit'])) { - // For configuration entities edit path is the MENU_DEFAULT_LOCAL_TASK and - // therefore should be accessed by the short route. - $operations['edit']['href'] = $uri['path']; - } - - if (isset($this->entityInfo['entity_keys']['status'])) { - if (!$entity->status()) { - $operations['enable'] = array( - 'title' => t('Enable'), - 'href' => $uri['path'] . '/enable', - 'options' => $uri['options'], - 'weight' => -10, - ); - } - else { - $operations['disable'] = array( - 'title' => t('Disable'), - 'href' => $uri['path'] . '/disable', - 'options' => $uri['options'], - 'weight' => 40, - ); - } - } - - return $operations; - } - } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityOperationsProvider.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityOperationsProvider.php new file mode 100644 index 0000000..e3ad4d6 --- /dev/null +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityOperationsProvider.php @@ -0,0 +1,51 @@ +uri(); + $operations = parent::getDefaultOperations($entity); + + // For configuration entities edit path is the MENU_DEFAULT_LOCAL_TASK and + // therefore should be accessed by the short route. + $operations['update']['href'] = $uri['path']; + + $info = $entity->entityInfo(); + if (isset($info['entity_keys']['status'])) { + if (!$entity->status()) { + $operations['enable'] = array( + 'title' => $this->translationManager->translate('Enable'), + 'href' => $uri['path'] . '/enable', + 'options' => $uri['options'], + 'weight' => -10, + ); + } + else { + $operations['disable'] = array( + 'title' => $this->translationManager->translate('Disable'), + 'href' => $uri['path'] . '/disable', + 'options' => $uri['options'], + 'weight' => 40, + ); + } + } + + return $operations; + } +} diff --git a/core/lib/Drupal/Core/Config/Entity/DraggableListController.php b/core/lib/Drupal/Core/Config/Entity/DraggableListController.php index 5370be5..9c4c5bd 100644 --- a/core/lib/Drupal/Core/Config/Entity/DraggableListController.php +++ b/core/lib/Drupal/Core/Config/Entity/DraggableListController.php @@ -8,9 +8,11 @@ namespace Drupal\Core\Config\Entity; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityOperationsProviderInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormInterface; +use Drupal\Core\Session\AccountInterface; /** * Provides a list controller for draggable configuration entities. @@ -41,8 +43,8 @@ /** * {@inheritdoc} */ - public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler) { - parent::__construct($entity_type, $entity_info, $storage, $module_handler); + public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, EntityOperationsProviderInterface $operations, ModuleHandlerInterface $module_handler, AccountInterface $current_user) { + parent::__construct($entity_type, $entity_info, $storage, $operations, $module_handler, $current_user); // Check if the entity type supports weighting. if (!empty($this->entityInfo['entity_keys']['weight'])) { diff --git a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php index b46d9f7..1b55f0c 100644 --- a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php +++ b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php @@ -57,6 +57,10 @@ class EntityType extends Plugin { * - translation: The name of the controller class that should be used to * handle the translation process. The class must implement * \Drupal\content_translation\ContentTranslationControllerInterface. + * - operations: The name of the controller class that provides entity + * operations, for which access checks must be run through the "access" + * controller. The class must implement + * \Drupal\Core\Entity\EntityOperationsProviderInterface. * * @todo Interfaces from outside \Drupal\Core or \Drupal\Component should not * be used here. diff --git a/core/lib/Drupal/Core/Entity/EntityListController.php b/core/lib/Drupal/Core/Entity/EntityListController.php index 0a722a0..8bd2ccb 100644 --- a/core/lib/Drupal/Core/Entity/EntityListController.php +++ b/core/lib/Drupal/Core/Entity/EntityListController.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Entity; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\TranslationInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Component\Utility\String; @@ -18,6 +19,13 @@ class EntityListController implements EntityListControllerInterface, EntityControllerInterface { /** + * The current user. + * + * @var \Drupal\Core\Session\AccountInterface + */ + protected $currentUser; + + /** * The entity storage controller class. * * @var \Drupal\Core\Entity\EntityStorageControllerInterface @@ -25,6 +33,13 @@ class EntityListController implements EntityListControllerInterface, EntityContr protected $storage; /** + * The entity operations controller. + * + * @var \Drupal\Core\Entity\EntityOperationsProviderInterface + */ + protected $operations; + + /** * The module handler to invoke hooks on. * * @var \Drupal\Core\Extension\ModuleHandlerInterface @@ -62,7 +77,9 @@ public static function createInstance(ContainerInterface $container, $entity_typ $entity_type, $entity_info, $container->get('entity.manager')->getStorageController($entity_type), - $container->get('module_handler') + $container->get('entity.manager')->getOperationsProvider($entity_type), + $container->get('module_handler'), + $container->get('current_user') ); } @@ -75,14 +92,20 @@ public static function createInstance(ContainerInterface $container, $entity_typ * An array of entity info for the entity type. * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage * The entity storage controller class. + * @param \Drupal\Core\Entity\EntityOperationsProviderInterface $operations + * The entity operations controller. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke hooks on. + * @param \Drupal\Core\Session\AccountInterface $current_user + * The current user. */ - public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler) { + public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, EntityOperationsProviderInterface $operations, ModuleHandlerInterface $module_handler, AccountInterface $current_user) { $this->entityType = $entity_type; $this->storage = $storage; + $this->operations = $operations; $this->entityInfo = $entity_info; $this->moduleHandler = $module_handler; + $this->currentUser = $current_user; } /** @@ -113,33 +136,6 @@ protected function getLabel(EntityInterface $entity) { } /** - * {@inheritdoc} - */ - public function getOperations(EntityInterface $entity) { - $uri = $entity->uri(); - - $operations = array(); - if ($entity->access('update')) { - $operations['edit'] = array( - 'title' => $this->t('Edit'), - 'href' => $uri['path'] . '/edit', - 'options' => $uri['options'], - 'weight' => 10, - ); - } - if ($entity->access('delete')) { - $operations['delete'] = array( - 'title' => $this->t('Delete'), - 'href' => $uri['path'] . '/delete', - 'options' => $uri['options'], - 'weight' => 100, - ); - } - - return $operations; - } - - /** * Builds the header row for the entity listing. * * @return array @@ -164,31 +160,12 @@ public function buildHeader() { * @see \Drupal\Core\Entity\EntityListController::render() */ public function buildRow(EntityInterface $entity) { - $row['operations']['data'] = $this->buildOperations($entity); - return $row; - } - - /** - * Builds a renderable list of operation links for the entity. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity on which the linked operations will be performed. - * - * @return array - * A renderable array of operation links. - * - * @see \Drupal\Core\Entity\EntityListController::render() - */ - public function buildOperations(EntityInterface $entity) { - // Retrieve and sort operations. - $operations = $this->getOperations($entity); - $this->moduleHandler->alter('entity_operation', $operations, $entity); - uasort($operations, 'drupal_sort_weight'); - $build = array( + $row['operations']['data'] = array( '#type' => 'operations', - '#links' => $operations, + '#links' => $this->operations->getOperations($entity, $this->currentUser), ); - return $build; + + return $row; } /** diff --git a/core/lib/Drupal/Core/Entity/EntityListControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityListControllerInterface.php index b7581d8..a56d959 100644 --- a/core/lib/Drupal/Core/Entity/EntityListControllerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityListControllerInterface.php @@ -32,22 +32,6 @@ public function getStorageController(); public function load(); /** - * Provides an array of information to build a list of operation links. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity the operations are for. - * - * @return array - * An associative array of operation link data for this list, keyed by - * operation name, containing the following key-value pairs: - * - title: The localized title of the operation. - * - href: The path for the operation. - * - options: An array of URL options for the path. - * - weight: The weight of this operation. - */ - public function getOperations(EntityInterface $entity); - - /** * Renders the list page markup to be output. * * @return string diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index 5fc2d16..f1e9fd5 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -286,6 +286,18 @@ protected function getController($entity_type, $controller_type) { } /** + * Gets an entity type's operations controller. + * + * @param string $entity_type + * The entity type for this operations controller. + * + * @return \Drupal\Core\Entity\EntityOperationsProviderInterface. + */ + public function getOperationsProvider($entity_type) { + return $this->getController($entity_type, 'operations'); + } + + /** * {@inheritdoc} */ public function getForm(EntityInterface $entity, $operation = 'default', array $form_state = array()) { diff --git a/core/lib/Drupal/Core/Entity/EntityOperationsProvider.php b/core/lib/Drupal/Core/Entity/EntityOperationsProvider.php new file mode 100644 index 0000000..4b1c148 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/EntityOperationsProvider.php @@ -0,0 +1,104 @@ +moduleHandler = $module_handler; + $this->translationManager = $translation_manager; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + return new static($container->get('module_handler'), $container->get('string_translation')); + } + + /** + * {@inheritdoc} + */ + public function getOperations(EntityInterface $entity, AccountInterface $account) { + // Operations are retrieved from specific to non-specific contexts (the + // controller, the entity-type-specific hook, and the generic hook). + $operations = $this->getDefaultOperations($entity); + $hooks = array($entity->entityType() . '_operations' , 'entity_operations'); + foreach ($hooks as $hook) { + $operations = array_merge($this->moduleHandler->invokeAll($hook, array($entity)), $operations); + } + $this->moduleHandler->alter(array('entity_operations', $entity->entityType() . '_operations'), $entity, $operations); + + // Check access to the operations. + foreach ($operations as $operation => $operation_link) { + if (!$entity->access($operation, $account)) { + unset($operations[$operation]); + } + } +// @todo Sort operations by weight and human-readable label. + + return $operations; + } + + /** + * Gets the entity's default operations. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * + * @return array + * The structure is identical to that of the return value of + * self::getOperations(). + */ + protected function getDefaultOperations(EntityInterface $entity) { + $uri = $entity->uri(); + $operations = array(); + $operations['update'] = array( + 'title' => $this->translationManager->translate('Edit'), + 'href' => $uri['path'] . '/edit', + 'options' => $uri['options'], + 'weight' => 10, + ); + $operations['delete'] = array( + 'title' => $this->translationManager->translate('Delete'), + 'href' => $uri['path'] . '/delete', + 'options' => $uri['options'], + 'weight' => 100, + ); + + return $operations; + } +} diff --git a/core/lib/Drupal/Core/Entity/EntityOperationsProviderInterface.php b/core/lib/Drupal/Core/Entity/EntityOperationsProviderInterface.php new file mode 100644 index 0000000..f0a3dbf --- /dev/null +++ b/core/lib/Drupal/Core/Entity/EntityOperationsProviderInterface.php @@ -0,0 +1,32 @@ +actionManager = $action_manager; } @@ -60,8 +66,10 @@ public static function createInstance(ContainerInterface $container, $entity_typ $entity_type, $entity_info, $container->get('entity.manager')->getStorageController($entity_type), + $container->get('entity.manager')->getOperationsProvider($entity_type), $container->get('plugin.manager.action'), - $container->get('module_handler') + $container->get('module_handler'), + $container->get('current_user') ); } @@ -105,17 +113,6 @@ public function buildHeader() { /** * {@inheritdoc} */ - public function getOperations(EntityInterface $entity) { - $operations = $entity->isConfigurable() ? parent::getOperations($entity) : array(); - if (isset($operations['edit'])) { - $operations['edit']['title'] = t('Configure'); - } - return $operations; - } - - /** - * {@inheritdoc} - */ public function render() { $build['action_header']['#markup'] = '

' . t('Available actions:') . '

'; $build['action_table'] = parent::render(); diff --git a/core/modules/action/lib/Drupal/action/ActionOperationsProvider.php b/core/modules/action/lib/Drupal/action/ActionOperationsProvider.php new file mode 100644 index 0000000..1e476c2 --- /dev/null +++ b/core/modules/action/lib/Drupal/action/ActionOperationsProvider.php @@ -0,0 +1,30 @@ +isConfigurable()) { + return array(); + } + + $operations = parent::getDefaultOperations($entity); + $operations['update']['title'] = t('Configure'); + return $operations; + } +} diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockListController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockListController.php index efa31b3..012e2b8 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockListController.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockListController.php @@ -31,18 +31,4 @@ public function buildRow(EntityInterface $entity) { return $row + parent::buildRow($entity); } - /** - * {@inheritdoc} - */ - public function getOperations(EntityInterface $entity) { - $operations = parent::getOperations($entity); - // The custom block edit path does not contain '/edit'. - if (isset($operations['edit'])) { - $uri = $entity->uri(); - $operations['edit']['href'] = $uri['path']; - $operations['edit']['query']['destination'] = 'admin/structure/block/custom-blocks'; - } - return $operations; - } - } diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockOperationsProvider.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockOperationsProvider.php new file mode 100644 index 0000000..974cda3 --- /dev/null +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockOperationsProvider.php @@ -0,0 +1,31 @@ +uri(); + $operations['update']['href'] = $uri['path']; + $operations['update']['query']['destination'] = 'admin/structure/block/custom-blocks'; + + return $operations; + } + +} diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListController.php index efa4380..004b1af 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListController.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListController.php @@ -16,19 +16,6 @@ class CustomBlockTypeListController extends ConfigEntityListController { /** - * {@inheritdoc} - */ - public function getOperations(EntityInterface $entity) { - $operations = parent::getOperations($entity); - // Place the edit operation after the operations added by field_ui.module - // which have the weights 15, 20, 25. - if (isset($operations['edit'])) { - $operations['edit']['weight'] = 30; - } - return $operations; - } - - /** * Overrides \Drupal\Core\Entity\EntityListController::buildHeader(). */ public function buildHeader() { diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeOperationsProvider.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeOperationsProvider.php new file mode 100644 index 0000000..3793f97 --- /dev/null +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeOperationsProvider.php @@ -0,0 +1,29 @@ +blockManager = $block_manager; } @@ -80,7 +86,9 @@ public static function createInstance(ContainerInterface $container, $entity_typ $entity_type, $entity_info, $container->get('entity.manager')->getStorageController($entity_type), + $container->get('entity.manager')->getOperationsProvider($entity_type), $container->get('module_handler'), + $container->get('current_user'), $container->get('plugin.manager.block') ); } @@ -287,7 +295,10 @@ public function buildForm(array $form, array &$form_state) { 'class' => array('block-weight', 'block-weight-' . $region), ), ); - $form['blocks'][$entity_id]['operations'] = $this->buildOperations($info['entity']); + $form['blocks'][$entity_id]['operations']['data'] = array( + '#type' => 'operations', + '#links' => $this->operations->getOperations($info['entity'], $this->currentUser), + ); } } } @@ -375,19 +386,6 @@ public function buildForm(array $form, array &$form_state) { } /** - * {@inheritdoc} - */ - public function getOperations(EntityInterface $entity) { - $operations = parent::getOperations($entity); - - if (isset($operations['edit'])) { - $operations['edit']['title'] = t('Configure'); - } - - return $operations; - } - - /** * Implements \Drupal\Core\Form\FormInterface::validateForm(). */ public function validateForm(array &$form, array &$form_state) { diff --git a/core/modules/block/lib/Drupal/block/Entity/Block.php b/core/modules/block/lib/Drupal/block/Entity/Block.php index f433ea6..608fc85 100644 --- a/core/modules/block/lib/Drupal/block/Entity/Block.php +++ b/core/modules/block/lib/Drupal/block/Entity/Block.php @@ -21,6 +21,7 @@ * id = "block", * label = @Translation("Block"), * controllers = { + * "operations" = "Drupal\Core\Config\Entity\ConfigEntityOperationsProvider", * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "access" = "Drupal\block\BlockAccessController", * "view_builder" = "Drupal\block\BlockViewBuilder", diff --git a/core/modules/block/lib/Drupal/block/Entity/BlockOperationsProvider.php b/core/modules/block/lib/Drupal/block/Entity/BlockOperationsProvider.php new file mode 100644 index 0000000..7632b4a --- /dev/null +++ b/core/modules/block/lib/Drupal/block/Entity/BlockOperationsProvider.php @@ -0,0 +1,27 @@ +assertTrue(!empty($entity), '"Default" ConfigTest entity ID found.'); $this->assertTrue($entity instanceof ConfigTest, '"Default" ConfigTest entity is an instance of ConfigTest.'); - // Test getOperations() method. - $uri = $entity->uri(); - $expected_operations = array( - 'edit' => array ( - 'title' => t('Edit'), - 'href' => $uri['path'], - 'options' => $uri['options'], - 'weight' => 10, - ), - 'disable' => array( - 'title' => t('Disable'), - 'href' => $uri['path'] . '/disable', - 'options' => $uri['options'], - 'weight' => 40, - ), - 'delete' => array ( - 'title' => t('Delete'), - 'href' => $uri['path'] . '/delete', - 'options' => $uri['options'], - 'weight' => 100, - ), - ); - - $actual_operations = $controller->getOperations($entity); - // Sort the operations to normalize link order. - uasort($actual_operations, 'drupal_sort_weight'); - $this->assertIdentical($expected_operations, $actual_operations); - // Test buildHeader() method. $expected_items = array( 'label' => 'Label', @@ -88,15 +60,12 @@ function testList() { $this->assertIdentical($expected_items, $actual_items, 'Return value from buildHeader matches expected.'); // Test buildRow() method. - $build_operations = $controller->buildOperations($entity); $expected_items = array( 'label' => 'Default', 'id' => 'dotted.default', - 'operations' => array( - 'data' => $build_operations, - ), ); $actual_items = $controller->buildRow($entity); + unset($actual_items['operations']); $this->assertIdentical($expected_items, $actual_items, 'Return value from buildRow matches expected.'); // Test sorting. $storage_controller = $controller->getStorageController(); @@ -120,36 +89,6 @@ function testList() { $entity->save(); $list = $controller->load(); $this->assertIdentical(array_keys($list), array('beta', 'dotted.default', 'alpha', 'omega')); - - // Test that config entities that do not support status, do not have - // enable/disable operations. - $controller = $this->container->get('entity.manager') - ->getListController('config_test_no_status'); - - $list = $controller->load(); - $entity = $list['default']; - - // Test getOperations() method. - $uri = $entity->uri(); - $expected_operations = array( - 'edit' => array( - 'title' => t('Edit'), - 'href' => $uri['path'], - 'options' => $uri['options'], - 'weight' => 10, - ), - 'delete' => array( - 'title' => t('Delete'), - 'href' => $uri['path'] . '/delete', - 'options' => $uri['options'], - 'weight' => 100, - ), - ); - - $actual_operations = $controller->getOperations($entity); - // Sort the operations to normalize link order. - uasort($actual_operations, 'drupal_sort_weight'); - $this->assertIdentical($expected_operations, $actual_operations); } /** 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 19ee07f..b207572 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 @@ -19,6 +19,7 @@ * id = "config_test", * label = @Translation("Test configuration"), * controllers = { + * "operations" = "Drupal\Core\Config\Entity\ConfigEntityOperationsProvider", * "storage" = "Drupal\config_test\ConfigTestStorageController", * "list" = "Drupal\config_test\ConfigTestListController", * "form" = { diff --git a/core/modules/contact/lib/Drupal/contact/Entity/Category.php b/core/modules/contact/lib/Drupal/contact/Entity/Category.php index e636713..b369906 100644 --- a/core/modules/contact/lib/Drupal/contact/Entity/Category.php +++ b/core/modules/contact/lib/Drupal/contact/Entity/Category.php @@ -20,6 +20,7 @@ * id = "contact_category", * label = @Translation("Contact category"), * controllers = { + * "operations" = "Drupal\Core\Config\Entity\ConfigEntityOperationsProvider", * "storage" = "Drupal\contact\CategoryStorageController", * "access" = "Drupal\contact\CategoryAccessController", * "list" = "Drupal\contact\CategoryListController", diff --git a/core/modules/entity/lib/Drupal/entity/Entity/EntityFormMode.php b/core/modules/entity/lib/Drupal/entity/Entity/EntityFormMode.php index 533321c..def662c 100644 --- a/core/modules/entity/lib/Drupal/entity/Entity/EntityFormMode.php +++ b/core/modules/entity/lib/Drupal/entity/Entity/EntityFormMode.php @@ -33,6 +33,7 @@ * id = "form_mode", * label = @Translation("Form mode"), * controllers = { + * "operations" = "Drupal\Core\Config\Entity\ConfigEntityOperationsProvider", * "list" = "Drupal\entity\EntityFormModeListController", * "form" = { * "add" = "Drupal\entity\Form\EntityFormModeAddForm", diff --git a/core/modules/entity/lib/Drupal/entity/Entity/EntityViewMode.php b/core/modules/entity/lib/Drupal/entity/Entity/EntityViewMode.php index 6107d4f..6b04148 100644 --- a/core/modules/entity/lib/Drupal/entity/Entity/EntityViewMode.php +++ b/core/modules/entity/lib/Drupal/entity/Entity/EntityViewMode.php @@ -34,6 +34,7 @@ * id = "view_mode", * label = @Translation("View mode"), * controllers = { + * "operations" = "Drupal\Core\Config\Entity\ConfigEntityOperationsProvider", * "list" = "Drupal\entity\EntityDisplayModeListController", * "form" = { * "add" = "Drupal\entity\Form\EntityDisplayModeAddForm", diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeListController.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeListController.php index 835c1c6..81227c8 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeListController.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeListController.php @@ -9,8 +9,10 @@ use Drupal\Core\Config\Entity\ConfigEntityListController; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityOperationsProviderInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Session\AccountInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -34,13 +36,17 @@ class EntityDisplayModeListController extends ConfigEntityListController { * An array of entity info for the entity type. * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage * The entity storage controller class. + * @param \Drupal\Core\Entity\EntityOperationsProviderInterface $operations + * The entity operations provider. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke hooks on. + * @param |Drupal\Core\Session\AccountInterface $current_user + * The current user. * @param array $entity_info_complete * The entity info for all entity types. */ - public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, array $entity_info_complete) { - parent::__construct($entity_type, $entity_info, $storage, $module_handler); + public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, EntityOperationsProviderInterface $operations, ModuleHandlerInterface $module_handler, AccountInterface $current_user, array $entity_info_complete) { + parent::__construct($entity_type, $entity_info, $storage, $operations, $module_handler, $current_user); $this->entityInfoComplete = $entity_info_complete; } @@ -54,7 +60,9 @@ public static function createInstance(ContainerInterface $container, $entity_typ $entity_type, $entity_info, $entity_manager->getStorageController($entity_type), + $entity_manager->getOperationsProvider($entity_type), $container->get('module_handler'), + $container->get('current_user'), $entity_manager->getDefinitions() ); } diff --git a/core/modules/field/lib/Drupal/field/Entity/Field.php b/core/modules/field/lib/Drupal/field/Entity/Field.php index 47003fb..ad194d6 100644 --- a/core/modules/field/lib/Drupal/field/Entity/Field.php +++ b/core/modules/field/lib/Drupal/field/Entity/Field.php @@ -23,6 +23,7 @@ * id = "field_entity", * label = @Translation("Field"), * controllers = { + * "operations" = "Drupal\Core\Config\Entity\ConfigEntityOperationsProvider", * "storage" = "Drupal\field\FieldStorageController" * }, * config_prefix = "field.field", diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module index dc0d38f..361f680 100644 --- a/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -179,6 +179,64 @@ function field_ui_permission() { } /** + * Implements hook_entity_operations(). + */ +function field_ui_entity_operations(EntityInterface $entity) { + $info = $entity->entityInfo(); + $operations = array(); + + // If the entity is fieldable, or if it is the bundle of a fieldable entity + // type, add field administration links. + if ($info['fieldable'] || !empty($info['bundle_of'])) { + $uri = $entity->uri(); + $operations['manage-fields'] = array( + 'title' => t('Manage fields'), + 'href' => $uri['path'] . '/fields', + 'options' => $uri['options'], + 'weight' => 15, + ); + $operations['manage-display'] = array( + 'title' => t('Manage display'), + 'href' => $uri['path'] . '/display', + 'options' => $uri['options'], + 'weight' => 25, + ); + } + + // If the entity is the bundle of a fieldable entity type, add additional + // field administration links. + if (!empty($info['bundle_of'])) { + $uri = $entity->uri(); + $operations['manage-form-display'] = array( + 'title' => t('Manage form display'), + 'href' => $uri['path'] . '/form-display', + 'options' => $uri['options'], + 'weight' => 20, + ); + } + + return $operations; +} + +/** + * Implements hook_entity_access(). + */ +function field_ui_entity_access(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account, $langcode) { + $info = $entity->entityInfo(); + $entity_type = isset($info['bundle_of']) ? $info['bundle_of'] : $entity->entityType(); + + if ($operation == 'manage-fields') { + return $account->hasPermission('administer ' . $entity_type . ' fields'); + } + if ($operation == 'manage-form-display') { + return $account->hasPermission('administer ' . $entity_type . ' form display'); + } + if ($operation == 'manage-display') { + return $account->hasPermission('administer ' . $entity_type . ' display'); + } +} + +/** * Menu loader callback: Loads a field instance based on field and bundle name. * * @param $field_name @@ -291,43 +349,6 @@ function field_ui_form_node_type_form_alter(&$form, $form_state) { } /** - * Implements hook_entity_operation_alter(). - */ -function field_ui_entity_operation_alter(array &$operations, EntityInterface $entity) { - $info = $entity->entityInfo(); - // Add manage fields and display links if this entity type is the bundle - // of another. - if (!empty($info['bundle_of'])) { - $bundle_of = $info['bundle_of']; - $uri = $entity->uri(); - if (user_access('administer '. $bundle_of . ' fields')) { - $operations['manage-fields'] = array( - 'title' => t('Manage fields'), - 'href' => $uri['path'] . '/fields', - 'options' => $uri['options'], - 'weight' => 15, - ); - } - if (user_access('administer '. $bundle_of . ' form display')) { - $operations['manage-form-display'] = array( - 'title' => t('Manage form display'), - 'href' => $uri['path'] . '/form-display', - 'options' => $uri['options'], - 'weight' => 20, - ); - } - if (user_access('administer '. $bundle_of . ' display')) { - $operations['manage-display'] = array( - 'title' => t('Manage display'), - 'href' => $uri['path'] . '/display', - 'options' => $uri['options'], - 'weight' => 25, - ); - } - } -} - -/** * Form submission handler for the 'Save and manage fields' button. * * @see field_ui_form_node_type_form_alter() diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldListController.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldListController.php index 0025379..5ea2ac5 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/FieldListController.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldListController.php @@ -12,6 +12,7 @@ use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Field\FieldTypePluginManager; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Session\AccountInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -58,13 +59,15 @@ class FieldListController extends ConfigEntityListController { * The entity manager. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke hooks on. + * @param |Drupal\Core\Session\AccountInterface $current_user + * The current user. * @param \Drupal\field\FieldInfo $field_info * The field info service. * @param \Drupal\Core\Field\FieldTypePluginManager $field_type_manager * The 'field type' plugin manager. */ - public function __construct($entity_type, array $entity_info, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, FieldTypePluginManager $field_type_manager) { - parent::__construct($entity_type, $entity_info, $entity_manager->getStorageController($entity_type), $module_handler); + public function __construct($entity_type, array $entity_info, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user, FieldTypePluginManager $field_type_manager) { + parent::__construct($entity_type, $entity_info, $entity_manager->getStorageController($entity_type), $entity_manager->getOperationsProvider($entity_type), $module_handler, $current_user); $this->entityManager = $entity_manager; $this->bundles = entity_get_bundles(); @@ -81,6 +84,7 @@ public static function createInstance(ContainerInterface $container, $entity_typ $entity_info, $container->get('entity.manager'), $container->get('module_handler'), + $container->get('current_user'), $container->get('plugin.manager.field.field_type') ); } diff --git a/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php b/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php index 6c4bf5b..a9823e6 100644 --- a/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php +++ b/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php @@ -21,6 +21,7 @@ * id = "filter_format", * label = @Translation("Text format"), * controllers = { + * "operations" = "Drupal\filter\FilterFormatOperationsProvider", * "form" = { * "add" = "Drupal\filter\FilterFormatAddFormController", * "edit" = "Drupal\filter\FilterFormatEditFormController", diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatAccessController.php b/core/modules/filter/lib/Drupal/filter/FilterFormatAccessController.php index a1edbd9..2d30711 100644 --- a/core/modules/filter/lib/Drupal/filter/FilterFormatAccessController.php +++ b/core/modules/filter/lib/Drupal/filter/FilterFormatAccessController.php @@ -30,6 +30,10 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A if ($operation == 'delete') { return FALSE; } + // The fallback format may not be disabled. + if ($operation == 'disable' && $entity->isFallbackFormat()) { + return FALSE; + } if ($operation != 'view' && $account->hasPermission('administer filters')) { return TRUE; diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php b/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php index cd94f86..ca980c5 100644 --- a/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php +++ b/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php @@ -12,8 +12,10 @@ use Drupal\Core\Config\Entity\DraggableListController; use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityOperationsProviderInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Session\AccountInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -42,13 +44,17 @@ class FilterFormatListController extends DraggableListController implements Enti * An array of entity info for the entity type. * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage * The entity storage controller class. + * @param \Drupal\Core\Entity\EntityOperationsProviderInterface $operations + * The entity operations provider. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke hooks on. + * @param |Drupal\Core\Session\AccountInterface $current_user + * The current user. * @param \Drupal\Core\Config\ConfigFactory $config_factory * The config factory. */ - public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, ConfigFactory $config_factory) { - parent::__construct($entity_type, $entity_info, $storage, $module_handler); + public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, EntityOperationsProviderInterface $operations, ModuleHandlerInterface $module_handler, AccountInterface $current_user, ConfigFactory $config_factory) { + parent::__construct($entity_type, $entity_info, $storage, $operations, $module_handler, $current_user); $this->configFactory = $config_factory; } @@ -61,7 +67,9 @@ public static function createInstance(ContainerInterface $container, $entity_typ $entity_type, $entity_info, $container->get('entity.manager')->getStorageController($entity_type), + $container->get('entity.manager')->getOperationsProvider($entity_type), $container->get('module_handler'), + $container->get('current_user'), $container->get('config.factory') ); } @@ -123,24 +131,6 @@ public function buildRow(EntityInterface $entity) { /** * {@inheritdoc} */ - public function getOperations(EntityInterface $entity) { - $operations = parent::getOperations($entity); - - if (isset($operations['edit'])) { - $operations['edit']['title'] = t('Configure'); - } - - // The fallback format may not be disabled. - if ($entity->isFallbackFormat()) { - unset($operations['disable']); - } - - return $operations; - } - - /** - * {@inheritdoc} - */ public function buildForm(array $form, array &$form_state) { $form = parent::buildForm($form, $form_state); $form['actions']['submit']['#value'] = t('Save changes'); diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatOperationsProvider.php b/core/modules/filter/lib/Drupal/filter/FilterFormatOperationsProvider.php new file mode 100644 index 0000000..208b9fc --- /dev/null +++ b/core/modules/filter/lib/Drupal/filter/FilterFormatOperationsProvider.php @@ -0,0 +1,27 @@ +urlGenerator = $url_generator; } @@ -55,7 +61,9 @@ public static function createInstance(ContainerInterface $container, $entity_typ $entity_type, $entity_info, $container->get('entity.manager')->getStorageController($entity_type), + $container->get('entity.manager')->getOperationsProvider($entity_type), $container->get('module_handler'), + $container->get('current_user'), $container->get('url_generator'), $container->get('string_translation') ); diff --git a/core/modules/language/lib/Drupal/language/Entity/Language.php b/core/modules/language/lib/Drupal/language/Entity/Language.php index d4c8e1b..b6c5e35 100644 --- a/core/modules/language/lib/Drupal/language/Entity/Language.php +++ b/core/modules/language/lib/Drupal/language/Entity/Language.php @@ -21,6 +21,7 @@ * id = "language_entity", * label = @Translation("Language"), * controllers = { + * "operations" = "Drupal\language\LanguageOperationsProvider", * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "list" = "Drupal\language\LanguageListController", * "access" = "Drupal\language\LanguageAccessController", diff --git a/core/modules/language/lib/Drupal/language/LanguageAccessController.php b/core/modules/language/lib/Drupal/language/LanguageAccessController.php index 2cc17d0..f49b64d 100644 --- a/core/modules/language/lib/Drupal/language/LanguageAccessController.php +++ b/core/modules/language/lib/Drupal/language/LanguageAccessController.php @@ -18,6 +18,11 @@ class LanguageAccessController extends EntityAccessController { * {@inheritdoc} */ public function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) { + // Deleting the site default language is not allowed. + if ($operation == 'delete' && $entity->id() == language_default()->id) { + return FALSE; + } + switch ($operation) { case 'update': case 'delete': diff --git a/core/modules/language/lib/Drupal/language/LanguageListController.php b/core/modules/language/lib/Drupal/language/LanguageListController.php index 35724b7..54b6855 100644 --- a/core/modules/language/lib/Drupal/language/LanguageListController.php +++ b/core/modules/language/lib/Drupal/language/LanguageListController.php @@ -41,31 +41,6 @@ public function getFormId() { /** * {@inheritdoc} */ - public function getOperations(EntityInterface $entity) { - $operations = parent::getOperations($entity); - $default = language_default(); - - // Edit and delete path for Languages entities have a different pattern - // than other config entities. - $path = 'admin/config/regional/language'; - if (isset($operations['edit'])) { - $operations['edit']['href'] = $path . '/edit/' . $entity->id(); - } - if (isset($operations['delete'])) { - $operations['delete']['href'] = $path . '/delete/' . $entity->id(); - } - - // Deleting the site default language is not allowed. - if ($entity->id() == $default->id) { - unset($operations['delete']); - } - - return $operations; - } - - /** - * {@inheritdoc} - */ public function buildHeader() { $header['label'] = t('Name'); return $header + parent::buildHeader(); diff --git a/core/modules/language/lib/Drupal/language/LanguageOperationsProvider.php b/core/modules/language/lib/Drupal/language/LanguageOperationsProvider.php new file mode 100644 index 0000000..6801373 --- /dev/null +++ b/core/modules/language/lib/Drupal/language/LanguageOperationsProvider.php @@ -0,0 +1,32 @@ +id(); + $operations['delete']['href'] = $path . '/delete/' . $entity->id(); + + return $operations; + } +} diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageListTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageListTest.php index 8b2190d..9472987 100644 --- a/core/modules/language/lib/Drupal/language/Tests/LanguageListTest.php +++ b/core/modules/language/lib/Drupal/language/Tests/LanguageListTest.php @@ -76,10 +76,10 @@ function testLanguageList() { // Ensure we can't delete the default language. $this->drupalGet('admin/config/regional/language/delete/' . $langcode); - $this->assertEqual($this->getUrl(), url('admin/config/regional/language', array('absolute' => TRUE)), 'Correct page redirection.'); - $this->assertText(t('The default language cannot be deleted.'), 'Failed to delete the default language.'); + $this->assertResponse('403'); // Ensure 'Edit' link works. + $this->drupalGet('admin/config/regional/language'); $this->clickLink(t('Edit')); $this->assertTitle(t('Edit language | Drupal'), 'Page title is "Edit language".'); // Edit a language. diff --git a/core/modules/menu/lib/Drupal/menu/MenuListController.php b/core/modules/menu/lib/Drupal/menu/MenuListController.php index 4c5a408..6b3da33 100644 --- a/core/modules/menu/lib/Drupal/menu/MenuListController.php +++ b/core/modules/menu/lib/Drupal/menu/MenuListController.php @@ -39,28 +39,6 @@ public function buildRow(EntityInterface $entity) { } /** - * {@inheritdoc} - */ - public function getOperations(EntityInterface $entity) { - $operations = parent::getOperations($entity); - $uri = $entity->uri(); - - if (isset($operations['edit'])) { - $operations['edit']['title'] = t('Edit menu'); - $operations['add'] = array( - 'title' => t('Add link'), - 'href' => $uri['path'] . '/add', - 'options' => $uri['options'], - 'weight' => 20, - ); - } - if (isset($operations['delete'])) { - $operations['delete']['title'] = t('Delete menu'); - } - return $operations; - } - - /** * Overrides \Drupal\Core\Entity\EntityListController::render(); */ public function render() { diff --git a/core/modules/menu/lib/Drupal/menu/MenuOperationsProvider.php b/core/modules/menu/lib/Drupal/menu/MenuOperationsProvider.php new file mode 100644 index 0000000..0daaf2d --- /dev/null +++ b/core/modules/menu/lib/Drupal/menu/MenuOperationsProvider.php @@ -0,0 +1,36 @@ +uri(); + + $operations['update']['title'] = t('Edit menu'); + $operations['delete']['title'] = t('Delete menu'); + $operations['add'] = array( + 'title' => t('Add link'), + 'href' => $uri['path'] . '/add', + 'options' => $uri['options'], + 'weight' => 20, + ); + + return $operations; + } +} diff --git a/core/modules/node/lib/Drupal/node/Entity/NodeType.php b/core/modules/node/lib/Drupal/node/Entity/NodeType.php index fb13664..0b77c8b 100644 --- a/core/modules/node/lib/Drupal/node/Entity/NodeType.php +++ b/core/modules/node/lib/Drupal/node/Entity/NodeType.php @@ -20,6 +20,7 @@ * id = "node_type", * label = @Translation("Content type"), * controllers = { + * "operations" = "Drupal\node\NodeTypeOperationsProvider", * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "access" = "Drupal\node\NodeTypeAccessController", * "form" = { diff --git a/core/modules/node/lib/Drupal/node/NodeTypeListController.php b/core/modules/node/lib/Drupal/node/NodeTypeListController.php index 0cb406f..5aa5fbc 100644 --- a/core/modules/node/lib/Drupal/node/NodeTypeListController.php +++ b/core/modules/node/lib/Drupal/node/NodeTypeListController.php @@ -8,6 +8,8 @@ use Drupal\Core\Config\Entity\ConfigEntityListController; use Drupal\Core\Entity\EntityControllerInterface; +use Drupal\Core\Entity\EntityOperationsProviderInterface; +use Drupal\Core\Session\AccountInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; @@ -37,13 +39,17 @@ class NodeTypeListController extends ConfigEntityListController implements Entit * An array of entity info for the entity type. * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage * The entity storage controller class. + * @param \Drupal\Core\Entity\EntityOperationsProviderInterface $operations + * The entity operations provider. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke hooks on. + * @param |Drupal\Core\Session\AccountInterface $current_user + * The current user. * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator * The url generator service. */ - public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, UrlGeneratorInterface $url_generator) { - parent::__construct($entity_type, $entity_info, $storage, $module_handler); + public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, EntityOperationsProviderInterface $operations, ModuleHandlerInterface $module_handler, AccountInterface $current_user, UrlGeneratorInterface $url_generator) { + parent::__construct($entity_type, $entity_info, $storage, $operations, $module_handler, $current_user); $this->urlGenerator = $url_generator; } /** @@ -54,7 +60,9 @@ public static function createInstance(ContainerInterface $container, $entity_typ $entity_type, $entity_info, $container->get('entity.manager')->getStorageController($entity_type), + $container->get('entity.manager')->getOperationsProvider($entity_type), $container->get('module_handler'), + $container->get('current_user'), $container->get('url_generator') ); } @@ -86,19 +94,6 @@ public function buildRow(EntityInterface $entity) { /** * {@inheritdoc} */ - public function getOperations(EntityInterface $entity) { - $operations = parent::getOperations($entity); - // Place the edit operation after the operations added by field_ui.module - // which have the weights 15, 20, 25. - if (isset($operations['edit'])) { - $operations['edit']['weight'] = 30; - } - return $operations; - } - - /** - * {@inheritdoc} - */ public function render() { $build = parent::render(); $build['#empty'] = t('No content types available. Add content type.', array( diff --git a/core/modules/node/lib/Drupal/node/NodeTypeOperationsProvider.php b/core/modules/node/lib/Drupal/node/NodeTypeOperationsProvider.php new file mode 100644 index 0000000..b290998 --- /dev/null +++ b/core/modules/node/lib/Drupal/node/NodeTypeOperationsProvider.php @@ -0,0 +1,29 @@ +uri(); - $operations['duplicate'] = array( - 'title' => t('Duplicate'), - 'href' => $uri['path'] . '/duplicate', - 'options' => $uri['options'], - 'weight' => 15, - ); - return $operations; - } - } diff --git a/core/modules/picture/lib/Drupal/picture/PictureMappingOperationsProvider.php b/core/modules/picture/lib/Drupal/picture/PictureMappingOperationsProvider.php new file mode 100644 index 0000000..ce2ea2e --- /dev/null +++ b/core/modules/picture/lib/Drupal/picture/PictureMappingOperationsProvider.php @@ -0,0 +1,33 @@ +uri(); + $operations['duplicate'] = array( + 'title' => t('Duplicate'), + 'href' => $uri['path'] . '/duplicate', + 'options' => $uri['options'], + 'weight' => 15, + ); + + return $operations; + } +} diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php b/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php index d826f70..2d0f033 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php @@ -20,6 +20,7 @@ * id = "shortcut_set", * label = @Translation("Shortcut set"), * controllers = { + * "operations" = "Drupal\shortcut\ShortcutSetOperationsProvider", * "storage" = "Drupal\shortcut\ShortcutSetStorageController", * "access" = "Drupal\shortcut\ShortcutSetAccessController", * "list" = "Drupal\shortcut\ShortcutSetListController", diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetListController.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetListController.php index 6215a87..ca66977 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetListController.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetListController.php @@ -24,25 +24,6 @@ public function buildHeader() { } /** - * {@inheritdoc} - */ - public function getOperations(EntityInterface $entity) { - $operations = parent::getOperations($entity); - $uri = $entity->uri(); - - if (isset($operations['edit'])) { - $operations['edit']['title'] = t('Edit menu'); - $operations['edit']['href'] = $uri['path'] . '/edit'; - } - - $operations['list'] = array( - 'title' => t('List links'), - 'href' => $uri['path'], - ); - return $operations; - } - - /** * Overrides \Drupal\Core\Entity\EntityListController::buildRow(). */ public function buildRow(EntityInterface $entity) { diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetOperationsProvider.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetOperationsProvider.php new file mode 100644 index 0000000..8df3e2e --- /dev/null +++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetOperationsProvider.php @@ -0,0 +1,33 @@ +uri(); + $operations['update']['title'] = t('Edit menu'); + $operations['update']['href'] = $uri['path'] . '/edit'; + $operations['list'] = array( + 'title' => t('List links'), + 'href' => $uri['path'], + ); + + return $operations; + } +} diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php index 05f9e57..d561d95 100644 --- a/core/modules/system/entity.api.php +++ b/core/modules/system/entity.api.php @@ -684,15 +684,54 @@ function hook_entity_field_info_alter(&$info, $entity_type) { } /** - * Alter entity operations. + * Declares operations for an entity. + * + * @see \Drupal\Core\Entity\EntityOperationsProvider * - * @param array $operations - * Operations array as returned by - * \Drupal\Core\Entity\EntityStorageControllerInterface::getOperations(). * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity on which the linked operations will be performed. + * + * @return array + * The structure is identical to that of the return value of + * \Drupal\Core\Entity\EntityOperationsProviderInterface::getOperations(). + */ +function hook_entity_operations(\Drupal\Core\Entity\EntityInterface $entity) { + $uri = $entity->uri(); + $operations['translate'] = array( + 'title' => t('Translate'), + 'href' => $uri['path'] . '/translate', + 'weight' => 50, + ); + + return $operations; +} + +/** + * Declares operations for an entity of a specific type. + * + * @see \Drupal\Core\Entity\EntityOperationsProvider + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * + * @return array + * The structure is identical to that of the return value of + * \Drupal\Core\Entity\EntityOperationsProviderInterface::getOperations(). */ -function hook_entity_operation_alter(array &$operations, \Drupal\Core\Entity\EntityInterface $entity) { +function hook_ENTITY_TYPE_operations(\Drupal\Core\Entity\EntityInterface $entity) { + return array(); +} + +/** + * Alters entity operations. + * + * @see \Drupal\Core\Entity\EntityOperationsProvider + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity on which the linked operations will be performed. + * @param array $operations + * Operations array as returned by + * \Drupal\Core\Entity\EntityStorageControllerInterface::getOperations(). + */ +function hook_entity_operations_alter(\Drupal\Core\Entity\EntityInterface $entity, array &$operations) { $uri = $entity->uri(); $operations['translate'] = array( 'title' => t('Translate'), @@ -702,6 +741,20 @@ function hook_entity_operation_alter(array &$operations, \Drupal\Core\Entity\Ent } /** + * Alters entity operations for an entity of a specific type. + * + * @see \Drupal\Core\Entity\EntityOperationsProvider + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity on which the linked operations will be performed. + * @param array $operations + * Operations array as returned by + * \Drupal\Core\Entity\EntityStorageControllerInterface::getOperations(). + */ +function hook_ENTITY_TYPE_operations_alter(\Drupal\Core\Entity\EntityInterface $entity, array &$operations) { +} + +/** * Control access to fields. * * This hook is invoked from diff --git a/core/modules/system/lib/Drupal/system/DateFormatListController.php b/core/modules/system/lib/Drupal/system/DateFormatListController.php index d22642b..d87f2a4 100644 --- a/core/modules/system/lib/Drupal/system/DateFormatListController.php +++ b/core/modules/system/lib/Drupal/system/DateFormatListController.php @@ -11,8 +11,10 @@ use Drupal\Core\Config\Entity\ConfigEntityListController; use Drupal\Core\Datetime\Date; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityOperationsProviderInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Session\AccountInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -36,13 +38,17 @@ class DateFormatListController extends ConfigEntityListController { * An array of entity info for the entity type. * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage * The entity storage controller class. + * @param \Drupal\Core\Entity\EntityOperationsProviderInterface $operations + * The entity operations provider. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke hooks on. + * @param |Drupal\Core\Session\AccountInterface $current_user + * The current user. * @param \Drupal\Core\Datetime\Date $date_service * The date service. */ - public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, Date $date_service) { - parent::__construct($entity_type, $entity_info, $storage, $module_handler); + public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, EntityOperationsProviderInterface $operations, ModuleHandlerInterface $module_handler, AccountInterface $current_user, Date $date_service) { + parent::__construct($entity_type, $entity_info, $storage, $operations, $module_handler, $current_user); $this->dateService = $date_service; } @@ -55,7 +61,9 @@ public static function createInstance(ContainerInterface $container, $entity_typ $entity_type, $entity_info, $container->get('entity.manager')->getStorageController($entity_type), + $container->get('entity.manager')->getOperationsProvider($entity_type), $container->get('module_handler'), + $container->get('current_user'), $container->get('date') ); } diff --git a/core/modules/system/lib/Drupal/system/Entity/Action.php b/core/modules/system/lib/Drupal/system/Entity/Action.php index 4962a92..da1e65e 100644 --- a/core/modules/system/lib/Drupal/system/Entity/Action.php +++ b/core/modules/system/lib/Drupal/system/Entity/Action.php @@ -22,6 +22,7 @@ * id = "action", * label = @Translation("Action"), * controllers = { + * "operations" = "Drupal\action\ActionOperationsProvider", * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * }, * admin_permission = "administer actions", diff --git a/core/modules/system/lib/Drupal/system/Entity/DateFormat.php b/core/modules/system/lib/Drupal/system/Entity/DateFormat.php index fb4c7d3..9516a99 100644 --- a/core/modules/system/lib/Drupal/system/Entity/DateFormat.php +++ b/core/modules/system/lib/Drupal/system/Entity/DateFormat.php @@ -21,6 +21,7 @@ * id = "date_format", * label = @Translation("Date format"), * controllers = { + * "operations" = "\Drupal\Core\Config\Entity\ConfigEntityOperationsProvider", * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "access" = "Drupal\system\DateFormatAccessController", * "list" = "Drupal\system\DateFormatListController", diff --git a/core/modules/system/lib/Drupal/system/Entity/Menu.php b/core/modules/system/lib/Drupal/system/Entity/Menu.php index 5f6d075..ac93af2 100644 --- a/core/modules/system/lib/Drupal/system/Entity/Menu.php +++ b/core/modules/system/lib/Drupal/system/Entity/Menu.php @@ -19,6 +19,7 @@ * id = "menu", * label = @Translation("Menu"), * controllers = { + * "operations" = "Drupal\menu\MenuOperationsProvider", * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "access" = "Drupal\system\MenuAccessController" * }, diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityOperationsTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityOperationsTest.php index 776021d..424b290 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityOperationsTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityOperationsTest.php @@ -40,11 +40,11 @@ public function setUp() { } /** - * Checks that hook_entity_operation_alter() can add an operation. + * Checks that hook_entity_operations() can add an operation. * - * @see entity_test_entity_operation_alter() + * @see entity_test_entity_operations() */ - public function testEntityOperationAlter() { + public function testEntityOperations() { // Check that role listing contain our test_operation operation. $this->drupalGet('admin/people/roles'); $roles = user_roles(); diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module index c8f868e..6a06ee5 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/core/modules/system/tests/modules/entity_test/entity_test.module @@ -455,15 +455,17 @@ function entity_test_entity_predelete(EntityInterface $entity) { } /** - * Implements hook_entity_operation_alter(). + * Implements hook_entity_operations(). */ -function entity_test_entity_operation_alter(array &$operations, EntityInterface $entity) { +function entity_test_entity_operations(EntityInterface $entity) { $uri = $entity->uri(); $operations['test_operation'] = array( 'title' => format_string('Test Operation: @label', array('@label' => $entity->label())), 'href' => $uri['path'] . '/test_operation', 'weight' => 50, ); + + return $operations; } /** diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php index fe6669b..b0a522b 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php @@ -20,6 +20,7 @@ * id = "taxonomy_vocabulary", * label = @Translation("Taxonomy vocabulary"), * controllers = { + * "operations" = "Drupal\taxonomy\VocabularyOperationsProvider", * "storage" = "Drupal\taxonomy\VocabularyStorageController", * "list" = "Drupal\taxonomy\VocabularyListController", * "form" = { diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyListController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyListController.php index ff93ede..eb0ed5f 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyListController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyListController.php @@ -30,35 +30,6 @@ public function getFormId() { /** * {@inheritdoc} */ - public function getOperations(EntityInterface $entity) { - $operations = parent::getOperations($entity); - $uri = $entity->uri(); - - if (isset($operations['edit'])) { - $operations['edit']['title'] = t('edit vocabulary'); - $operations['edit']['href'] = $uri['path'] . '/edit'; - } - - $operations['list'] = array( - 'title' => t('list terms'), - 'href' => $uri['path'], - 'options' => $uri['options'], - 'weight' => 0, - ); - $operations['add'] = array( - 'title' => t('add terms'), - 'href' => $uri['path'] . '/add', - 'options' => $uri['options'], - 'weight' => 10, - ); - unset($operations['delete']); - - return $operations; - } - - /** - * {@inheritdoc} - */ public function buildHeader() { $header['label'] = t('Vocabulary name'); return $header + parent::buildHeader(); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyOperationsProvider.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyOperationsProvider.php new file mode 100644 index 0000000..1080c26 --- /dev/null +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyOperationsProvider.php @@ -0,0 +1,43 @@ +uri(); + + $operations['update']['title'] = t('edit vocabulary'); + $operations['update']['href'] = $uri['path'] . '/edit'; + $operations['list'] = array( + 'title' => t('list terms'), + 'href' => $uri['path'], + 'options' => $uri['options'], + 'weight' => 0, + ); + $operations['add'] = array( + 'title' => t('add terms'), + 'href' => $uri['path'] . '/add', + 'options' => $uri['options'], + 'weight' => 10, + ); + unset($operations['delete']); + + return $operations; + } +} diff --git a/core/modules/user/lib/Drupal/user/Entity/Role.php b/core/modules/user/lib/Drupal/user/Entity/Role.php index d58a358..10f1996 100644 --- a/core/modules/user/lib/Drupal/user/Entity/Role.php +++ b/core/modules/user/lib/Drupal/user/Entity/Role.php @@ -18,6 +18,7 @@ * id = "user_role", * label = @Translation("Role"), * controllers = { + * "operations" = "Drupal\user\RoleOperationsProvider", * "storage" = "Drupal\user\RoleStorageController", * "access" = "Drupal\user\RoleAccessController", * "list" = "Drupal\user\RoleListController", diff --git a/core/modules/user/lib/Drupal/user/RoleListController.php b/core/modules/user/lib/Drupal/user/RoleListController.php index 4aa4f52..51e7f08 100644 --- a/core/modules/user/lib/Drupal/user/RoleListController.php +++ b/core/modules/user/lib/Drupal/user/RoleListController.php @@ -41,24 +41,6 @@ public function buildRow(EntityInterface $entity) { /** * {@inheritdoc} */ - public function getOperations(EntityInterface $entity) { - $operations = parent::getOperations($entity); - - $operations['permissions'] = array( - 'title' => t('Edit permissions'), - 'href' => 'admin/people/permissions/' . $entity->id(), - 'weight' => 20, - ); - // Built-in roles could not be deleted or disabled. - if (in_array($entity->id(), array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { - unset($operations['delete']); - } - return $operations; - } - - /** - * {@inheritdoc} - */ public function submitForm(array &$form, array &$form_state) { parent::submitForm($form, $form_state); diff --git a/core/modules/user/lib/Drupal/user/RoleOperationsProvider.php b/core/modules/user/lib/Drupal/user/RoleOperationsProvider.php new file mode 100644 index 0000000..804e2c2 --- /dev/null +++ b/core/modules/user/lib/Drupal/user/RoleOperationsProvider.php @@ -0,0 +1,31 @@ + t('Edit permissions'), + 'href' => 'admin/people/permissions/' . $entity->id(), + 'weight' => 20, + ); + + return $operations; + } +} diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php index ef88707..84ceecc 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php @@ -12,8 +12,10 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Config\Entity\ConfigEntityListController; use Drupal\Core\Entity\EntityControllerInterface; +use Drupal\Core\Entity\EntityOperationsProviderInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Session\AccountInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -35,9 +37,11 @@ public static function createInstance(ContainerInterface $container, $entity_typ return new static( $entity_type, $container->get('entity.manager')->getStorageController($entity_type), + $container->get('entity.manager')->getOperationsProvider($entity_type), $entity_info, $container->get('plugin.manager.views.display'), - $container->get('module_handler') + $container->get('module_handler'), + $container->get('current_user') ); } @@ -48,15 +52,19 @@ public static function createInstance(ContainerInterface $container, $entity_typ * The type of entity to be listed. * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage. * The entity storage controller class. + * @param \Drupal\Core\Entity\EntityOperationsProviderInterface $operations + * The entity operations provider. * @param array $entity_info * An array of entity info for this entity type. * @param \Drupal\Component\Plugin\PluginManagerInterface $display_manager * The views display plugin manager to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. + * @param |Drupal\Core\Session\AccountInterface $current_user + * The current user. */ - public function __construct($entity_type, EntityStorageControllerInterface $storage, $entity_info, PluginManagerInterface $display_manager, ModuleHandlerInterface $module_handler) { - parent::__construct($entity_type, $entity_info, $storage, $module_handler); + public function __construct($entity_type, EntityStorageControllerInterface $storage, EntityOperationsProviderInterface $operations, $entity_info, PluginManagerInterface $display_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user) { + parent::__construct($entity_type, $entity_info, $storage, $operations, $module_handler, $current_user); $this->displayManager = $display_manager; } @@ -140,31 +148,6 @@ public function buildHeader() { /** * {@inheritdoc} */ - public function getOperations(EntityInterface $entity) { - $operations = parent::getOperations($entity); - $uri = $entity->uri(); - - $operations['clone'] = array( - 'title' => $this->t('Clone'), - 'href' => $uri['path'] . '/clone', - 'options' => $uri['options'], - 'weight' => 15, - ); - - // Add AJAX functionality to enable/disable operations. - foreach (array('enable', 'disable') as $op) { - if (isset($operations[$op])) { - $operations[$op]['ajax'] = TRUE; - $operations[$op]['query']['token'] = drupal_get_token($op); - } - } - - return $operations; - } - - /** - * {@inheritdoc} - */ public function buildOperations(EntityInterface $entity) { $build = parent::buildOperations($entity); diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewOperationsProvider.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewOperationsProvider.php new file mode 100644 index 0000000..e6da725 --- /dev/null +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewOperationsProvider.php @@ -0,0 +1,45 @@ +uri(); + $operations['clone'] = array( + 'title' => $this->translationManager->translate('Clone'), + 'href' => $uri['path'] . '/clone', + 'options' => $uri['options'], + 'weight' => 15, + ); + // Add AJAX functionality to enable/disable operations. + foreach (array('enable', 'disable') as $operation) { + // @todo There is no generic access control for enable and disable + // operations yet. Once that is done, this if statement can be removed. + if (isset($operations[$operation])) { + $operations[$operation]['ajax'] = TRUE; + $operations[$operation]['query']['token'] = drupal_get_token($operation); + } + } + + return $operations; + } + + + +} 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 b30bb34..4dd1596 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 @@ -124,9 +124,21 @@ public function testBuildRowEntityList() { ->disableOriginalConstructor() ->getMock(); + $operations = $this->getMock('\Drupal\Core\Entity\EntityOperationsProviderInterface'); + $operations->expects($this->once()) + ->method('getOperations') + ->will($this->returnValue(array( + 'foo' => array( + 'href' => 'bar', + 'title' => 'Baz', + ), + ))); + + $current_user = $this->getMock('\Drupal\Core\Session\AccountInterface'); + // Setup a view list controller with a mocked buildOperations method, // because t() is called on there. - $view_list_controller = $this->getMock('Drupal\views_ui\ViewListController', array('buildOperations'), array('view', $storage_controller, $entity_info, $display_manager, $module_handler)); + $view_list_controller = $this->getMock('Drupal\views_ui\ViewListController', array('buildOperations'), array('view', $storage_controller, $operations, $entity_info, $display_manager, $module_handler, $current_user)); $view_list_controller->expects($this->any()) ->method('buildOperations') ->will($this->returnValue(array())); diff --git a/core/modules/views_ui/views_ui.module b/core/modules/views_ui/views_ui.module index 93742a4..b55650d 100644 --- a/core/modules/views_ui/views_ui.module +++ b/core/modules/views_ui/views_ui.module @@ -51,6 +51,7 @@ function views_ui_menu() { */ function views_ui_entity_info(&$entity_info) { $entity_info['view']['controllers'] += array( + 'operations' => 'Drupal\views_ui\ViewOperationsProvider', 'list' => 'Drupal\views_ui\ViewListController', 'form' => array( 'edit' => 'Drupal\views_ui\ViewEditFormController', diff --git a/core/tests/Drupal/Tests/Core/Entity/ConfigEntityOperationsProviderUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/ConfigEntityOperationsProviderUnitTest.php new file mode 100644 index 0000000..5dac4bf --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Entity/ConfigEntityOperationsProviderUnitTest.php @@ -0,0 +1,65 @@ + '', + 'group' => 'Configuration', + 'name' => '\Drupal\Core\Entity\EntityOperationsProvider', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + + $this->moduleHandler = $this->getMock('\Drupal\Core\Extension\ModuleHandlerInterface'); + $this->moduleHandler->expects($this->exactly(2)) + ->method('invokeAll') + ->will($this->returnValue(array())); + + $this->currentUser = $this->getMock('\Drupal\Core\Session\AccountInterface'); + + $this->translationManager = $this->getMockBuilder('\Drupal\Core\StringTranslation\TranslationManager') + ->disableOriginalConstructor() + ->getMock(); + + $this->entity = $this->getMock('\Drupal\Core\Config\Entity\ConfigEntityInterface'); + $this->entity->expects($this->any()) + ->method('access') + ->will($this->returnValue(TRUE)); + + $this->operationsProvider = new EntityOperationsProvider($this->moduleHandler, $this->translationManager); + } + + /** + * Tests getOperations(). + */ + public function testGetOperations() { + $operations = $this->operationsProvider->getOperations($this->entity, $this->currentUser); + $this->assertInternalType('array', $operations); + $this->assertArrayHasKey('update', $operations); + $this->assertInternalType('array', $operations['update']); + $this->assertArrayHasKey('delete', $operations); + $this->assertInternalType('array', $operations['delete']); + } +} diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityListControllerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityListControllerTest.php index c8b07d6..d5841a2 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityListControllerTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityListControllerTest.php @@ -74,11 +74,23 @@ protected function setUp() { ->disableOriginalConstructor() ->getMock(); + $operations = $this->getMock('\Drupal\Core\Entity\EntityOperationsProviderInterface'); + $operations->expects($this->once()) + ->method('getOperations') + ->will($this->returnValue(array( + 'foo' => array( + 'href' => 'bar', + 'title' => 'Baz', + ), + ))); + + $current_user = $this->getMock('\Drupal\Core\Session\AccountInterface'); + $module_handler = $this->getMockBuilder('Drupal\Core\Extension\ModuleHandler') ->disableOriginalConstructor() ->getMock(); - $this->entityListController = $this->getMock('Drupal\entity_test\EntityTestListController', array('buildOperations'), array('user_role', static::$entityInfo, $role_storage_controller, $module_handler)); + $this->entityListController = $this->getMock('Drupal\entity_test\EntityTestListController', array('buildOperations'), array('user_role', static::$entityInfo, $role_storage_controller, $operations, $module_handler, $current_user)); $this->entityListController->expects($this->any()) ->method('buildOperations')