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..58068d0 --- /dev/null +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityOperationsProvider.php @@ -0,0 +1,52 @@ +uri(); + $operations = parent::getDefaultOperations($entity); + if (isset($operations['update'])) { + // 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' => 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/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..cf336b7 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/EntityOperationsProvider.php @@ -0,0 +1,111 @@ +moduleHandler = $module_handler; + $this->translationManager = $translation_manager; + $this->accessController = $access_controller; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + return new static($container->get('module_handler'), $container->get('string_translation'), $container->get('entity.manager')->getAccessController($entity_type)); + } + + /** + * {@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..7fd40e8 --- /dev/null +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockOperationsProvider.php @@ -0,0 +1,33 @@ +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/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 @@ +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_ui/field_ui.module b/core/modules/field_ui/field_ui.module index dc0d38f..e580192 100644 --- a/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -179,6 +179,71 @@ function field_ui_permission() { } /** + * Implements hook_entity_operations(). + */ +function field_ui_entity_operations(EntityInterface $entity) { + $info = $entity->entityInfo(); + $operations = array(); + + if ($info['fieldable']) { + $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' => 20, + ); + } + + // Add manage fields and display links if this entity type is the bundle + // of another. + if (!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-form-display'] = array( + 'title' => t('Manage form display'), + 'href' => $uri['path'] . '/form-display', + 'options' => $uri['options'], + 'weight' => 20, + ); + $operations['manage-display'] = array( + 'title' => t('Manage display'), + 'href' => $uri['path'] . '/display', + 'options' => $uri['options'], + 'weight' => 25, + ); + } + + return $operations; +} + +/** + * Implements hook_entity_access(). + */ +function field_ui_entity_access(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account, $langcode) { + if ($operation == 'manage-fields') { + return $account->hasPermission('administer ' . $entity->entityType() . ' fields'); + } + if ($operation == 'manage-form-display') { + return $account->hasPermission('administer ' . $entity->entityType() . ' form display'); + } + if ($operation == 'manage-display') { + return $account->hasPermission('administer ' . $entity->entityType() . ' display'); + } +} + +/** * Menu loader callback: Loads a field instance based on field and bundle name. * * @param $field_name @@ -291,43 +356,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..6777521 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 ($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/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/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..74c6aac --- /dev/null +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewOperationsProvider.php @@ -0,0 +1,38 @@ +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) { + $operations[$op]['ajax'] = TRUE; + $operations[$op]['query']['token'] = drupal_get_token($op); + } + + 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/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')