diff --git a/core/modules/shortcut/shortcut.admin.inc b/core/modules/shortcut/shortcut.admin.inc deleted file mode 100644 index 56e5e03..0000000 --- a/core/modules/shortcut/shortcut.admin.inc +++ /dev/null @@ -1,177 +0,0 @@ - $set) { - $options[$name] = String::checkPlain($set->label()); - } - - // Only administrators can add shortcut sets. - $add_access = $user->hasPermission('administer shortcuts'); - if ($add_access) { - $options['new'] = t('New set'); - } - - if (count($options) > 1) { - $form['account'] = array( - '#type' => 'value', - '#value' => $account, - ); - - $form['set'] = array( - '#type' => 'radios', - '#title' => $user->id() == $account->id() ? t('Choose a set of shortcuts to use') : t('Choose a set of shortcuts for this user'), - '#options' => $options, - '#default_value' => $current_set->id(), - ); - - $form['label'] = array( - '#type' => 'textfield', - '#title' => t('Label'), - '#title_display' => 'invisible', - '#description' => t('The new set is created by copying items from your default shortcut set.'), - '#access' => $add_access, - ); - $form['id'] = array( - '#type' => 'machine_name', - '#machine_name' => array( - 'exists' => '\Drupal\shortcut\Entity\ShortcutSet::load', - 'source' => array('label'), - 'replace_pattern' => '[^a-z0-9-]+', - 'replace' => '-', - ), - // This id could be used for menu name. - '#maxlength' => 23, - '#states' => array( - 'required' => array( - ':input[name="set"]' => array('value' => 'new'), - ), - ), - '#required' => FALSE, - ); - - if ($user->id() != $account->id()) { - $default_set = shortcut_default_set($account); - $form['new']['#description'] = t('The new set is created by copying items from the %default set.', array('%default' => $default_set->label())); - } - - $form['#attached'] = array( - 'library' => array('shortcut/drupal.shortcut.admin'), - ); - - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => t('Change set'), - ); - } - else { - // There is only 1 option, so output a message in the $form array. - $form['info'] = array( - '#markup' => '

' . t('You are currently using the %set-name shortcut set.', array('%set-name' => $current_set->label())) . '

