diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutAccessController.php b/core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutAccessController.php similarity index 69% rename from core/modules/shortcut/lib/Drupal/shortcut/ShortcutAccessController.php rename to core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutAccessController.php index 4dd0aea..066beef 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutAccessController.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutAccessController.php @@ -2,15 +2,17 @@ /** * @file - * Contains \Drupal\shortcut\ShortcutAccessController. + * Contains \Drupal\shortcut\Access\ShortcutAccessController. */ -namespace Drupal\shortcut; +namespace Drupal\shortcut\Access; use Drupal\Core\Entity\EntityAccessController; use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Session\AccountInterface; +use Drupal\shortcut\ShortcutSetStorageController; +use Drupal\shortcut\ShortcutManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -26,6 +28,13 @@ class ShortcutAccessController extends EntityAccessController implements EntityC protected $shortcutSetStorage; /** + * Stores the shortcut Manager. + * + * @var \Drupal\shortcut\ShortcutManagerInterface + */ + protected $shortcutManager; + + /** * Constructs a ShortcutAccessController object. * * @param string $entity_type @@ -34,10 +43,13 @@ class ShortcutAccessController extends EntityAccessController implements EntityC * An array of entity info for the entity type. * @param \Drupal\shortcut\ShortcutSetStorageController $shortcut_set_storage * The shortcut_set storage controller. + * @param \Drupal\shortcut\ShortcutManagerInterface $shortcut_manager + * Injected ShortcutManager service. */ - public function __construct($entity_type, array $entity_info, ShortcutSetStorageController $shortcut_set_storage) { + public function __construct($entity_type, array $entity_info, ShortcutSetStorageController $shortcut_set_storage, ShortcutManagerInterface $shortcut_manager) { parent::__construct($entity_type, $entity_info); $this->shortcutSetStorage = $shortcut_set_storage; + $this->shortcutManager = $shortcut_manager; } /** @@ -47,7 +59,8 @@ public static function createInstance(ContainerInterface $container, $entity_typ return new static( $entity_type, $entity_info, - $container->get('entity.manager')->getStorageController('shortcut_set') + $container->get('entity.manager')->getStorageController('shortcut_set'), + $container->get('shortcut.manager') ); } @@ -56,7 +69,7 @@ public static function createInstance(ContainerInterface $container, $entity_typ */ protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) { if ($shortcut_set = $this->shortcutSetStorage->load($entity->bundle())) { - return shortcut_set_edit_access($shortcut_set, $account); + return $this->shortcutManager->shortcutSetEditAccess($shortcut_set, $account); } } @@ -65,7 +78,7 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A */ protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { if ($shortcut_set = $this->shortcutSetStorage->load($entity_bundle)) { - return shortcut_set_edit_access($shortcut_set, $account); + return $this->shortcutManager->shortcutSetEditAccess($shortcut_set, $account); } } diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetAccessController.php b/core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutSetAccessController.php similarity index 52% rename from core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetAccessController.php rename to core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutSetAccessController.php index c60d52a..24bdb5c 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetAccessController.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutSetAccessController.php @@ -2,19 +2,48 @@ /** * @file - * Contains \Drupal\shortcut\ShortcutSetAccessController. + * Contains \Drupal\shortcut\Access\ShortcutSetAccessController. */ -namespace Drupal\shortcut; +namespace Drupal\shortcut\Access; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityAccessController; use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Entity\EntityControllerInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\shortcut\ShortcutManagerInterface; /** * Defines the access controller for the shortcut entity type. */ -class ShortcutSetAccessController extends EntityAccessController { +class ShortcutSetAccessController extends EntityAccessController implements EntityControllerInterface { + + /** + * Stores the shortcut Manager. + * + * @var \Drupal\shortcut\ShortcutManagerInterface + */ + protected $shortcutManager; + + /** + * Constructs ShortcutSetAccessController object. + * + * @param \Drupal\shortcut\ShortcutManagerInterface $shortcut_manager + * Injected ShortcutManager service. + */ + function __construct(ShortcutManagerInterface $shortcut_manager) { + $this->shortcutManager = $shortcut_manager; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + return new static( + $container->get('shortcut.manager') + ); + } /** * {@inheritdoc} @@ -26,7 +55,7 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A return TRUE; } if ($account->hasPermission('customize shortcut links')) { - return $entity == shortcut_current_displayed_set($account); + return $entity == $this->shortcutManager->currentDisplayedSet($account); } return FALSE; break; diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutSetEditAccessCheck.php b/core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutSetEditAccessCheck.php index 283825a..ed3b272 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutSetEditAccessCheck.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutSetEditAccessCheck.php @@ -11,6 +11,7 @@ use Drupal\Core\Session\AccountInterface; use Symfony\Component\Routing\Route; use Symfony\Component\HttpFoundation\Request; +use Drupal\shortcut\ShortcutManagerInterface; /** * Provides an access check for shortcut link delete routes. @@ -18,6 +19,23 @@ class ShortcutSetEditAccessCheck implements StaticAccessCheckInterface { /** + * Stores the shortcut Manager. + * + * @var \Drupal\shortcut\ShortcutManagerInterface + */ + protected $shortcutManager; + + /** + * Constructs ShortcutSetEditAccessCheck object. + * + * @param \Drupal\shortcut\ShortcutManagerInterface $shortcut_manager + * Injected ShortcutManager service. + */ + function __construct(ShortcutManagerInterface $shortcut_manager) { + $this->shortcutManager = $shortcut_manager; + } + + /** * {@inheritdoc} */ public function appliesTo() { @@ -28,17 +46,8 @@ public function appliesTo() { * {@inheritdoc} */ public function access(Route $route, Request $request, AccountInterface $account) { - $account = \Drupal::currentUser(); $shortcut_set = $request->attributes->get('shortcut_set'); - // Sufficiently-privileged users can edit their currently displayed shortcut - // set, but not other sets. Shortcut administrators can edit any set. - if ($account->hasPermission('administer shortcuts')) { - return static::ALLOW; - } - if ($account->hasPermission('customize shortcut links')) { - return !isset($shortcut_set) || $shortcut_set == shortcut_current_displayed_set() ? static::ALLOW : static::DENY; - } - return static::DENY; + return $this->shortcutManager->shortcutSetEditAccess($shortcut_set, $account) ? static::ALLOW : static::DENY; } } diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutSetSwitchAccessCheck.php b/core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutSetSwitchAccessCheck.php index d39f630..a95d565 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutSetSwitchAccessCheck.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Access/ShortcutSetSwitchAccessCheck.php @@ -11,6 +11,7 @@ use Drupal\Core\Session\AccountInterface; use Symfony\Component\Routing\Route; use Symfony\Component\HttpFoundation\Request; +use Drupal\shortcut\ShortcutManagerInterface; /** * Provides an access check for shortcut link delete routes. @@ -18,6 +19,23 @@ class ShortcutSetSwitchAccessCheck implements StaticAccessCheckInterface { /** + * Stores the shortcut Manager. + * + * @var \Drupal\shortcut\ShortcutManagerInterface + */ + protected $shortcutManager; + + /** + * Constructs ShortcutSetSwitchAccessCheck object. + * + * @param \Drupal\shortcut\ShortcutManagerInterface $shortcut_manager + * Injected ShortcutManager service. + */ + function __construct(ShortcutManagerInterface $shortcut_manager) { + $this->shortcutManager = $shortcut_manager; + } + + /** * {@inheritdoc} */ public function appliesTo() { @@ -28,23 +46,8 @@ public function appliesTo() { * {@inheritdoc} */ public function access(Route $route, Request $request, AccountInterface $account) { - if ($account->hasPermission('administer shortcuts')) { - // Administrators can switch anyone's shortcut set. - return static::ALLOW; - } - - if (!$account->hasPermission('switch shortcut sets')) { - // The user has no permission to switch anyone's shortcut set. - return static::DENY; - } - $user = $request->attributes->get('account'); - if (!isset($user) || $user->id() == $account->id()) { - // Users with the 'switch shortcut sets' permission can switch their own - // shortcuts sets. - return static::ALLOW; - } - return static::DENY; + return $this->shortcutManager->shortcutSetSwitchAccess($account, $user) ? static::ALLOW : static::DENY; } } diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Controller/ShortcutSetController.php b/core/modules/shortcut/lib/Drupal/shortcut/Controller/ShortcutSetController.php index 2d90342..3e6f797 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Controller/ShortcutSetController.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Controller/ShortcutSetController.php @@ -8,9 +8,9 @@ namespace Drupal\shortcut\Controller; use Drupal\Core\Controller\ControllerBase; +use Drupal\shortcut\ShortcutManagerInterface; use Drupal\shortcut\ShortcutSetInterface; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -20,6 +20,32 @@ class ShortcutSetController extends ControllerBase { /** + * Stores the shortcut Manager. + * + * @var \Drupal\shortcut\ShortcutManagerInterface + */ + protected $shortcutManager; + + /** + * Constructs ShortcutSetController object. + * + * @param \Drupal\shortcut\ShortcutManagerInterface $shortcut_manager + * ShortcutManager service. + */ + function __construct(ShortcutManagerInterface $shortcut_manager) { + $this->shortcutManager = $shortcut_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('shortcut.manager') + ); + } + + /** * Creates a new link in the provided shortcut set. * * @param \Drupal\shortcut\ShortcutSetInterface $shortcut_set @@ -35,7 +61,7 @@ class ShortcutSetController extends ControllerBase { public function addShortcutLinkInline(ShortcutSetInterface $shortcut_set, Request $request) { $link = $request->query->get('link'); $name = $request->query->get('name'); - if (shortcut_valid_link($link)) { + if ($this->shortcutManager->validLink($link)) { $shortcut = $this->entityManager()->getStorageController('shortcut')->create(array( 'title' => $name, 'shortcut_set' => $shortcut_set->id(), diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Entity/Shortcut.php b/core/modules/shortcut/lib/Drupal/shortcut/Entity/Shortcut.php index 59f8287..8bf9444 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Entity/Shortcut.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Entity/Shortcut.php @@ -22,7 +22,7 @@ * module = "shortcut", * controllers = { * "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController", - * "access" = "Drupal\shortcut\ShortcutAccessController", + * "access" = "Drupal\shortcut\Access\ShortcutAccessController", * "form" = { * "default" = "Drupal\shortcut\ShortcutFormController", * "add" = "Drupal\shortcut\ShortcutFormController", diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php b/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php index ef2c480..4818d82 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php @@ -20,7 +20,7 @@ * label = @Translation("Shortcut set"), * controllers = { * "storage" = "Drupal\shortcut\ShortcutSetStorageController", - * "access" = "Drupal\shortcut\ShortcutSetAccessController", + * "access" = "Drupal\shortcut\Access\ShortcutSetAccessController", * "list" = "Drupal\shortcut\ShortcutSetListController", * "form" = { * "default" = "Drupal\shortcut\ShortcutSetFormController", @@ -73,7 +73,7 @@ public function postCreate(EntityStorageControllerInterface $storage_controller) // Generate menu-compatible set name. if (!$this->getOriginalId()) { // Save a new shortcut set with links copied from the user's default set. - $default_set = shortcut_default_set(); + $default_set = \Drupal::service('shortcut.manager')->defaultSet(); foreach ($default_set->getShortcuts() as $shortcut) { $shortcut = $shortcut->createDuplicate(); $shortcut->enforceIsNew(); diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Plugin/Block/ShortcutsBlock.php b/core/modules/shortcut/lib/Drupal/shortcut/Plugin/Block/ShortcutsBlock.php index 4a5efe2..339b221 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Plugin/Block/ShortcutsBlock.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Plugin/Block/ShortcutsBlock.php @@ -10,6 +10,9 @@ use Drupal\block\BlockBase; use Drupal\block\Annotation\Block; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\shortcut\ShortcutManagerInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides a 'Shortcut' block. @@ -20,14 +23,37 @@ * category = @Translation("Menus") * ) */ -class ShortcutsBlock extends BlockBase { +class ShortcutsBlock extends BlockBase implements ContainerFactoryPluginInterface { /** + * Stores the shortcut Manager. + * + * @var \Drupal\shortcut\ShortcutManagerInterface + */ + public $shortcutManager; + + /** + * @param \Drupal\shortcut\ShortcutManagerInterface $shortcut_manager + * Injected shortcut manager. + */ + function __construct(ShortcutManagerInterface $shortcut_manager) { + $this->shortcutManager = $shortcut_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) { + return new static( + $container->get('shortcut.manager') + ); + } + /** * {@inheritdoc} */ public function build() { return array( - shortcut_renderable_links(shortcut_current_displayed_set()), + $this->shortcutManager->renderableLinks($this->shortcutManager->currentDisplayedSet()), ); } diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutFormController.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutFormController.php index 7179886..bc64058 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutFormController.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutFormController.php @@ -43,6 +43,13 @@ class ShortcutFormController extends ContentEntityFormController { protected $formBuilder; /** + * Stores the shortcut Manager. + * + * @var \Drupal\shortcut\ShortcutManagerInterface + */ + protected $shortcutManager; + + /** * Constructs a new action form. * * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager @@ -53,12 +60,15 @@ class ShortcutFormController extends ContentEntityFormController { * The URL generator. * @param \Drupal\Core\Form\FormBuilderInterface $form_builder * The form builder. + * @param \Drupal\shortcut\ShortcutManagerInterface $shortcut_manager + * ShortcutManager service. */ - public function __construct(EntityManagerInterface $entity_manager, AliasManagerInterface $alias_manager, UrlGeneratorInterface $url_generator, FormBuilderInterface $form_builder) { + public function __construct(EntityManagerInterface $entity_manager, AliasManagerInterface $alias_manager, UrlGeneratorInterface $url_generator, FormBuilderInterface $form_builder, ShortcutManagerInterface $shortcut_manager) { $this->entityManager = $entity_manager; $this->aliasManager = $alias_manager; $this->urlGenerator = $url_generator; $this->formBuilder = $form_builder; + $this->shortcutManager = $shortcut_manager; } /** @@ -69,7 +79,8 @@ public static function create(ContainerInterface $container) { $container->get('entity.manager'), $container->get('path.alias_manager'), $container->get('url_generator'), - $container->get('form_builder') + $container->get('form_builder'), + $container->get('shortcut.manager') ); } @@ -139,7 +150,7 @@ public function buildEntity(array $form, array &$form_state) { * {@inheritdoc} */ public function validate(array $form, array &$form_state) { - if (!shortcut_valid_link($form_state['values']['path'])) { + if (!$this->shortcutManager->validLink($form_state['values']['path'])) { $this->formBuilder->setErrorByName('path', $form_state, $this->t('The shortcut must correspond to a valid path on the site.')); } diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutManager.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutManager.php new file mode 100644 index 0000000..b8b983e --- /dev/null +++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutManager.php @@ -0,0 +1,265 @@ +entityManager = $entity_manager; + $this->aliasManager = $alias_manager; + $this->routeProvider = $route_provider; + $this->moduleHandler = $module_handler; + $this->shortcutSetStorageController = $entity_manager->getStorageController('shortcut_set'); + } + + /** + * {@inheritdoc} + */ + public function currentDisplayedSet(AccountInterface $account = NULL) { + $shortcut_sets = &drupal_static('Drupal\shortcut\ShortcutManager::currentDisplayedSet', array()); + if (!isset($account)) { + $account = \Drupal::currentUser(); + } + // Try to return a shortcut set from the static cache. + if (isset($shortcut_sets[$account->id()])) { + return $shortcut_sets[$account->id()]; + } + // If none was found, try to find a shortcut set that is explicitly assigned + // to this user. + $shortcut_set_name = $this->shortcutSetStorageController->getAssignedToUser($account); + if ($shortcut_set_name) { + $shortcut_set = $this->shortcutSetStorageController->load($shortcut_set_name); + } + // Otherwise, use the default set. + else { + $shortcut_set = $this->defaultSet($account); + } + + $shortcut_sets[$account->id()] = $shortcut_set; + return $shortcut_set; + } + + /** + * {@inheritdoc} + */ + public function shortcutSetTitleExists($title) { + // Get all the shortcut sets with the specified label. + $sets = $this->shortcutSetStorageController->loadByProperties(array( + 'label' => $title, + )); + return !empty($sets); + } + + /** + * {@inheritdoc} + */ + public function validLink($path) { + // Do not use URL aliases. + $normal_path = $this->aliasManager->getSystemPath($path); + if ($path != $normal_path) { + $path = $normal_path; + } + + // An empty path is valid too and will be converted to . + return (!Url::isExternal($path) && ($this->routeProvider->getRoutesByPattern('/' . $path)->count() > 0 || menu_get_item($path))) || empty($path) || $path == ''; + } + + /** + * {@inheritdoc} + */ + public function adminAddLink($shortcut_link, ShortcutSetInterface &$shortcut_set) { + // Normalize the path in case it is an alias. + $shortcut_link['link_path'] = $this->aliasManager->getSystemPath($shortcut_link['link_path']); + if (empty($shortcut_link['link_path'])) { + $shortcut_link['link_path'] = ''; + } + $menu_link = $this->entityManager->getStorageController('menu_link')->create($shortcut_link); + $menu_link->save(); + + // Add the link to the end of the list. + $shortcut_set->links[$menu_link->uuid()] = $menu_link; + $this->shortcutSetResetLinkWeights($shortcut_set); + } + + /** + * {@inheritdoc} + */ + public function renderableLinks(ShortcutSetInterface $shortcut_set = NULL) { + $shortcut_links = array(); + + if (!isset($shortcut_set)) { + $shortcut_set = $this->currentDisplayedSet(); + } + + $shortcuts = $this->entityManager->getStorageController('shortcut')->loadByProperties(array('shortcut_set' => $shortcut_set->id())); + foreach ($shortcuts as $shortcut) { + $links[] = array( + 'title' => $shortcut->label(), + 'href' => $shortcut->path->value, + ); + } + + if (!empty($links)) { + $shortcut_links = array( + '#theme' => 'links__toolbar_shortcuts', + '#links' => $links, + '#attributes' => array( + 'class' => array('menu'), + ), + ); + } + + return $shortcut_links; + } + + /** + * {@inheritdoc} + */ + public function shortcutSetEditAccess(ShortcutSetInterface $shortcut_set = NULL, AccountInterface $user = NULL) { + $user = $user ?: \Drupal::currentUser(); + // Sufficiently-privileged users can edit their currently displayed shortcut + // set, but not other sets. Shortcut administrators can edit any set. + if ($user->hasPermission('administer shortcuts')) { + return TRUE; + } + if ($user->hasPermission('customize shortcut links')) { + return !isset($shortcut_set) || $shortcut_set == $this->currentDisplayedSet(); + } + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function shortcutSetSwitchAccess(AccountInterface $account = NULL, AccountInterface $user = NULL) { + $account = $account ?: \Drupal::currentUser(); + if ($account->hasPermission('administer shortcuts')) { + // Administrators can switch anyone's shortcut set. + return TRUE; + } + + if (!$account->hasPermission('switch shortcut sets')) { + // The user has no permission to switch anyone's shortcut set. + return FALSE; + } + + if (!isset($user) || $user->id() == $account->id()) { + // Users with the 'switch shortcut sets' permission can switch their own + // shortcuts sets. + return TRUE; + } + + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function defaultSet(AccountInterface $account = NULL) { + if (!isset($account)) { + $account = \Drupal::currentUser(); + } + + // Allow modules to return a default shortcut set name. Since we can only + // have one, we allow the last module which returns a valid result to take + // precedence. If no module returns a valid set, fall back on the site-wide + // default, which is the lowest-numbered shortcut set. + $suggestions = array_reverse($this->moduleHandler->invokeAll('shortcut_default_set', array($account))); + $suggestions[] = 'default'; + foreach ($suggestions as $name) { + if ($shortcut_set = $this->shortcutSetStorageController->load($name)) { + break; + } + } + + return $shortcut_set; + } + + /** + * This is an OO wrapper for menu_tree since this function has no OO variant. + * This wrapper is introduced with the intention to be able to mock it at + * testing time. + * + * Renders a menu tree based on the current path. + * + * The tree is expanded based on the current path and dynamic paths are also + * changed according to the defined to_arg functions (for example the 'My + * account' link is changed from user/% to a link with the current user's + * uid). + * + * @param $menu_name + * The name of the menu. + * + * @return array + * A structured array representing the specified menu on the current page, + * to be rendered by drupal_render(). + * + * @see menu_tree() + * @see ShortcutManager::renderableLinks() + */ + protected function menuTree($menu_name) { + return menu_tree($menu_name); + } + +} diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutManagerInterface.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutManagerInterface.php new file mode 100644 index 0000000..31c8233 --- /dev/null +++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutManagerInterface.php @@ -0,0 +1,129 @@ +shortcutManager = $shortcut_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('shortcut.manager') + ); + } /** * Overrides \Drupal\Core\Entity\EntityFormController::form(). @@ -64,8 +92,8 @@ public function validate(array $form, array &$form_state) { parent::validate($form, $form_state); $entity = $this->entity; // Check to prevent a duplicate title. - if ($form_state['values']['label'] != $entity->label() && shortcut_set_title_exists($form_state['values']['label'])) { - $this->setFormError('label', $form_state, $this->t('The shortcut set %name already exists. Choose another name.', array('%name' => $form_state['values']['label']))); + if ($form_state['values']['label'] != $entity->label() && $this->shortcutManager->shortcutSetTitleExists($form_state['values']['label'])) { + $this->setFormError('label', $form_state, t('The shortcut set %name already exists. Choose another name.', array('%name' => $form_state['values']['label']))); } } diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetStorageController.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetStorageController.php index 76f9582..bb44aa1 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetStorageController.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetStorageController.php @@ -33,7 +33,7 @@ public function assignUser(ShortcutSetInterface $shortcut_set, $account) { ->key(array('uid' => $account->id())) ->fields(array('set_name' => $shortcut_set->id())) ->execute(); - drupal_static_reset('shortcut_current_displayed_set'); + drupal_static_reset('Drupal\shortcut\ShortcutManager::currentDisplayedSet'); } /** diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php index 832ca64..79a8f37 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php @@ -60,7 +60,7 @@ public function testShortcutLinkAdd() { ); $this->drupalPostForm('admin/config/user-interface/shortcut/manage/' . $set->id() . '/add-link', $form_data, t('Save')); $this->assertResponse(200); - $saved_set = shortcut_set_load($set->id()); + $saved_set = entity_load('shortcut_set', $set->id()); $paths = $this->getShortcutInformation($saved_set, 'path'); $this->assertTrue(in_array($this->container->get('path.alias_manager')->getSystemPath($test['path']), $paths), 'Shortcut created: ' . $test['path']); $this->assertLink($title, 0, 'Shortcut link found on the page.'); @@ -94,7 +94,7 @@ public function testShortcutLinkRename() { $shortcuts = $set->getShortcuts(); $shortcut = reset($shortcuts); $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $shortcut->id(), array('title' => $new_link_name, 'path' => $shortcut->path->value), t('Save')); - $saved_set = shortcut_set_load($set->id()); + $saved_set = entity_load('shortcut_set', $set->id()); $titles = $this->getShortcutInformation($saved_set, 'title'); $this->assertTrue(in_array($new_link_name, $titles), 'Shortcut renamed: ' . $new_link_name); $this->assertLink($new_link_name, 0, 'Renamed shortcut link appears on the page.'); @@ -112,7 +112,7 @@ public function testShortcutLinkChangePath() { $shortcuts = $set->getShortcuts(); $shortcut = reset($shortcuts); $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $shortcut->id(), array('title' => $shortcut->title->value, 'path' => $new_link_path), t('Save')); - $saved_set = shortcut_set_load($set->id()); + $saved_set = entity_load('shortcut_set', $set->id()); $paths = $this->getShortcutInformation($saved_set, 'path'); $this->assertTrue(in_array($new_link_path, $paths), 'Shortcut path changed: ' . $new_link_path); $this->assertLinkByHref($new_link_path, 0, 'Shortcut with new path appears on the page.'); @@ -140,7 +140,7 @@ public function testShortcutLinkDelete() { $shortcuts = $set->getShortcuts(); $shortcut = reset($shortcuts); $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $shortcut->id() . '/delete', array(), 'Delete'); - $saved_set = shortcut_set_load($set->id()); + $saved_set = entity_load('shortcut_set', $set->id()); $ids = $this->getShortcutInformation($saved_set, 'id'); $this->assertFalse(in_array($shortcut->id(), $ids), 'Successfully deleted a shortcut.'); diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutSetsTest.php b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutSetsTest.php index 06493ec..27ba3ef 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutSetsTest.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutSetsTest.php @@ -47,7 +47,7 @@ function testShortcutSetSwitchOwn() { // set. $this->drupalPostForm('user/' . $this->admin_user->id() . '/shortcuts', array('set' => $new_set->id()), t('Change set')); $this->assertResponse(200); - $current_set = shortcut_current_displayed_set($this->admin_user); + $current_set = \Drupal::service('shortcut.manager')->currentDisplayedSet($this->admin_user); $this->assertTrue($new_set->id() == $current_set->id(), 'Successfully switched own shortcut set.'); } @@ -58,7 +58,7 @@ function testShortcutSetAssign() { $new_set = $this->generateShortcutSet($this->randomName()); shortcut_set_assign_user($new_set, $this->shortcut_user); - $current_set = shortcut_current_displayed_set($this->shortcut_user); + $current_set = \Drupal::service('shortcut.manager')->currentDisplayedSet($this->shortcut_user); $this->assertTrue($new_set->id() == $current_set->id(), "Successfully switched another user's shortcut set."); } @@ -72,7 +72,7 @@ function testShortcutSetSwitchCreate() { 'label' => $this->randomString(), ); $this->drupalPostForm('user/' . $this->admin_user->id() . '/shortcuts', $edit, t('Change set')); - $current_set = shortcut_current_displayed_set($this->admin_user); + $current_set = \Drupal::service('shortcut.manager')->currentDisplayedSet($this->admin_user); $this->assertNotEqual($current_set->id(), $this->set->id(), 'A shortcut set can be switched to at the same time as it is created.'); $this->assertEqual($current_set->label(), $edit['label'], 'The new set is correctly assigned to the user.'); } @@ -84,7 +84,7 @@ function testShortcutSetSwitchNoSetName() { $edit = array('set' => 'new'); $this->drupalPostForm('user/' . $this->admin_user->id() . '/shortcuts', $edit, t('Change set')); $this->assertText(t('The new set label is required.')); - $current_set = shortcut_current_displayed_set($this->admin_user); + $current_set = \Drupal::service('shortcut.manager')->currentDisplayedSet($this->admin_user); $this->assertEqual($current_set->id(), $this->set->id(), 'Attempting to switch to a new shortcut set without providing a set name does not succeed.'); } @@ -98,7 +98,7 @@ function testShortcutSetRename() { $this->drupalGet('admin/config/user-interface/shortcut'); $this->clickLink(t('Edit shortcut set')); $this->drupalPostForm(NULL, array('label' => $new_label), t('Save')); - $set = shortcut_set_load($set->id()); + $set = entity_load('shortcut_set', $set->id()); $this->assertTrue($set->label() == $new_label, 'Shortcut set has been successfully renamed.'); } @@ -110,7 +110,7 @@ function testShortcutSetRenameAlreadyExists() { $existing_label = $this->set->label(); $this->drupalPostForm('admin/config/user-interface/shortcut/manage/' . $set->id() . '/edit', array('label' => $existing_label), t('Save')); $this->assertRaw(t('The shortcut set %name already exists. Choose another name.', array('%name' => $existing_label))); - $set = shortcut_set_load($set->id()); + $set = entity_load('shortcut_set', $set->id()); $this->assertNotEqual($set->label(), $existing_label, format_string('The shortcut set %title cannot be renamed to %new-title because a shortcut set with that title already exists.', array('%title' => $set->label(), '%new-title' => $existing_label))); } @@ -122,8 +122,8 @@ function testShortcutSetUnassign() { shortcut_set_assign_user($new_set, $this->shortcut_user); shortcut_set_unassign_user($this->shortcut_user); - $current_set = shortcut_current_displayed_set($this->shortcut_user); - $default_set = shortcut_default_set($this->shortcut_user); + $current_set = \Drupal::service('shortcut.manager')->currentDisplayedSet($this->shortcut_user); + $default_set = \Drupal::service('shortcut.manager')->defaultSet($this->shortcut_user); $this->assertTrue($current_set->id() == $default_set->id(), "Successfully unassigned another user's shortcut set."); } diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutTestBase.php b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutTestBase.php index 64e5370..962890c 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutTestBase.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutTestBase.php @@ -79,7 +79,7 @@ function setUp() { // Log in as admin and grab the default shortcut set. $this->drupalLogin($this->admin_user); - $this->set = shortcut_set_load('default'); + $this->set = entity_load('shortcut_set', 'default'); shortcut_set_assign_user($this->set, $this->admin_user); } diff --git a/core/modules/shortcut/shortcut.admin.inc b/core/modules/shortcut/shortcut.admin.inc index 876c9f8..9ca5c02 100644 --- a/core/modules/shortcut/shortcut.admin.inc +++ b/core/modules/shortcut/shortcut.admin.inc @@ -34,7 +34,7 @@ function shortcut_set_switch($form, &$form_state, $account = NULL) { // Prepare the list of shortcut sets. $sets = entity_load_multiple('shortcut_set'); - $current_set = shortcut_current_displayed_set($account); + $current_set = \Drupal::service('shortcut.manager')->currentDisplayedSet($account); $options = array(); foreach ($sets as $name => $set) { @@ -86,7 +86,7 @@ function shortcut_set_switch($form, &$form_state, $account = NULL) { ); if ($user->id() != $account->id()) { - $default_set = shortcut_default_set($account); + $default_set = \Drupal::service('shortcut.manager')->defaultSet($account); $form['new']['#description'] = t('The new set is created by copying items from the %default set.', array('%default' => $default_set->label())); } @@ -120,7 +120,7 @@ function shortcut_set_switch_validate($form, &$form_state) { form_set_error('new', $form_state, t('The new set label is required.')); } // Check to prevent a duplicate title. - if (shortcut_set_title_exists($form_state['values']['label'])) { + if (\Drupal::service('shortcut.manager')->shortcutSetTitleExists($form_state['values']['label'])) { form_set_error('label', $form_state, t('The shortcut set %name already exists. Choose another name.', array('%name' => $form_state['values']['label']))); } } @@ -135,7 +135,7 @@ function shortcut_set_switch_submit($form, &$form_state) { if ($form_state['values']['set'] == 'new') { // Save a new shortcut set with links copied from the user's default set. - $default_set = shortcut_default_set($account); + $default_set = \Drupal::service('shortcut.manager')->defaultSet($account); $set = entity_create('shortcut_set', array( 'id' => $form_state['values']['id'], 'label' => $form_state['values']['label'], @@ -163,7 +163,7 @@ function shortcut_set_switch_submit($form, &$form_state) { } else { // Switch to a different shortcut set. - $set = shortcut_set_load($form_state['values']['set']); + $set = entity_load('shortcut_set', $form_state['values']['set']); $replacements = array( '%user' => $account->getUsername(), '%set_name' => $set->label(), diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index 8c7c869..8f1748a 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -5,9 +5,7 @@ * Allows users to manage customizable lists of shortcut links. */ -use Drupal\Core\Routing\UrlMatcher; use Drupal\shortcut\ShortcutSetInterface; -use Symfony\Component\HttpFoundation\Request; /** * Implements hook_help(). @@ -103,21 +101,14 @@ function shortcut_admin_paths() { * (optional) The shortcut set to be edited. If not set, the current user's * shortcut set will be used. * + * @deprecated Use \Drupal\shortcut\ShortcutManager::shortcutSetEditAccess() + * * @return bool * TRUE if the current user has access to edit the shortcut set, FALSE * otherwise. */ function shortcut_set_edit_access(ShortcutSetInterface $shortcut_set = NULL) { - $account = \Drupal::currentUser(); - // Sufficiently-privileged users can edit their currently displayed shortcut - // set, but not other sets. Shortcut administrators can edit any set. - if ($account->hasPermission('administer shortcuts')) { - return TRUE; - } - if ($account->hasPermission('customize shortcut links')) { - return !isset($shortcut_set) || $shortcut_set == shortcut_current_displayed_set(); - } - return FALSE; + return \Drupal::service('shortcut.manager')->shortcutSetEditAccess($shortcut_set); } /** @@ -128,37 +119,21 @@ function shortcut_set_edit_access(ShortcutSetInterface $shortcut_set = NULL) { * permissions will be checked for switching the logged-in user's own * shortcut set. * + * @deprecated Use \Drupal\shortcut\ShortcutManager::shortcutSetSwitchAccess() + * * @return bool * TRUE if the current user has access to switch the shortcut set of the * provided account, FALSE otherwise. */ function shortcut_set_switch_access($account = NULL) { - $user = \Drupal::currentUser(); - - if ($user->hasPermission('administer shortcuts')) { - // Administrators can switch anyone's shortcut set. - return TRUE; - } - - if (!$user->hasPermission('switch shortcut sets')) { - // The user has no permission to switch anyone's shortcut set. - return FALSE; - } - - if (!isset($account) || $user->id() == $account->id()) { - // Users with the 'switch shortcut sets' permission can switch their own - // shortcuts sets. - return TRUE; - } - - return FALSE; + return \Drupal::service('shortcut.manager')->shortcutSetSwitchAccess(NULL, $account); } /** * Loads the data for a shortcut set. * * @param string $id - * The machine-name of the shortcut set to load. + * The machinename of the shortcut set to load. * * @return \Drupal\shortcut\ShortcutSetInterface|null * If the shortcut set exists, an object containing the following properties: @@ -210,36 +185,15 @@ function shortcut_set_unassign_user($account) { * (optional) The user account whose shortcuts will be returned. Defaults to * the currently logged-in user. * + * @deprecated Use \Drupal\shortcut\ShortcutManager::currentDisplayedSet() + * * @return * An object representing the shortcut set that should be displayed to the * current user. If the user does not have an explicit shortcut set defined, * the default set is returned. */ function shortcut_current_displayed_set($account = NULL) { - $shortcut_sets = &drupal_static(__FUNCTION__, array()); - $user = \Drupal::currentUser(); - if (!isset($account)) { - $account = $user; - } - // Try to return a shortcut set from the static cache. - if (isset($shortcut_sets[$account->id()])) { - return $shortcut_sets[$account->id()]; - } - // If none was found, try to find a shortcut set that is explicitly assigned - // to this user. - $shortcut_set_name = \Drupal::entityManager() - ->getStorageController('shortcut_set') - ->getAssignedToUser($account); - if ($shortcut_set_name) { - $shortcut_set = shortcut_set_load($shortcut_set_name); - } - // Otherwise, use the default set. - else { - $shortcut_set = shortcut_default_set($account); - } - - $shortcut_sets[$account->id()] = $shortcut_set; - return $shortcut_set; + return \Drupal::service('shortcut.manager')->currentDisplayedSet($account); } /** @@ -250,28 +204,13 @@ function shortcut_current_displayed_set($account = NULL) { * If not provided, the function will return the currently logged-in user's * default shortcut set. * - * @return + * @deprecated Use \Drupal\shortcut\ShortcutManager::defaultSet() + * + * @return \Drupal\shortcut\ShortcutSetInterface * An object representing the default shortcut set. */ function shortcut_default_set($account = NULL) { - $user = \Drupal::currentUser(); - if (!isset($account)) { - $account = $user; - } - - // Allow modules to return a default shortcut set name. Since we can only - // have one, we allow the last module which returns a valid result to take - // precedence. If no module returns a valid set, fall back on the site-wide - // default, which is the lowest-numbered shortcut set. - $suggestions = array_reverse(\Drupal::moduleHandler()->invokeAll('shortcut_default_set', array($account))); - $suggestions[] = 'default'; - foreach ($suggestions as $name) { - if ($shortcut_set = shortcut_set_load($name)) { - break; - } - } - - return $shortcut_set; + return \Drupal::service('shortcut.manager')->defaultSet($account); } /** @@ -280,17 +219,13 @@ function shortcut_default_set($account = NULL) { * @param $title * Human-readable name of the shortcut set to check. * - * @return + * @deprecated Use \Drupal\shortcut\ShortcutManager::shortcutSetTitleExists() + * + * @return bool * TRUE if a shortcut set with that title exists; FALSE otherwise. */ function shortcut_set_title_exists($title) { - $sets = entity_load_multiple('shortcut_set'); - foreach ($sets as $set) { - if ($set->label == $title) { - return TRUE; - } - } - return FALSE; + return \Drupal::service('shortcut.manager')->shortcutSetTitleExists($title); } /** @@ -299,6 +234,8 @@ function shortcut_set_title_exists($title) { * @param string $path * The path to the link. * + * @deprecated Use \Drupal\shortcut\ShortcutManager::validLink() + * * @return bool * TRUE if the shortcut link is valid, FALSE otherwise. Valid links are ones * that correspond to actual paths on the site. @@ -306,14 +243,7 @@ function shortcut_set_title_exists($title) { * @see menu_edit_item_validate() */ function shortcut_valid_link($path) { - // Do not use URL aliases. - $normal_path = \Drupal::service('path.alias_manager')->getSystemPath($path); - if ($path != $normal_path) { - $path = $normal_path; - } - - // An empty path is valid too and will be converted to . - return (!url_is_external($path) && (\Drupal::service('router.route_provider')->getRoutesByPattern('/' . $path)->count() > 0 || menu_get_item($path))) || empty($path) || $path == ''; + return \Drupal::service('shortcut.manager')->validLink($path); } /** @@ -323,37 +253,15 @@ function shortcut_valid_link($path) { * (optional) An object representing the set whose links will be displayed. * If not provided, the user's current set will be displayed. * + * @deprecated Use \Drupal\shortcut\ShortcutManager::renderableLinks() + * * @return \Drupal\shortcut\ShortcutInterface[] * An array of shortcut links, in the format returned by the menu system. * * @see menu_tree() */ function shortcut_renderable_links($shortcut_set = NULL) { - $shortcut_links = array(); - - if (!isset($shortcut_set)) { - $shortcut_set = shortcut_current_displayed_set(); - } - - $shortcuts = \Drupal::entityManager()->getStorageController('shortcut')->loadByProperties(array('shortcut_set' => $shortcut_set->id())); - foreach ($shortcuts as $shortcut) { - $links[] = array( - 'title' => $shortcut->label(), - 'href' => $shortcut->path->value, - ); - } - - if (!empty($links)) { - $shortcut_links = array( - '#theme' => 'links__toolbar_shortcuts', - '#links' => $links, - '#attributes' => array( - 'class' => array('menu'), - ), - ); - } - - return $shortcut_links; + return \Drupal::service('shortcut.manager')->renderableLinks($shortcut_set); } /** @@ -373,7 +281,7 @@ function shortcut_preprocess_page(&$variables) { // shortcuts and if the page's actual content is being shown (for example, // we do not want to display it on "access denied" or "page not found" // pages). - if (shortcut_set_edit_access() && ($item = menu_get_item()) && $item['access']) { + if (\Drupal::service('shortcut.manager')->shortcutSetEditAccess() && ($item = menu_get_item()) && $item['access']) { $link = current_path(); if (!($route_info = \Drupal::service('router.matcher.final_matcher')->findRouteNameParameters($link))) { // Bail out early if we couldn't find a matching route. @@ -386,7 +294,7 @@ function shortcut_preprocess_page(&$variables) { ); $query += drupal_get_destination(); - $shortcut_set = shortcut_current_displayed_set(); + $shortcut_set = \Drupal::service('shortcut.manager')->currentDisplayedSet(); // Check if $link is already a shortcut and set $link_mode accordingly. $shortcuts = \Drupal::entityManager()->getStorageController('shortcut')->loadByProperties(array('shortcut_set' => $shortcut_set->id())); @@ -399,13 +307,13 @@ function shortcut_preprocess_page(&$variables) { $link_mode = isset($shortcut_id) ? "remove" : "add"; if ($link_mode == "add") { - $link_text = shortcut_set_switch_access() ? t('Add to %shortcut_set shortcuts', array('%shortcut_set' => $shortcut_set->label())) : t('Add to shortcuts'); + $link_text = \Drupal::service('shortcut.manager')->shortcutSetSwitchAccess() ? t('Add to %shortcut_set shortcuts', array('%shortcut_set' => $shortcut_set->label())) : t('Add to shortcuts'); $route_name = 'shortcut.link_add_inline'; $route_parameters = array('shortcut_set' => $shortcut_set->id()); } else { $query['id'] = $shortcut_id; - $link_text = shortcut_set_switch_access() ? t('Remove from %shortcut_set shortcuts', array('%shortcut_set' => $shortcut_set->label())) : t('Remove from shortcuts'); + $link_text = \Drupal::service('shortcut.manager')->shortcutSetSwitchAccess() ? t('Remove from %shortcut_set shortcuts', array('%shortcut_set' => $shortcut_set->label())) : t('Remove from shortcuts'); $route_name = 'shortcut.link_delete'; $route_parameters = array('shortcut' => $shortcut_id); } @@ -434,10 +342,10 @@ function shortcut_preprocess_page(&$variables) { */ function shortcut_toolbar() { $items = array(); - $links = shortcut_renderable_links(); - $shortcut_set = shortcut_current_displayed_set(); + $links = \Drupal::service('shortcut.manager')->renderableLinks(); + $shortcut_set = \Drupal::service('shortcut.manager')->currentDisplayedSet(); $configure_link = NULL; - if (shortcut_set_edit_access($shortcut_set)) { + if (\Drupal::service('shortcut.manager')->shortcutSetEditAccess($shortcut_set)) { $configure_link = array( '#type' => 'link', '#title' => t('Edit shortcuts'), diff --git a/core/modules/shortcut/shortcut.services.yml b/core/modules/shortcut/shortcut.services.yml index 3a04d99..ec223de 100644 --- a/core/modules/shortcut/shortcut.services.yml +++ b/core/modules/shortcut/shortcut.services.yml @@ -1,10 +1,16 @@ services: + shortcut.manager: + class: Drupal\shortcut\ShortcutManager + arguments: ['@entity.manager', '@path.alias_manager', '@router.route_provider', '@module_handler'] + access_check.shortcut.shortcut_set_edit: class: Drupal\shortcut\Access\ShortcutSetEditAccessCheck + arguments: ['@shortcut.manager'] tags: - { name: access_check } access_check.shortcut.shortcut_set_switch: class: Drupal\shortcut\Access\ShortcutSetSwitchAccessCheck + arguments: ['@shortcut.manager'] tags: - { name: access_check }