commit 42f1843e16da81974304a154cc78c2e20043f45d Author: Bart Feenstra Date: Thu Nov 7 17:37:38 2013 +0100 baz 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/ConfigEntityOperationsProvider.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityOperationsProvider.php index 58068d0..e3ad4d6 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityOperationsProvider.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityOperationsProvider.php @@ -21,17 +21,16 @@ class ConfigEntityOperationsProvider extends EntityOperationsProvider { protected function getDefaultOperations(EntityInterface $entity) { $uri = $entity->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']; - } + + // 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'), + 'title' => $this->translationManager->translate('Enable'), 'href' => $uri['path'] . '/enable', 'options' => $uri['options'], 'weight' => -10, @@ -39,7 +38,7 @@ protected function getDefaultOperations(EntityInterface $entity) { } else { $operations['disable'] = array( - 'title' => t('Disable'), + 'title' => $this->translationManager->translate('Disable'), 'href' => $uri['path'] . '/disable', 'options' => $uri['options'], 'weight' => 40, diff --git a/core/lib/Drupal/Core/Entity/EntityOperationsProvider.php b/core/lib/Drupal/Core/Entity/EntityOperationsProvider.php index cf336b7..4b1c148 100644 --- a/core/lib/Drupal/Core/Entity/EntityOperationsProvider.php +++ b/core/lib/Drupal/Core/Entity/EntityOperationsProvider.php @@ -18,13 +18,6 @@ class EntityOperationsProvider implements EntityOperationsProviderInterface, EntityControllerInterface { /** - * The entity type's access controller. - * - * @var \Drupal\Core\Entity\EntityAccessControllerInterface - */ - protected $accessController; - - /** * The module handler. * * @var \Drupal\Core\Extension\ModuleHandlerInterface @@ -45,17 +38,16 @@ class EntityOperationsProvider implements EntityOperationsProviderInterface, Ent * @param \Drupal\Core\StringTranslation\TranslationManager $translation_manager * @param \Drupal\Core\Entity\EntityAccessControllerInterface $access_controller */ - public function __construct(ModuleHandlerInterface $module_handler, TranslationManager $translation_manager, EntityAccessControllerInterface $access_controller) { + public function __construct(ModuleHandlerInterface $module_handler, TranslationManager $translation_manager) { $this->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)); + return new static($container->get('module_handler'), $container->get('string_translation')); } /** @@ -78,6 +70,7 @@ public function getOperations(EntityInterface $entity, AccountInterface $account } } // @todo Sort operations by weight and human-readable label. + 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 index 7fd40e8..974cda3 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockOperationsProvider.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockOperationsProvider.php @@ -21,11 +21,9 @@ class CustomBlockOperationsProvider extends EntityOperationsProvider { protected function getDefaultOperations(EntityInterface $entity) { $operations = parent::getDefaultOperations($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'; - } + $uri = $entity->uri(); + $operations['update']['href'] = $uri['path']; + $operations['update']['query']['destination'] = 'admin/structure/block/custom-blocks'; return $operations; } diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityListTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityListTest.php index b26e7f2..d286c7d 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityListTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityListTest.php @@ -50,34 +50,6 @@ function testList() { $this->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/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/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 e580192..361f680 100644 --- a/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -185,7 +185,9 @@ function field_ui_entity_operations(EntityInterface $entity) { $info = $entity->entityInfo(); $operations = array(); - if ($info['fieldable']) { + // 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'), @@ -197,32 +199,20 @@ function field_ui_entity_operations(EntityInterface $entity) { 'title' => t('Manage display'), 'href' => $uri['path'] . '/display', 'options' => $uri['options'], - 'weight' => 20, + 'weight' => 25, ); } - // Add manage fields and display links if this entity type is the bundle - // of another. + // 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-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; @@ -232,14 +222,17 @@ function field_ui_entity_operations(EntityInterface $entity) { * 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->entityType() . ' fields'); + return $account->hasPermission('administer ' . $entity_type . ' fields'); } if ($operation == 'manage-form-display') { - return $account->hasPermission('administer ' . $entity->entityType() . ' form display'); + return $account->hasPermission('administer ' . $entity_type . ' form display'); } if ($operation == 'manage-display') { - return $account->hasPermission('administer ' . $entity->entityType() . ' display'); + return $account->hasPermission('administer ' . $entity_type . ' display'); } } diff --git a/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php b/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php index a8d0e21..0c8621f 100644 --- a/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php +++ b/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php @@ -25,6 +25,7 @@ * id = "image_style", * label = @Translation("Image style"), * controllers = { + * "operations" = "Drupal\Core\Config\Entity\ConfigEntityOperationsProvider", * "form" = { * "add" = "Drupal\image\Form\ImageStyleAddForm", * "edit" = "Drupal\image\Form\ImageStyleEditForm", diff --git a/core/modules/language/lib/Drupal/language/LanguageAccessController.php b/core/modules/language/lib/Drupal/language/LanguageAccessController.php index 6777521..f49b64d 100644 --- a/core/modules/language/lib/Drupal/language/LanguageAccessController.php +++ b/core/modules/language/lib/Drupal/language/LanguageAccessController.php @@ -19,7 +19,7 @@ class LanguageAccessController extends EntityAccessController { */ public function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) { // Deleting the site default language is not allowed. - if ($entity->id() == language_default()->id) { + if ($operation == 'delete' && $entity->id() == language_default()->id) { return FALSE; } 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/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/views_ui/lib/Drupal/views_ui/ViewOperationsProvider.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewOperationsProvider.php index 74c6aac..e6da725 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewOperationsProvider.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewOperationsProvider.php @@ -22,17 +22,24 @@ protected function getDefaultOperations(EntityInterface $entity) { $operations = parent::getDefaultOperations($entity); $uri = $entity->uri(); $operations['clone'] = array( - 'title' => $this->t('Clone'), + '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 $op) { - $operations[$op]['ajax'] = TRUE; - $operations[$op]['query']['token'] = drupal_get_token($op); + 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/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']); + } +}