', - ); - } - - return $form; -} - -/** - * Validation handler for shortcut_set_switch(). - */ -function shortcut_set_switch_validate($form, &$form_state) { - if ($form_state['values']['set'] == 'new') { - // Check to prevent creating a shortcut set with an empty title. - if (trim($form_state['values']['label']) == '') { - form_set_error('label', $form_state, t('The new set label is required.')); - } - // Check to prevent a duplicate title. - if (shortcut_set_title_exists($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']))); - } - } -} - -/** - * Submit handler for shortcut_set_switch(). - */ -function shortcut_set_switch_submit($form, &$form_state) { - $user = \Drupal::currentUser(); - $account = $form_state['values']['account']; - - if ($form_state['values']['set'] == 'new') { - // Save a new shortcut set with links copied from the user's default set. - $set = ShortcutSet::create(array( - 'id' => $form_state['values']['id'], - 'label' => $form_state['values']['label'], - )); - $set->save(); - $replacements = array( - '%user' => $account->getUsername(), - '%set_name' => $set->label(), - '@switch-url' => url(current_path()), - ); - if ($account->id() == $user->id()) { - // Only administrators can create new shortcut sets, so we know they have - // access to switch back. - drupal_set_message(t('You are now using the new %set_name shortcut set. You can edit it from this page or switch back to a different one.', $replacements)); - } - else { - drupal_set_message(t('%user is now using a new shortcut set called %set_name. You can edit it from this page.', $replacements)); - } - $form_state['redirect_route'] = array( - 'route_name' => 'shortcut.set_customize', - 'route_parameters' => array( - 'shortcut_set' => $set->id(), - ), - ); - } - else { - // Switch to a different shortcut set. - $set = ShortcutSet::load($form_state['values']['set']); - $replacements = array( - '%user' => $account->getUsername(), - '%set_name' => $set->label(), - ); - drupal_set_message($account->id() == $user->id() ? t('You are now using the %set_name shortcut set.', $replacements) : t('%user is now using the %set_name shortcut set.', $replacements)); - } - - // Assign the shortcut set to the provided user account. - shortcut_set_assign_user($set, $account); -} diff --git a/core/modules/shortcut/shortcut.local_tasks.yml b/core/modules/shortcut/shortcut.local_tasks.yml index 486d584..f391583 100644 --- a/core/modules/shortcut/shortcut.local_tasks.yml +++ b/core/modules/shortcut/shortcut.local_tasks.yml @@ -1,5 +1,5 @@ -shortcut.overview: - route_name: shortcut.overview +shortcut.set_switch: + route_name: shortcut.set_switch base_route: user.view title: 'Shortcuts' diff --git a/core/modules/shortcut/shortcut.routing.yml b/core/modules/shortcut/shortcut.routing.yml index 100fbc5..9aad750 100644 --- a/core/modules/shortcut/shortcut.routing.yml +++ b/core/modules/shortcut/shortcut.routing.yml @@ -70,13 +70,12 @@ shortcut.link_delete: requirements: _entity_access: 'shortcut.delete' -shortcut.overview: +shortcut.set_switch: path: '/user/{user}/shortcuts' defaults: - _content: '\Drupal\shortcut\Form\ShortcutForm::overview' + _form: 'Drupal\shortcut\Form\SwitchShortcutSet' _title: 'Shortcuts' requirements: - _access_shortcut_set_switch: 'TRUE' + _custom_access: 'Drupal\shortcut\Form\SwitchShortcutSet::checkAccess' options: _admin_route: TRUE - diff --git a/core/modules/shortcut/shortcut.services.yml b/core/modules/shortcut/shortcut.services.yml deleted file mode 100644 index dc8d30c..0000000 --- a/core/modules/shortcut/shortcut.services.yml +++ /dev/null @@ -1,5 +0,0 @@ -services: - access_check.shortcut.shortcut_set_switch: - class: Drupal\shortcut\Access\ShortcutSetSwitchAccessCheck - tags: - - { name: access_check, applies_to: _access_shortcut_set_switch } diff --git a/core/modules/shortcut/src/Access/ShortcutSetSwitchAccessCheck.php b/core/modules/shortcut/src/Access/ShortcutSetSwitchAccessCheck.php deleted file mode 100644 index dece42f..0000000 --- a/core/modules/shortcut/src/Access/ShortcutSetSwitchAccessCheck.php +++ /dev/null @@ -1,54 +0,0 @@ -hasPermission('administer shortcuts')) { - // Administrators can switch anyone's shortcut set. - return static::ALLOW; - } - - if (!$account->hasPermission('access shortcuts')) { - // The user has no permission to use shortcuts. - return static::DENY; - } - - if (!$account->hasPermission('switch shortcut sets')) { - // The user has no permission to switch anyone's shortcut set. - return static::DENY; - } - - if ($user->id() == $account->id()) { - // Users with the 'switch shortcut sets' permission can switch their own - // shortcuts sets. - return static::ALLOW; - } - return static::DENY; - } - -} diff --git a/core/modules/shortcut/src/Form/ShortcutForm.php b/core/modules/shortcut/src/Form/ShortcutForm.php deleted file mode 100644 index 4f556b7..0000000 --- a/core/modules/shortcut/src/Form/ShortcutForm.php +++ /dev/null @@ -1,27 +0,0 @@ -getForm('shortcut_set_switch', $user); - } - -} diff --git a/core/modules/shortcut/src/Form/SwitchShortcutSet.php b/core/modules/shortcut/src/Form/SwitchShortcutSet.php new file mode 100644 index 0000000..ec3180c --- /dev/null +++ b/core/modules/shortcut/src/Form/SwitchShortcutSet.php @@ -0,0 +1,271 @@ +shortcutSetStorage = $shortcut_set_storage; + $this->routeMatch = $route_match; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.manager')->getStorage('shortcut_set'), + $container->get('current_route_match') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'shortcut_set_switch'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state, UserInterface $user = NULL) { + $account = $this->currentUser(); + + $this->user = $user; + + // Prepare the list of shortcut sets. + $options = array_map(function (ShortcutSet $set) { + return String::checkPlain($set->label()); + }, $this->shortcutSetStorage->loadMultiple()); + + $current_set = shortcut_current_displayed_set($this->user); + + // Only administrators can add shortcut sets. + $add_access = $account->hasPermission('administer shortcuts'); + if ($add_access) { + $options['new'] = $this->t('New set'); + } + + $account_is_user = $this->user->id() == $account->id(); + if (count($options) > 1) { + $form['set'] = array( + '#type' => 'radios', + '#title' => $account_is_user ? $this->t('Choose a set of shortcuts to use') : $this->t('Choose a set of shortcuts for this user'), + '#options' => $options, + '#default_value' => $current_set->id(), + ); + + $form['label'] = array( + '#type' => 'textfield', + '#title' => $this->t('Label'), + '#title_display' => 'invisible', + '#description' => $this->t('The new set is created by copying items from your default shortcut set.'), + '#access' => $add_access, + ); + $form['id'] = array( + '#type' => 'machine_name', + '#machine_name' => array( + 'exists' => array($this, 'exists'), + 'replace_pattern' => '[^a-z0-9-]+', + 'replace' => '-', + ), + // This ID could be used for menu name. + '#maxlength' => 23, + '#states' => array( + 'required' => array( + ':input[name="set"]' => array('value' => 'new'), + ), + ), + '#required' => FALSE, + ); + + if (!$account_is_user) { + $default_set = $this->shortcutSetStorage->getDefaultSet($this->user); + $form['new']['#description'] = $this->t('The new set is created by copying items from the %default set.', array('%default' => $default_set->label())); + } + + $form['#attached'] = array( + 'library' => array('shortcut/drupal.shortcut.admin'), + ); + + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => $this->t('Change set'), + ); + } + else { + // There is only 1 option, so output a message in the $form array. + $form['info'] = array( + '#markup' => '

' . $this->t('You are currently using the %set-name shortcut set.', array('%set-name' => $current_set->label())) . '

', + ); + } + + return $form; + } + + /** + * Determines if a shortcut set exists already. + * + * @param string $id + * The set ID to check. + * + * @return bool + * TRUE if the shortcut set exists, FALSE otherwise. + */ + public function exists($id) { + return (bool) $this->shortcutSetStorage->getQuery() + ->condition('id', $id) + ->execute(); + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, array &$form_state) { + if ($form_state['values']['set'] == 'new') { + // Check to prevent creating a shortcut set with an empty title. + if (trim($form_state['values']['label']) == '') { + $this->setFormError('new', $form_state, $this->t('The new set label is required.')); + } + // Check to prevent a duplicate title. + if (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']))); + } + } + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + $account = $this->currentUser(); + + $account_is_user = $this->user->id() == $account->id(); + if ($form_state['values']['set'] == 'new') { + // Save a new shortcut set with links copied from the user's default set. + /* @var \Drupal\shortcut\Entity\ShortcutSet $set */ + $set = $this->shortcutSetStorage->create(array( + 'id' => $form_state['values']['id'], + 'label' => $form_state['values']['label'], + )); + $set->save(); + $replacements = array( + '%user' => $this->user->label(), + '%set_name' => $set->label(), + '@switch-url' => $this->url($this->routeMatch->getRouteName(), array('user' => $this->user->id())), + ); + if ($account_is_user) { + // Only administrators can create new shortcut sets, so we know they have + // access to switch back. + drupal_set_message($this->t('You are now using the new %set_name shortcut set. You can edit it from this page or switch back to a different one.', $replacements)); + } + else { + drupal_set_message($this->t('%user is now using a new shortcut set called %set_name. You can edit it from this page.', $replacements)); + } + $form_state['redirect_route'] = array( + 'route_name' => 'shortcut.set_customize', + 'route_parameters' => array( + 'shortcut_set' => $set->id(), + ), + ); + } + else { + // Switch to a different shortcut set. + /* @var \Drupal\shortcut\Entity\ShortcutSet $set */ + $set = $this->shortcutSetStorage->load($form_state['values']['set']); + $replacements = array( + '%user' => $this->user->label(), + '%set_name' => $set->label(), + ); + drupal_set_message($account_is_user ? $this->t('You are now using the %set_name shortcut set.', $replacements) : $this->t('%user is now using the %set_name shortcut set.', $replacements)); + } + + // Assign the shortcut set to the provided user account. + $this->shortcutSetStorage->assignUser($set, $this->user); + } + + /** + * Checks access for the shortcut set switch form. + * + * @param \Drupal\user\UserInterface $user + * (optional) The owner of the shortcut set. + * + * @return mixed + * AccessInterface::ALLOW, AccessInterface::DENY, or AccessInterface::KILL. + */ + public function checkAccess(UserInterface $user = NULL) { + $account = $this->currentUser(); + $this->user = $user; + + if ($account->hasPermission('administer shortcuts')) { + // Administrators can switch anyone's shortcut set. + return AccessInterface::ALLOW; + } + + if (!$account->hasPermission('access shortcuts')) { + // The user has no permission to use shortcuts. + return AccessInterface::DENY; + } + + if (!$account->hasPermission('switch shortcut sets')) { + // The user has no permission to switch anyone's shortcut set. + return AccessInterface::DENY; + } + + if ($this->user->id() == $account->id()) { + // Users with the 'switch shortcut sets' permission can switch their own + // shortcuts sets. + return AccessInterface::ALLOW; + } + return AccessInterface::DENY; + } + +} diff --git a/core/modules/shortcut/src/ShortcutSetStorage.php b/core/modules/shortcut/src/ShortcutSetStorage.php index ea723d6..dba5752 100644 --- a/core/modules/shortcut/src/ShortcutSetStorage.php +++ b/core/modules/shortcut/src/ShortcutSetStorage.php @@ -7,7 +7,15 @@ namespace Drupal\shortcut; +use Drupal\Component\Uuid\UuidInterface; +use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Config\Entity\ConfigEntityStorage; +use Drupal\Core\Config\StorageInterface; +use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Language\LanguageManagerInterface; +use Drupal\Core\Session\AccountInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines a storage for shortcut_set entities. @@ -15,6 +23,49 @@ class ShortcutSetStorage extends ConfigEntityStorage implements ShortcutSetStorageInterface { /** + * The module handler. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface + */ + protected $moduleHandler; + + /** + * Constructs a ShortcutSetStorageController object. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_info + * The entity info for the entity type. + * @param \Drupal\Core\Config\ConfigFactory $config_factory + * The config factory service. + * @param \Drupal\Core\Config\StorageInterface $config_storage + * The config storage service. + * @param \Drupal\Component\Uuid\UuidInterface $uuid_service + * The UUID service. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler. + * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager + * The language manager. + */ + public function __construct(EntityTypeInterface $entity_info, ConfigFactory $config_factory, StorageInterface $config_storage, UuidInterface $uuid_service, ModuleHandlerInterface $module_handler, LanguageManagerInterface $language_manager) { + parent::__construct($entity_info, $config_factory, $config_storage, $uuid_service, $language_manager); + + $this->moduleHandler = $module_handler; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_info) { + return new static( + $entity_info, + $container->get('config.factory'), + $container->get('config.storage'), + $container->get('uuid'), + $container->get('module_handler'), + $container->get('language_manager') + ); + } + + /** * {@inheritdoc} */ public function deleteAssignedShortcutSets(ShortcutSetInterface $entity) { @@ -63,4 +114,24 @@ public function countAssignedUsers(ShortcutSetInterface $shortcut_set) { return db_query('SELECT COUNT(*) FROM {shortcut_set_users} WHERE set_name = :name', array(':name' => $shortcut_set->id()))->fetchField(); } + /** + * {@inheritdoc} + */ + public function getDefaultSet(AccountInterface $account) { + // 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'; + $shortcut_set = NULL; + foreach ($suggestions as $name) { + if ($shortcut_set = $this->load($name)) { + break; + } + } + + return $shortcut_set; + } + } diff --git a/core/modules/shortcut/src/ShortcutSetStorageInterface.php b/core/modules/shortcut/src/ShortcutSetStorageInterface.php index 11af402..995ed9f 100644 --- a/core/modules/shortcut/src/ShortcutSetStorageInterface.php +++ b/core/modules/shortcut/src/ShortcutSetStorageInterface.php @@ -8,6 +8,7 @@ namespace Drupal\shortcut; use Drupal\Core\Config\Entity\ConfigEntityStorageInterface; +use Drupal\Core\Session\AccountInterface; /** * Defines a common interface for shortcut entity controller classes. @@ -68,4 +69,16 @@ public function getAssignedToUser($account); * The number of users who have this set assigned to them. */ public function countAssignedUsers(ShortcutSetInterface $shortcut_set); + + /** + * Gets the default shortcut set for a given user account. + * + * @param \Drupal\Core\Session\AccountInterface $account + * The user account whose default shortcut set will be returned. + * + * @return \Drupal\shortcut\ShortcutSetInterface + * An object representing the default shortcut set. + */ + public function getDefaultSet(AccountInterface $account); + } diff --git a/core/modules/shortcut/tests/src/Menu/ShortcutLocalTasksTest.php b/core/modules/shortcut/tests/src/Menu/ShortcutLocalTasksTest.php index c4b4564..25c0a8f 100644 --- a/core/modules/shortcut/tests/src/Menu/ShortcutLocalTasksTest.php +++ b/core/modules/shortcut/tests/src/Menu/ShortcutLocalTasksTest.php @@ -40,7 +40,7 @@ public function setUp() { */ public function testShortcutPageLocalTasks($route) { $tasks = array( - 0 => array('shortcut.overview', 'user.view', 'user.edit',), + 0 => array('shortcut.set_switch', 'user.view', 'user.edit',), ); $this->assertLocalTasks($route, $tasks); } @@ -52,7 +52,7 @@ public function getShortcutPageRoutes() { return array( array('user.view'), array('user.edit'), - array('shortcut.overview'), + array('shortcut.set_switch'), ); }