shortcut.module

Same filename in other branches
  1. 7.x modules/shortcut/shortcut.module
  2. 9 core/modules/shortcut/shortcut.module
  3. 8.9.x core/modules/shortcut/shortcut.module
  4. 10 core/modules/shortcut/shortcut.module

File

core/modules/shortcut/shortcut.module

View source
<?php


/**
 * @file
 */
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Url;
use Drupal\shortcut\ShortcutSetInterface;

/**
 * Access callback for editing a shortcut set.
 *
 * @param Drupal\shortcut\ShortcutSetInterface $shortcut_set
 *   (optional) The shortcut set to be edited. If not set, the current user's
 *   shortcut set will be used.
 *
 * @return \Drupal\Core\Access\AccessResultInterface
 *   The access result.
 */
function shortcut_set_edit_access(?ShortcutSetInterface $shortcut_set = NULL) {
    $account = \Drupal::currentUser();
    // Shortcut administrators can edit any set.
    if ($account->hasPermission('administer shortcuts')) {
        return AccessResult::allowed()->cachePerPermissions();
    }
    // Sufficiently-privileged users can edit their currently displayed shortcut
    // set, but not other sets. They must also be able to access shortcuts.
    $may_edit_current_shortcut_set = $account->hasPermission('customize shortcut links') && $account->hasPermission('access shortcuts');
    if ($may_edit_current_shortcut_set && isset($shortcut_set)) {
        $displayed_shortcut_set = \Drupal::entityTypeManager()->getStorage('shortcut_set')
            ->getDisplayedToUser($account);
        $may_edit_current_shortcut_set = $shortcut_set == $displayed_shortcut_set;
    }
    $result = AccessResult::allowedIf($may_edit_current_shortcut_set)->cachePerPermissions();
    if (!$result->isAllowed()) {
        $result->setReason("The shortcut set must be the currently displayed set for the user and the user must have 'access shortcuts' AND 'customize shortcut links' permissions.");
    }
    return $result;
}

/**
 * Access callback for switching the shortcut set assigned to a user account.
 *
 * @param object $account
 *   (optional) The user account whose shortcuts will be switched. If not set,
 *   permissions will be checked for switching the logged-in user's own
 *   shortcut set.
 *
 * @return \Drupal\Core\Access\AccessResultInterface
 *   The access result.
 */
function shortcut_set_switch_access($account = NULL) {
    $user = \Drupal::currentUser();
    if ($user->hasPermission('administer shortcuts')) {
        // Administrators can switch anyone's shortcut set.
        return AccessResult::allowed()->cachePerPermissions();
    }
    if (!$user->hasPermission('access shortcuts')) {
        // The user has no permission to use shortcuts.
        return AccessResult::neutral()->cachePerPermissions();
    }
    if (!$user->hasPermission('switch shortcut sets')) {
        // The user has no permission to switch anyone's shortcut set.
        return AccessResult::neutral()->cachePerPermissions();
    }
    // Users with the 'switch shortcut sets' permission can switch their own
    // shortcuts sets.
    if (!isset($account)) {
        return AccessResult::allowed()->cachePerPermissions();
    }
    elseif ($user->id() == $account->id()) {
        return AccessResult::allowed()->cachePerPermissions()
            ->cachePerUser();
    }
    // No opinion.
    return AccessResult::neutral()->cachePerPermissions();
}

/**
 * Returns an array of shortcut links, suitable for rendering.
 *
 * @param \Drupal\shortcut\ShortcutSetInterface $shortcut_set
 *   (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[]
 *   An array of shortcut links, in the format returned by the menu system.
 */
function shortcut_renderable_links($shortcut_set = NULL) {
    $shortcut_links = [];
    if (!isset($shortcut_set)) {
        $account = \Drupal::currentUser();
        $shortcut_set = \Drupal::entityTypeManager()->getStorage('shortcut_set')
            ->getDisplayedToUser($account);
    }
    $cache_tags = [];
    foreach ($shortcut_set->getShortcuts() as $shortcut) {
        $shortcut = \Drupal::service('entity.repository')->getTranslationFromContext($shortcut);
        $url = $shortcut->getUrl();
        if ($url->access()) {
            $links[$shortcut->id()] = [
                'type' => 'link',
                'title' => $shortcut->label(),
                'url' => $shortcut->getUrl(),
            ];
            $cache_tags = Cache::mergeTags($cache_tags, $shortcut->getCacheTags());
        }
    }
    if (!empty($links)) {
        $shortcut_links = [
            '#theme' => 'links__toolbar_shortcuts',
            '#links' => $links,
            '#attributes' => [
                'class' => [
                    'toolbar-menu',
                ],
            ],
            '#cache' => [
                'tags' => $cache_tags,
            ],
        ];
    }
    return $shortcut_links;
}

