diff -u b/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php --- b/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -286,12 +286,7 @@ } /** - * Gets an entity type's operations controller. - * - * @param string $entity_type - * The entity type for this operations controller. - * - * @return \Drupal\Core\Entity\EntityOperationsProviderInterface. + * {@inheritdoc} */ public function getOperationsProvider($entity_type) { return $this->getController($entity_type, 'operations'); diff -u b/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module --- b/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -92,6 +92,64 @@ } /** + * 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 @@ -179,64 +237,6 @@ } /** - * 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 @@ -262,43 +262,6 @@ } /** - * 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() @@ -349,6 +312,43 @@ } /** + * 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 -u b/core/modules/views_ui/views_ui.module b/core/modules/views_ui/views_ui.module --- b/core/modules/views_ui/views_ui.module +++ b/core/modules/views_ui/views_ui.module @@ -40,13 +40,13 @@ */ 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', */ 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', only in patch2: unchanged: --- a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php @@ -272,4 +272,14 @@ public function getBundleInfo($entity_type); */ public function getTranslationFromContext(EntityInterface $entity, $langcode = NULL, $context = array()); + /** + * 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); + } only in patch2: unchanged: --- a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlockType.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlockType.php @@ -20,6 +20,7 @@ * id = "custom_block_type", * label = @Translation("Custom block type"), * controllers = { + * "operations" = "Drupal\Core\Config\Entity\ConfigEntityOperationsProvider", * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "form" = { * "default" = "Drupal\custom_block\CustomBlockTypeFormController", only in patch2: unchanged: --- a/core/modules/config_translation/config_translation.module +++ b/core/modules/config_translation/config_translation.module @@ -7,6 +7,7 @@ use Drupal\config_translation\Plugin\Derivative\ConfigTranslationLocalTasks; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Session\AccountInterface; use Symfony\Component\Routing\Exception\RouteNotFoundException; /** @@ -137,18 +138,28 @@ function config_translation_config_translation_info(&$info) { } /** - * Implements hook_entity_operation_alter(). + * Implements hook_entity_operations(). */ -function config_translation_entity_operation_alter(array &$operations, EntityInterface $entity) { - if (\Drupal::currentUser()->hasPermission('translate configuration')) { - $uri = $entity->uri(); - $operations['translate'] = array( - 'title' => t('Translate'), - 'href' => $uri['path'] . '/translate', - 'options' => $uri['options'], - 'weight' => 50, - ); +function config_translation_entity_operations(EntityInterface $entity) { + $uri = $entity->uri(); + $operations['translate'] = array( + 'title' => t('Translate'), + 'href' => $uri['path'] . '/translate', + 'options' => $uri['options'], + 'weight' => 50, + ); + + return $operations; +} + +/** + * Implements hook_entity_access(). + */ +function config_translation_entity_access(EntityInterface $entity, $operation, AccountInterface $account, $langcode) { + if ($operation == 'translate') { + return $account->hasPermission('translate configuration'); } + return $entity::DENY; } /** only in patch2: unchanged: --- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationBlockListController.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationBlockListController.php @@ -9,8 +9,10 @@ use Drupal\Component\Utility\String; 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; /** * Defines the config translation controller for blocks. @@ -27,8 +29,8 @@ class ConfigTranslationBlockListController extends ConfigTranslationEntityListCo /** * {@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); $this->themes = list_themes(); } only in patch2: unchanged: --- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListController.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListController.php @@ -69,7 +69,17 @@ public function render() { public function buildRow(EntityInterface $entity) { $row['label']['data'] = $this->getLabel($entity); $row['label']['class'] = 'table-filter-text-source'; - return $row + parent::buildRow($entity); + $row['operations']['data'] = array( + '#type' => 'operations', + '#links' => $this->operations->getOperations($entity, $this->currentUser), + ); + foreach (array_keys($row['operations']['data']['#links']) as $operation) { + if ($operation != 'translate') { + unset($row['operations']['data']['#links'][$operation]); + } + } + + return $row; } /** only in patch2: unchanged: --- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationFieldInstanceListController.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationFieldInstanceListController.php @@ -11,8 +11,10 @@ use Drupal\Component\Utility\Unicode; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManager; +use Drupal\Core\Entity\EntityOperationsProviderInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Session\AccountInterface; use Drupal\field\Field; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -69,7 +71,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('entity.manager'), $definition ); @@ -84,15 +88,19 @@ 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. * @param \Drupal\Core\Entity\EntityManager $entity_manager * The entity manager. * @param $definition * The plugin definition of the config translation mapper. */ - public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, EntityManager $entity_manager, array $definition) { - 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, EntityManager $entity_manager, array $definition) { + parent::__construct($entity_type, $entity_info, $storage, $operations, $module_handler, $current_user); $this->entityManager = $entity_manager; $this->baseEntityType = $definition['base_entity_type']; $this->baseEntityInfo = $this->entityManager->getDefinition($this->baseEntityType); only in patch2: unchanged: --- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationListController.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationListController.php @@ -19,6 +19,15 @@ class ConfigTranslationListController extends ControllerBase implements ContainerInjectionInterface { /** + * The service container. + * + * The container should only be passed on to factory methods of other classes. + * + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ + protected $container; + + /** * Definition of the config mapper. * * @var array @@ -35,12 +44,15 @@ class ConfigTranslationListController extends ControllerBase implements Containe /** * Constructs a new ConfigTranslationListController object. * + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container + * The service container. * @param \Drupal\config_translation\ConfigMapperManagerInterface $mapper_manager * The config mapper manager. * @param $config_translation_mapper * The config mapper id. */ - public function __construct(ConfigMapperManagerInterface $mapper_manager, $config_translation_mapper) { + public function __construct(ContainerInterface $container, ConfigMapperManagerInterface $mapper_manager, $config_translation_mapper) { + $this->container = $container; $this->mapperDefinition = $mapper_manager->getDefinition($config_translation_mapper); $this->mapper = $mapper_manager->createInstance($config_translation_mapper, $this->mapperDefinition); } @@ -50,6 +62,7 @@ public function __construct(ConfigMapperManagerInterface $mapper_manager, $confi */ public static function create(ContainerInterface $container) { return new static( + $container, $container->get('plugin.manager.config_translation.mapper'), $container->get('request')->attributes->get('_raw_variables')->get('config_translation_mapper') ); @@ -75,8 +88,12 @@ public function listing() { // node_type and block, fallback to the generic configuration translation // list controller. $class = $this->mapperDefinition['list_controller']; - /** @var \Drupal\config_translation\Controller\ConfigTranslationEntityListControllerInterface $controller */ - $controller = new $class($entity_type, $this->entityManager()->getDefinition($entity_type), $this->entityManager()->getStorageController($entity_type), $this->moduleHandler(), $this->entityManager(), $this->mapperDefinition); + if (in_array('Drupal\Core\Entity\EntityControllerInterface', class_implements($class))) { + $controller = $class::createInstance($this->container, $entity_type, $this->entityManager()->getDefinition($entity_type)); + } + else { + $controller = new $class($entity_type, $this->getStorageController($entity_type)); + } $build = $controller->render(); $build['#title'] = $this->mapper->getTypeLabel(); return $build; only in patch2: unchanged: --- a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php @@ -8,8 +8,9 @@ namespace Drupal\field_ui; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Entity\EntityOperationsProviderInterface; use Drupal\Core\Field\FieldTypePluginManager; -use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Session\AccountInterface; use Drupal\field_ui\OverviewBase; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\field\Entity\Field; @@ -20,18 +21,18 @@ class FieldOverview extends OverviewBase { /** - * The field type manager. + * The current user. * - * @var \Drupal\Core\Field\FieldTypePluginManager + * @var \Drupal\Core\Session\AccountInterface */ - protected $fieldTypeManager; + protected $currentUser; /** - * The module handler service. + * The field type manager. * - * @var \Drupal\Core\Extension\ModuleHandlerInterface + * @var \Drupal\Core\Field\FieldTypePluginManager */ - protected $moduleHandler; + protected $fieldTypeManager; /** * Constructs a new FieldOverview. @@ -40,13 +41,12 @@ class FieldOverview extends OverviewBase { * The entity manager. * @param \Drupal\Core\Field\FieldTypePluginManager $field_type_manager * The field type manager - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler to invoke hooks on. + * @param \Drupal\Core\Session\AccountInterface $current_user */ - public function __construct(EntityManagerInterface $entity_manager, FieldTypePluginManager $field_type_manager, ModuleHandlerInterface $module_handler) { + public function __construct(EntityManagerInterface $entity_manager, FieldTypePluginManager $field_type_manager, AccountInterface $current_user) { parent::__construct($entity_manager); + $this->currentUser = $current_user; $this->fieldTypeManager = $field_type_manager; - $this->moduleHandler = $module_handler; } /** @@ -56,7 +56,7 @@ public static function create(ContainerInterface $container) { return new static( $container->get('entity.manager'), $container->get('plugin.manager.field.field_type'), - $container->get('module_handler') + $container->get('current_user') ); } @@ -155,10 +155,10 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, 'attributes' => array('title' => $this->t('Delete instance.')), ); // Allow altering the operations on this entity listing. - $this->moduleHandler->alter('entity_operation', $links, $instance); +// $this->moduleHandler->alter('entity_operation', $links, $instance); $table[$name]['operations']['data'] = array( '#type' => 'operations', - '#links' => $links, + '#links' => $this->entityManager->getOperationsProvider($entity_type)->getOperations($instance, $this->currentUser), ); if (!empty($field->locked)) { only in patch2: unchanged: --- a/core/modules/node/lib/Drupal/node/Entity/Node.php +++ b/core/modules/node/lib/Drupal/node/Entity/Node.php @@ -21,6 +21,7 @@ * label = @Translation("Content"), * bundle_label = @Translation("Content type"), * controllers = { + * "operations" = "\Drupal\Core\Entity\EntityOperationsProvider", * "storage" = "Drupal\node\NodeStorageController", * "view_builder" = "Drupal\node\NodeViewBuilder", * "access" = "Drupal\node\NodeAccessController",