tour.module

Same filename in other branches
  1. 8.9.x core/modules/tour/tour.module
  2. 10 core/modules/tour/tour.module
  3. 11.x core/modules/tour/tour.module

Main functions of the module.

File

core/modules/tour/tour.module

View source
<?php


/**
 * @file
 * Main functions of the module.
 */
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\tour\Entity\Tour;

/**
 * Implements hook_help().
 */
function tour_help($route_name, RouteMatchInterface $route_match) {
    switch ($route_name) {
        case 'help.page.tour':
            $output = '';
            $output .= '<h3>' . t('About') . '</h3>';
            $output .= '<p>' . t("The Tour module provides users with guided tours of the site interface. Each tour consists of several tips that highlight elements of the user interface, guide the user through a workflow, or explain key concepts of the website. For more information, see the <a href=':tour'>online documentation for the Tour module</a>.", [
                ':tour' => 'https://www.drupal.org/documentation/modules/tour',
            ]) . '</p>';
            $output .= '<h3>' . t('Uses') . '</h3>';
            $output .= '<dl>';
            $output .= '<dt>' . t('Viewing tours') . '</dt>';
            $output .= '<dd>' . t("If a tour is available on a page, a <em>Tour</em> button will be visible in the toolbar. If you click this button the first tip of the tour will appear. The tour continues after clicking the <em>Next</em> button in the tip. To see a tour users must have the permission <em>Access tour</em> and JavaScript must be enabled in the browser") . '</dd>';
            $output .= '<dt>' . t('Creating tours') . '</dt>';
            $output .= '<dd>' . t("Tours can be written as YAML-documents with a text editor, or using the contributed <a href=':tour_ui'>Tour UI</a> module. For more information, see <a href=':doc_url'>the online documentation for writing tours</a>.", [
                ':doc_url' => 'https://www.drupal.org/developing/api/tour',
                ':tour_ui' => 'https://www.drupal.org/project/tour_ui',
            ]) . '</dd>';
            $output .= '</dl>';
            return $output;
    }
}

/**
 * Implements hook_toolbar().
 */
function tour_toolbar() {
    $items = [];
    $items['tour'] = [
        '#cache' => [
            'contexts' => [
                'user.permissions',
            ],
        ],
    ];
    if (!\Drupal::currentUser()->hasPermission('access tour')) {
        return $items;
    }
    $items['tour'] += [
        '#type' => 'toolbar_item',
        'tab' => [
            '#type' => 'html_tag',
            '#tag' => 'button',
            '#value' => t('Tour'),
            '#attributes' => [
                'class' => [
                    'toolbar-icon',
                    'toolbar-icon-help',
                ],
                'aria-pressed' => 'false',
                'type' => 'button',
            ],
        ],
        '#wrapper_attributes' => [
            'class' => [
                'tour-toolbar-tab',
                'hidden',
            ],
            'id' => 'toolbar-tab-tour',
        ],
        '#attached' => [
            'library' => [
                'tour/tour',
            ],
        ],
    ];
    return $items;
}

/**
 * Implements hook_page_bottom().
 */
function tour_page_bottom(array &$page_bottom) {
    if (!\Drupal::currentUser()->hasPermission('access tour')) {
        return;
    }
    // Load all of the items and match on route name.
    $route_match = \Drupal::routeMatch();
    $route_name = $route_match->getRouteName();
    $results = \Drupal::entityQuery('tour')->condition('routes.*.route_name', $route_name)
        ->execute();
    if (!empty($results) && ($tours = Tour::loadMultiple(array_keys($results)))) {
        foreach ($tours as $id => $tour) {
            // Match on params.
            if (!$tour->hasMatchingRoute($route_name, $route_match->getRawParameters()
                ->all())) {
                unset($tours[$id]);
            }
        }
        if (!empty($tours)) {
            $page_bottom['tour'] = \Drupal::entityTypeManager()->getViewBuilder('tour')
                ->viewMultiple($tours, 'full');
        }
    }
}

/**
 * Implements hook_ENTITY_TYPE_insert() for tour entities.
 */
