Newer
Older
Dries Buytaert
committed
<?php
/**
* @file
* Allows users to manage customizable lists of shortcut links.
*/
catch
committed
use Drupal\Core\Access\AccessResult;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Cache\Cache;
Angie Byron
committed
use Drupal\Core\Routing\RouteMatchInterface;
Alex Pott
committed
use Drupal\Core\Routing\UrlMatcher;
use Drupal\Core\Url;
use Drupal\shortcut\Entity\ShortcutSet;
use Drupal\shortcut\ShortcutSetInterface;
Dries Buytaert
committed
/**
* Implements hook_help().
*/
Angie Byron
committed
function shortcut_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.shortcut':
$output = '<h3>' . t('About') . '</h3>';
Jennifer Hodgdon
committed
$output .= '<p>' . t('The Shortcut module allows users to create sets of <em>shortcut</em> links to commonly-visited pages of the site. Shortcuts are contained within <em>sets</em>. Each user with <em>Select any shortcut set</em> permission can select a shortcut set created by anyone at the site. For more information, see the online handbook entry for <a href="!shortcut">Shortcut module</a>.', array('!shortcut' => 'http://drupal.org/documentation/modules/shortcut')) . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
Dries Buytaert
committed
$output .= '<dl><dt>' . t('Administering shortcuts') . '</dt>';
Alex Pott
committed
$output .= '<dd>' . t('Users with the <em>Administer shortcuts</em> permission can manage shortcut sets and edit the shortcuts within sets from the <a href="!shortcuts">Shortcuts administration page</a>.', array('!shortcuts' => \Drupal::url('entity.shortcut_set.collection'))) . '</dd>';
Dries Buytaert
committed
$output .= '<dt>' . t('Choosing shortcut sets') . '</dt>';
$output .= '<dd>' . t('Users with permission to switch shortcut sets can choose a shortcut set to use from the Shortcuts tab of their user account page.') . '</dd>';
$output .= '<dt>' . t('Adding and removing shortcuts') . '</dt>';
Dries Buytaert
committed
$output .= '<dd>' . t('The Shortcut module creates an add/remove link for each page on your site; the link lets you add or remove the current page from the currently-enabled set of shortcuts (if your theme displays it and you have permission to edit your shortcut set). The core Seven administration theme displays this link next to the page title, as a small + or - sign. If you click on the + sign, you will add that page to your preferred set of shortcuts. If the page is already part of your shortcut set, the link will be a - sign, and will allow you to remove the current page from your shortcut set.') . '</dd>';
$output .= '<dt>' . t('Displaying shortcuts') . '</dt>';
Jennifer Hodgdon
committed
$output .= '<dd>' . t('You can display your shortcuts by enabling the Shortcuts block on the <a href="!blocks">Blocks administration page</a>. Certain administrative modules also display your shortcuts; for example, the core <a href="!toolbar-help">Toolbar module</a> displays them near the top of the page, along with an <em>Edit shortcuts</em> link.', array('!blocks' => \Drupal::url('block.admin_display'), '!toolbar-help' => \Drupal::url('help.page', array('name' => 'toolbar')))) . '</dd>';
$output .= '</dl>';
return $output;
Dries Buytaert
committed
Alex Pott
committed
case 'entity.shortcut_set.collection':
case 'shortcut.set_add':
case 'entity.shortcut_set.edit_form':
$user = \Drupal::currentUser();
Alex Pott
committed
if ($user->hasPermission('access shortcuts') && $user->hasPermission('switch shortcut sets')) {
Angie Byron
committed
$output = '<p>' . t('Define which shortcut set you are using on the <a href="@shortcut-link">Shortcuts tab</a> of your account page.', array('@shortcut-link' => \Drupal::url('shortcut.set_switch', array('user' => $user->id())))) . '</p>';
Dries Buytaert
committed
return $output;
}
}
}
Dries Buytaert
committed
Dries Buytaert
committed
/**
* Access callback for editing a shortcut set.
*
* @param Drupal\shortcut\ShortcutSetInterface $shortcut_set
Dries Buytaert
committed
* (optional) The shortcut set to be edited. If not set, the current user's
* shortcut set will be used.
*
catch
committed
* @return \Drupal\Core\Access\AccessResultInterface
* The access result.
Dries Buytaert
committed
*/
function shortcut_set_edit_access(ShortcutSetInterface $shortcut_set = NULL) {
$account = \Drupal::currentUser();
Alex Pott
committed
// Shortcut administrators can edit any set.
if ($account->hasPermission('administer shortcuts')) {
catch
committed
return AccessResult::allowed()->cachePerRole();
Alex Pott
committed
}
catch
committed
Alex Pott
committed
// Sufficiently-privileged users can edit their currently displayed shortcut
catch
committed
// set, but not other sets. They must also be able to access shortcuts.
$may_edit_current_shortcut_set = $account->hasPermission('customize shortcut links') && (!isset($shortcut_set) || $shortcut_set == shortcut_current_displayed_set()) && $account->hasPermission('access shortcuts');
return AccessResult::allowedIf($may_edit_current_shortcut_set)->cachePerRole();
Dries Buytaert
committed
}
/**
* Access callback for switching the shortcut set assigned to a user account.
*
Dries Buytaert
committed
* @param object $account
Dries Buytaert
committed
* (optional) The user account whose shortcuts will be switched. If not set,
Dries Buytaert
committed
* permissions will be checked for switching the logged-in user's own
* shortcut set.
*
catch
committed
* @return \Drupal\Core\Access\AccessResultInterface
* The access result.
Dries Buytaert
committed
*/
function shortcut_set_switch_access($account = NULL) {
$user = \Drupal::currentUser();
Dries Buytaert
committed
if ($user->hasPermission('administer shortcuts')) {
Dries Buytaert
committed
// Administrators can switch anyone's shortcut set.
catch
committed
return AccessResult::allowed()->cachePerRole();
Dries Buytaert
committed
}
Alex Pott
committed
if (!$user->hasPermission('access shortcuts')) {
// The user has no permission to use shortcuts.
Alex Pott
committed
return AccessResult::neutral()->cachePerRole();
Alex Pott
committed
}
if (!$user->hasPermission('switch shortcut sets')) {
Dries Buytaert
committed
// The user has no permission to switch anyone's shortcut set.
Alex Pott
committed
return AccessResult::neutral()->cachePerRole();
Dries Buytaert
committed
}
catch
committed
// Users with the 'switch shortcut sets' permission can switch their own
// shortcuts sets.
if (!isset($account)) {
return AccessResult::allowed()->cachePerRole();
}
else if ($user->id() == $account->id()) {
return AccessResult::allowed()->cachePerRole()->cachePerUser();
Dries Buytaert
committed
}
catch
committed
// No opinion.
Alex Pott
committed
return AccessResult::neutral()->cachePerRole();
Dries Buytaert
committed
}
/**
Dries Buytaert
committed
* Assigns a user to a particular shortcut set.
Dries Buytaert
committed
*
* @param $shortcut_set Drupal\shortcut\Entity\Shortcut
Dries Buytaert
committed
* An object representing the shortcut set.
* @param $account
* A user account that will be assigned to use the set.
*/
function shortcut_set_assign_user($shortcut_set, $account) {
\Drupal::entityManager()
catch
committed
->getStorage('shortcut_set')
->assignUser($shortcut_set, $account);
Dries Buytaert
committed
}
/**
Dries Buytaert
committed
* Unassigns a user from any shortcut set they may have been assigned to.
Dries Buytaert
committed
*
* The user will go back to using whatever default set applies.
*
* @param $account
* A user account that will be removed from the shortcut set assignment.
Dries Buytaert
committed
*
Dries Buytaert
committed
* @return
* TRUE if the user was previously assigned to a shortcut set and has been
* successfully removed from it. FALSE if the user was already not assigned
* to any set.
*/
function shortcut_set_unassign_user($account) {
return (bool) \Drupal::entityManager()
catch
committed
->getStorage('shortcut_set')
->unassignUser($account);
Dries Buytaert
committed
}
/**
* Returns the current displayed shortcut set for the provided user account.
*
* @param $account
* (optional) The user account whose shortcuts will be returned. Defaults to
Dries Buytaert
committed
* the currently logged-in user.
*
Dries Buytaert
committed
* @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());
Alex Pott
committed
$user = \Drupal::currentUser();
Dries Buytaert
committed
if (!isset($account)) {
$account = $user;
}
// Try to return a shortcut set from the static cache.
Dries Buytaert
committed
if (isset($shortcut_sets[$account->id()])) {
return $shortcut_sets[$account->id()];
Dries Buytaert
committed
}
// If none was found, try to find a shortcut set that is explicitly assigned
// to this user.
$shortcut_set_name = \Drupal::entityManager()
catch
committed
->getStorage('shortcut_set')
->getAssignedToUser($account);
Angie Byron
committed
if ($shortcut_set_name) {
$shortcut_set = ShortcutSet::load($shortcut_set_name);
Angie Byron
committed
}
Dries Buytaert
committed
// Otherwise, use the default set.
Dries Buytaert
committed
else {
Dries Buytaert
committed
$shortcut_set = shortcut_default_set($account);
}
Angie Byron
committed
Dries Buytaert
committed
$shortcut_sets[$account->id()] = $shortcut_set;
Dries Buytaert
committed
return $shortcut_set;
}
/**
* Returns the default shortcut set for a given user account.
*
Dries Buytaert
committed
* @param object $account
* (optional) The user account whose default shortcut set will be returned.
* If not provided, the function will return the currently logged-in user's
* default shortcut set.
*
Dries Buytaert
committed
* @return
* An object representing the default shortcut set.
*/
function shortcut_default_set($account = NULL) {
Alex Pott
committed
$user = \Drupal::currentUser();
Dries Buytaert
committed
if (!isset($account)) {
$account = $user;
}
Dries Buytaert
committed
Dries Buytaert
committed
// 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
Dries Buytaert
committed
// default, which is the lowest-numbered shortcut set.
$suggestions = array_reverse(\Drupal::moduleHandler()->invokeAll('shortcut_default_set', array($account)));
Angie Byron
committed
$suggestions[] = 'default';
Dries Buytaert
committed
foreach ($suggestions as $name) {
if ($shortcut_set = ShortcutSet::load($name)) {
Dries Buytaert
committed
break;
}
}
Dries Buytaert
committed
Dries Buytaert
committed
return $shortcut_set;
}
Dries Buytaert
committed
/**
* Check to see if a shortcut set with the given title already exists.
*
* @param $title
* Human-readable name of the shortcut set to check.
*
* @return
* TRUE if a shortcut set with that title exists; FALSE otherwise.
*/
function shortcut_set_title_exists($title) {
$sets = ShortcutSet::loadMultiple();
foreach ($sets as $set) {
if ($set->label() == $title) {
Angie Byron
committed
return TRUE;
}
}
return FALSE;
Dries Buytaert
committed
}
Dries Buytaert
committed
/**
* Returns an array of shortcut links, suitable for rendering.
*
* @param \Drupal\shortcut\ShortcutSetInterface $shortcut_set
Dries Buytaert
committed
* (optional) An object representing the set whose links will be displayed.
* If not provided, the user's current set will be displayed.
*
* @return \Drupal\shortcut\ShortcutInterface[]
Dries Buytaert
committed
* An array of shortcut links, in the format returned by the menu system.
*/
function shortcut_renderable_links($shortcut_set = NULL) {
$shortcut_links = array();
Dries Buytaert
committed
if (!isset($shortcut_set)) {
$shortcut_set = shortcut_current_displayed_set();
}
catch
committed
/** @var \Drupal\shortcut\ShortcutInterface[] $shortcuts */
catch
committed
$shortcuts = \Drupal::entityManager()->getStorage('shortcut')->loadByProperties(array('shortcut_set' => $shortcut_set->id()));
$cache_tags = array();
foreach ($shortcuts as $shortcut) {
Angie Byron
committed
$shortcut = \Drupal::entityManager()->getTranslationFromContext($shortcut);
$links[] = array(
'title' => $shortcut->label(),
'url' => Url::fromRoute($shortcut->getRouteName(), $shortcut->getRouteParameters()),
);
$cache_tags = Cache::mergeTags($cache_tags, $shortcut->getCacheTags());
}
if (!empty($links)) {
$shortcut_links = array(
'#theme' => 'links__toolbar_shortcuts',
'#links' => $links,
'#attributes' => array(
'class' => array('menu'),
),
catch
committed
'#cache' => array(
'tags' => $cache_tags,
catch
committed
),
);
}
return $shortcut_links;
Dries Buytaert
committed
}
/**
Angie Byron
committed
* Implements hook_preprocess_HOOK() for block templates.
*/
function shortcut_preprocess_block(&$variables) {
Alex Pott
committed
if ($variables['configuration']['provider'] == 'shortcut') {
Dries Buytaert
committed
$variables['attributes']['role'] = 'navigation';
}
}
Dries Buytaert
committed
/**
Angie Byron
committed
* Implements hook_preprocess_HOOK() for page templates.
Dries Buytaert
committed
*/
Angie Byron
committed
function shortcut_preprocess_page(&$variables) {
// Only display the shortcut link if the user has the ability to edit
// 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).
catch
committed
if (shortcut_set_edit_access()->isAllowed() && !\Drupal::request()->attributes->has('exception')) {
$link = Url::fromRouteMatch(\Drupal::routeMatch())->getInternalPath();
$route_match = \Drupal::routeMatch();
Dries Buytaert
committed
$query = array(
'link' => $link,
'name' => $variables['title'],
Dries Buytaert
committed
);
$query += drupal_get_destination();
$shortcut_set = shortcut_current_displayed_set();
Angie Byron
committed
// Check if $link is already a shortcut and set $link_mode accordingly.
catch
committed
$shortcuts = \Drupal::entityManager()->getStorage('shortcut')->loadByProperties(array('shortcut_set' => $shortcut_set->id()));
foreach ($shortcuts as $shortcut) {
if ($shortcut->getRouteName() == $route_match->getRouteName() && $shortcut->getRouteParameters() == $route_match->getParameters()->all()) {
$shortcut_id = $shortcut->id();
Angie Byron
committed
break;
}
}
$link_mode = isset($shortcut_id) ? "remove" : "add";
Angie Byron
committed
if ($link_mode == "add") {
catch
committed
$link_text = shortcut_set_switch_access()->isAllowed() ? 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());
Angie Byron
committed
}
else {
$query['id'] = $shortcut_id;
catch
committed
$link_text = shortcut_set_switch_access()->isAllowed() ? t('Remove from %shortcut_set shortcuts', array('%shortcut_set' => $shortcut_set->label())) : t('Remove from shortcuts');
$route_name = 'entity.shortcut.link_delete_inline';
$route_parameters = array('shortcut' => $shortcut_id);
Angie Byron
committed
}
Dries Buytaert
committed
if (theme_get_setting('third_party_settings.shortcut.module_link')) {
$variables['title_suffix']['add_or_remove_shortcut'] = array(
catch
committed
'#attached' => array(
Angie Byron
committed
'library' => array(
'shortcut/drupal.shortcut',
catch
committed
),
),
'#prefix' => '<div class="add-or-remove-shortcuts ' . $link_mode . '-shortcut">',
'#type' => 'link',
Alex Pott
committed
'#title' => '<span class="icon"></span><span class="text">'. $link_text .'</span>',
'#url' => Url::fromRoute($route_name, $route_parameters),
Alex Pott
committed
'#options' => array('query' => $query, 'html' => TRUE),
'#suffix' => '</div>',
);
}
Dries Buytaert
committed
}
Angie Byron
committed
}
/**
* Implements hook_toolbar().
Angie Byron
committed
*/
function shortcut_toolbar() {
Alex Pott
committed
$user = \Drupal::currentUser();
Angie Byron
committed
$items = array();
Alex Pott
committed
if ($user->hasPermission('access shortcuts')) {
$links = shortcut_renderable_links();
$shortcut_set = shortcut_current_displayed_set();
$configure_link = NULL;
catch
committed
if (shortcut_set_edit_access($shortcut_set)->isAllowed()) {
Alex Pott
committed
$configure_link = array(
Angie Byron
committed
'#type' => 'link',
Alex Pott
committed
'#title' => t('Edit shortcuts'),
'#url' => Url::fromRoute('entity.shortcut_set.customize_form', ['shortcut_set' => $shortcut_set->id()]),
Alex Pott
committed
'#options' => array('attributes' => array('class' => array('edit-shortcuts'))),
);
}
if (!empty($links) || !empty($configure_link)) {
$items['shortcuts'] = array(
'#type' => 'toolbar_item',
'tab' => array(
'#type' => 'link',
'#title' => t('Shortcuts'),
Alex Pott
committed
'#url' => $shortcut_set->urlInfo('collection'),
Alex Pott
committed
'#attributes' => array(
'title' => t('Shortcuts'),
'class' => array('toolbar-icon', 'toolbar-icon-shortcut'),
),
Angie Byron
committed
),
Alex Pott
committed
'tray' => array(
'#heading' => t('User-defined shortcuts'),
'shortcuts' => $links,
'configure' => $configure_link,
Angie Byron
committed
),
Alex Pott
committed
'#weight' => -10,
'#attached' => array(
'library' => array(
'shortcut/drupal.shortcut',
),
),
);
}
Angie Byron
committed
}
return $items;
Dries Buytaert
committed
}
Dries Buytaert
committed
/**
* Implements hook_themes_installed().
*/
function shortcut_themes_installed($theme_list) {
if (in_array('seven', $theme_list)) {
// Theme settings are not configuration entities and cannot depend on modules
// so to set a module-specific setting, we need to set it with logic.
if (\Drupal::moduleHandler()->moduleExists('shortcut')) {
\Drupal::configFactory()->getEditable('seven.settings')->set('third_party_settings.shortcut.module_link', TRUE)->save();