/**
 * Implements hook_preprocess_HOOK() for block templates.
 */
function shortcut_preprocess_block(&$variables) : void {
    if ($variables['configuration']['provider'] == 'shortcut') {
        $variables['attributes']['role'] = 'navigation';
    }
}

/**
 * Implements hook_preprocess_HOOK() for page title templates.
 */
function shortcut_preprocess_page_title(&$variables) : void {
    // Only display the shortcut link if the user has the ability to edit
    // shortcuts, the feature is enabled for the current theme 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()->isAllowed() && theme_get_setting('third_party_settings.shortcut.module_link') && !\Drupal::request()->attributes
        ->has('exception')) {
        $link = Url::fromRouteMatch(\Drupal::routeMatch())->getInternalPath();
        $route_match = \Drupal::routeMatch();
        // Replicate template_preprocess_html()'s processing to get the title in
        // string form, so we can set the default name for the shortcut.
        $name = $variables['title'] ?? '';
        if (is_array($name)) {
            $name = \Drupal::service('renderer')->render($name);
        }
        $query = [
            'link' => $link,
            'name' => trim(strip_tags($name)),
        ];
        $shortcut_set = \Drupal::entityTypeManager()->getStorage('shortcut_set')
            ->getDisplayedToUser(\Drupal::currentUser());
        // Pages with the add or remove shortcut button need cache invalidation when
        // a shortcut is added, edited, or removed.
        $cacheability_metadata = CacheableMetadata::createFromRenderArray($variables);
        $cacheability_metadata->addCacheTags(\Drupal::entityTypeManager()->getDefinition('shortcut')
            ->getListCacheTags());
        $cacheability_metadata->applyTo($variables);
        // Check if $link is already a shortcut and set $link_mode accordingly.
        $shortcuts = \Drupal::entityTypeManager()->getStorage('shortcut')
            ->loadByProperties([
            'shortcut_set' => $shortcut_set->id(),
        ]);
        
        /** @var \Drupal\shortcut\ShortcutInterface $shortcut */
        foreach ($shortcuts as $shortcut) {
            if (($shortcut_url = $shortcut->getUrl()) && $shortcut_url->isRouted() && $shortcut_url->getRouteName() == $route_match->getRouteName() && $shortcut_url->getRouteParameters() == $route_match->getRawParameters()
                ->all()) {
                $shortcut_id = $shortcut->id();
                break;
            }
        }
        $link_mode = isset($shortcut_id) ? "remove" : "add";
        if ($link_mode == "add") {
            $link_text = shortcut_set_switch_access()->isAllowed() ? t('Add to %shortcut_set shortcuts', [
                '%shortcut_set' => $shortcut_set->label(),
            ]) : t('Add to shortcuts');
            $route_name = 'shortcut.link_add_inline';
            $route_parameters = [
                'shortcut_set' => $shortcut_set->id(),
            ];
        }
        else {
            $query['id'] = $shortcut_id;
            $link_text = shortcut_set_switch_access()->isAllowed() ? t('Remove from %shortcut_set shortcuts', [
                '%shortcut_set' => $shortcut_set->label(),
            ]) : t('Remove from shortcuts');
            $route_name = 'entity.shortcut.link_delete_inline';
            $route_parameters = [
                'shortcut' => $shortcut_id,
            ];
        }
        $query += \Drupal::destination()->getAsArray();
        $variables['title_suffix']['add_or_remove_shortcut'] = [
            '#attached' => [
                'library' => [
                    'shortcut/drupal.shortcut',
                ],
            ],
            '#type' => 'link',
            '#title' => new FormattableMarkup('<span class="shortcut-action__icon"></span><span class="shortcut-action__message">@text</span>', [
                '@text' => $link_text,
            ]),
            '#url' => Url::fromRoute($route_name, $route_parameters),
            '#options' => [
                'query' => $query,
            ],
            '#attributes' => [
                'class' => [
                    'shortcut-action',
                    'shortcut-action--' . $link_mode,
                ],
            ],
        ];
    }
}

Functions

Title Deprecated Summary
shortcut_preprocess_block Implements hook_preprocess_HOOK() for block templates.
shortcut_preprocess_page_title Implements hook_preprocess_HOOK() for page title templates.
shortcut_renderable_links Returns an array of shortcut links, suitable for rendering.
shortcut_set_edit_access Access callback for editing a shortcut set.
shortcut_set_switch_access Access callback for switching the shortcut set assigned to a user account.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.