function tour_tour_insert($entity) {
    \Drupal::service('plugin.manager.tour.tip')->clearCachedDefinitions();
}

/**
 * Implements hook_ENTITY_TYPE_update() for tour entities.
 */
function tour_tour_update($entity) {
    \Drupal::service('plugin.manager.tour.tip')->clearCachedDefinitions();
}

/**
 * Implements hook_ENTITY_TYPE_presave() for tour entities.
 *
 * @todo https://www.drupal.org/i/3195823 Remove once deprecated properties are
 *   no longer supported.
 */
function tour_tour_presave(Tour $tour) {
    _tour_update_joyride($tour);
}

/**
 * Updates a tour to make it compatible with the Shepherd library.
 *
 * @param \Drupal\tour\Entity\Tour $tour
 *   The tour to update.
 * @param bool $trigger_deprecation
 *   (optional) Whether to trigger deprecations. Defaults to TRUE.
 *
 * @return bool
 *   Whether or not the entity needs saving.
 *
 * @see tour_post_update_joyride_selectors_to_selector_property()
 *
 * @internal
 *
 * @todo https://www.drupal.org/i/3195823 Remove once deprecated properties are
 *   no longer supported.
 */
function _tour_update_joyride(Tour $tour, bool $trigger_deprecation = TRUE) : bool {
    $needs_save = FALSE;
    // Update jQuery Joyride based plugins into a new, more structured format that
    // is compatible with Shepherd.
    $tips = $tour->get('tips');
    foreach ($tips as &$tip) {
        if (isset($tip['attributes']['data-class']) || isset($tip['attributes']['data-id'])) {
            if ($trigger_deprecation) {
                @trigger_error("The tour.tip 'attributes' config schema property is deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Instead of 'data-class' and 'data-id' attributes, use 'selector' to specify the element a tip attaches to. See https://www.drupal.org/node/3204093", E_USER_DEPRECATED);
            }
            $needs_save = TRUE;
            $selector = isset($tip['attributes']['data-class']) ? ".{$tip['attributes']['data-class']}" : NULL;
            $selector = isset($tip['attributes']['data-id']) ? "#{$tip['attributes']['data-id']}" : $selector;
            $tip['selector'] = $selector;
            // Although the attributes property is deprecated, only the properties
            // with 1:1 equivalents are unset.
            unset($tip['attributes']['data-class'], $tip['attributes']['data-id']);
            // Remove attributes if it is now empty.
            if (empty($tip['attributes'])) {
                unset($tip['attributes']);
            }
        }
        if (isset($tip['location'])) {
            if ($trigger_deprecation) {
                @trigger_error("The tour.tip 'location' config schema property is deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Instead use 'position'. The value must be a valid placement accepted by PopperJS. See https://www.drupal.org/node/3204093", E_USER_DEPRECATED);
            }
            $needs_save = TRUE;
            // Joyride only supports four location options: 'top', 'bottom',
            // 'left', and 'right'. Shepherd also accepts these as options, but they
            // result in different behavior. A given Joyride location option will
            // provide the same results in Shepherd if '-start' is appended to it (
            // e.g. the 'left-start' option in Shepherd positions the element the
            // same way that 'left' does in Joyride.
            //
            // @see https://shepherdjs.dev/docs/Step.html
            $tip['position'] = $tip['location'] . '-start';
            unset($tip['location']);
        }
    }
    if ($needs_save) {
        $tour->set('tips', $tips);
    }
    return $needs_save;
}

Functions

Title Deprecated Summary
tour_help Implements hook_help().
tour_page_bottom Implements hook_page_bottom().
tour_toolbar Implements hook_toolbar().
tour_tour_insert Implements hook_ENTITY_TYPE_insert() for tour entities.
tour_tour_presave Implements hook_ENTITY_TYPE_presave() for tour entities.
tour_tour_update Implements hook_ENTITY_TYPE_update() for tour entities.
_tour_update_joyride Updates a tour to make it compatible with the Shepherd library.

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