diff --git a/core/MAINTAINERS.txt b/core/MAINTAINERS.txt index e4120cc3d8..3003d6dc34 100644 --- a/core/MAINTAINERS.txt +++ b/core/MAINTAINERS.txt @@ -232,6 +232,10 @@ Hypertext Application Language (HAL) Help - ? +Help Topics +- Amber Matz 'Amber Himes Matz' https://www.drupal.org/u/amber-himes-matz +- Andrey Postnikov 'andypost' https://www.drupal.org/u/andypost + Image - Claudiu Cristea 'claudiu.cristea' https://www.drupal.org/u/claudiu.cristea diff --git a/core/composer.json b/core/composer.json index 020498f834..772d96e91a 100644 --- a/core/composer.json +++ b/core/composer.json @@ -123,6 +123,7 @@ "drupal/forum": "self.version", "drupal/hal": "self.version", "drupal/help": "self.version", + "drupal/help_topics": "self.version", "drupal/history": "self.version", "drupal/image": "self.version", "drupal/inline_form_errors": "self.version", diff --git a/core/modules/help_topics/help_topics.info.yml b/core/modules/help_topics/help_topics.info.yml new file mode 100644 index 0000000000..3afdacc432 --- /dev/null +++ b/core/modules/help_topics/help_topics.info.yml @@ -0,0 +1,8 @@ +name: Help Topics +type: module +description: 'Displays help topics provided by themes and modules.' +core: 8.x +package: Core (Experimental) +version: VERSION +dependencies: + - drupal:help diff --git a/core/modules/help_topics/help_topics.module b/core/modules/help_topics/help_topics.module new file mode 100644 index 0000000000..9ec6d21335 --- /dev/null +++ b/core/modules/help_topics/help_topics.module @@ -0,0 +1,63 @@ +' . t('About') . ''; + $output .= '

' . t('The Help Topics module adds module- and theme-provided help topics to the module overviews from the core Help module. For more information, see the online documentation for the Help Topics module.', [':online' => 'https://www.drupal.org/modules/help_topics']) . '

'; + $output .= '

' . t('Uses') . '

'; + $output .= '
'; + $output .= '
' . t('Viewing help topics') . '
'; + $output .= '
' . t('The top-level help topics are listed on the main Help page. Links to other topics, including non-top-level help topics, can be found under the "Related" heading when viewing a topic page.', [':help_page' => Url::fromRoute('help.main')->toString()]) . '
'; + $output .= '
' . t('Providing help topics') . '
'; + $output .= '
' . t("Modules and themes can provide help topics as YAML-file-based plugins in a project sub-directory called help_topics. Any file in a module or theme's help_topics directory with the suffix *.help_topic.yml will be discovered by the Help Topic module. Plugin-based help topics provided by modules and themes will automatically be updated when a module or theme is updated. Use the plugins in core/modules/help_topics/help_topics as a guide when writing and formatting a help topic plugin for your theme or module.") . '
'; + $output .= '
' . t('Translating help topics') . '
'; + $output .= '
' . t('The title and body text of help topics provided by contributed modules and themes are translatable using the Interface Translation module. Topics provided by custom modules and themes are also translatable if they have been viewed at least once in a non-English language, which triggers putting their translatable text into the translation database.', [':locale_help' => (\Drupal::moduleHandler()->moduleExists('locale')) ? \Drupal::url('help.page', ['name' => 'locale']) : '#']) . '
'; + $output .= '
'; + return ['#markup' => $output]; + + case 'help_topics.help_topic': + return '

' . t('See the Help page for more topics.', [ + ':help_page' => Url::fromRoute('help.main')->toString(), + ]) . '

'; + } +} + +/** + * Implements hook_theme(). + */ +function help_topics_theme($existing, $type, $theme, $path) { + $twigPlugins = array_filter(\Drupal::service('plugin.manager.help_topic')->getDefinitions(), function (array $definition) { + return $definition['class'] === HelpTopicTwig::class; + }); + $return = [ + 'help_topic' => [ + 'variables' => [ + 'body' => [], + 'related' => [], + ], + ], + ]; + foreach ($twigPlugins as $pluginId => $definition) { + $hook = HelpTopicTwig::getThemeHook($pluginId); + $return[$hook] = [ + 'variables' => [], + 'path' => drupal_get_path('module', $definition['provider']) . '/help_topics/templates', + 'template' => strtr($hook, '_', '-'), + ]; + } + return $return; +} diff --git a/core/modules/help_topics/help_topics.permissions.yml b/core/modules/help_topics/help_topics.permissions.yml new file mode 100644 index 0000000000..e7ce493278 --- /dev/null +++ b/core/modules/help_topics/help_topics.permissions.yml @@ -0,0 +1,2 @@ +view help topics: + title: 'View help topics' diff --git a/core/modules/help_topics/help_topics.routing.yml b/core/modules/help_topics/help_topics.routing.yml new file mode 100644 index 0000000000..5038440d20 --- /dev/null +++ b/core/modules/help_topics/help_topics.routing.yml @@ -0,0 +1,6 @@ +help_topics.help_topic: + path: '/admin/help/topic/{id}' + defaults: + _controller: '\Drupal\help_topics\Controller\HelpTopicPluginController::viewHelpTopic' + requirements: + _permission: 'view help topics' diff --git a/core/modules/help_topics/help_topics.services.yml b/core/modules/help_topics/help_topics.services.yml new file mode 100644 index 0000000000..8fd573f4b5 --- /dev/null +++ b/core/modules/help_topics/help_topics.services.yml @@ -0,0 +1,9 @@ +services: + help_topics.breadcrumb: + class: Drupal\help_topics\HelpBreadcrumbBuilder + arguments: ['@string_translation'] + tags: + - { name: breadcrumb_builder, priority: 900 } + plugin.manager.help_topic: + class: Drupal\help_topics\Plugin\HelpTopic\HelpTopicPluginManager + arguments: ['@module_handler', '@theme_handler'] diff --git a/core/modules/help_topics/help_topics.tokens.inc b/core/modules/help_topics/help_topics.tokens.inc new file mode 100644 index 0000000000..979e369acc --- /dev/null +++ b/core/modules/help_topics/help_topics.tokens.inc @@ -0,0 +1,69 @@ + t("Help Topics"), + 'description' => t("Tokens for help topics."), + ]; + + $topics = []; + $topics['url'] = [ + 'name' => t('URL'), + 'description' => t('The URL to the topic. Provide the topic machine name as help_topic:url:MACHINE_NAME'), + ]; + + return [ + 'types' => $types, + 'tokens' => [ + 'help_topic' => $topics, + ], + ]; +} + +/** + * Implements hook_tokens(). + */ +function help_topics_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) { + $replacements = []; + $token_service = \Drupal::token(); + /** @var \Drupal\help_topics\Plugin\HelpTopic\HelpTopicPluginManagerInterface $plugin_manager */ + $plugin_manager = \Drupal::service('plugin.manager.help_topic'); + + // Our tokens generate URLs, which depend on language. See if a language is + // passed in; if not, we will let the URL system use its own defaults. + $url_options = []; + if (isset($options['langcode'])) { + $language_manager = \Drupal::languageManager(); + $language = $language_manager->getLanguage($options['langcode']); + if ($language) { + $url_options['language'] = $language; + } + } + + if ($type == 'help_topic') { + $topics = $token_service->findWithPrefix($tokens, 'url'); + foreach ($topics as $name => $original) { + /** @var \Drupal\help_topics\Plugin\HelpTopic\HelpTopicPluginInterface $topic */ + if ($plugin_manager->hasDefinition($name) && $topic = $plugin_manager->createInstance($name, [])) { + $url = $topic->toUrl($url_options)->toString(TRUE); + $replacements[$original] = $url->getGeneratedUrl(); + $bubbleable_metadata + ->addCacheableDependency($url) + ->addCacheableDependency($topic); + } + } + } + + return $replacements; +} diff --git a/core/modules/help_topics/help_topics/config_basic.help_topic.yml b/core/modules/help_topics/help_topics/config_basic.help_topic.yml new file mode 100644 index 0000000000..eb6504f765 --- /dev/null +++ b/core/modules/help_topics/help_topics/config_basic.help_topic.yml @@ -0,0 +1,5 @@ +id: config_basic +label: 'Changing basic site settings' +top_level: true +related: { } +list_on: { } diff --git a/core/modules/help_topics/help_topics/config_error.help_topic.yml b/core/modules/help_topics/help_topics/config_error.help_topic.yml new file mode 100644 index 0000000000..6317dfbb7f --- /dev/null +++ b/core/modules/help_topics/help_topics/config_error.help_topic.yml @@ -0,0 +1,11 @@ +id: config_error +label: 'Configuring error responses, including 403/404 pages' +top_level: false +related: + - config_basic + - maintenance +list_on: + - config_basic + - maintenance + - menu_overview + - security diff --git a/core/modules/help_topics/help_topics/help_topic_writing.help_topic.yml b/core/modules/help_topics/help_topics/help_topic_writing.help_topic.yml new file mode 100644 index 0000000000..04d972821a --- /dev/null +++ b/core/modules/help_topics/help_topics/help_topic_writing.help_topic.yml @@ -0,0 +1,5 @@ +id: help_topic_writing +label: 'Writing good help' +top_level: true +related: { } +list_on: { } diff --git a/core/modules/help_topics/help_topics/maintenance.help_topic.yml b/core/modules/help_topics/help_topics/maintenance.help_topic.yml new file mode 100644 index 0000000000..1aee4e0128 --- /dev/null +++ b/core/modules/help_topics/help_topics/maintenance.help_topic.yml @@ -0,0 +1,5 @@ +id: maintenance +label: 'Maintaining and troubleshooting your site' +top_level: true +related: { } +list_on: { } diff --git a/core/modules/help_topics/help_topics/menu_overview.help_topic.yml b/core/modules/help_topics/help_topics/menu_overview.help_topic.yml new file mode 100644 index 0000000000..fbc3bd3ebf --- /dev/null +++ b/core/modules/help_topics/help_topics/menu_overview.help_topic.yml @@ -0,0 +1,5 @@ +id: menu_overview +label: 'Defining navigation and URLs' +top_level: true +related: { } +list_on: { } diff --git a/core/modules/help_topics/help_topics/security.help_topic.yml b/core/modules/help_topics/help_topics/security.help_topic.yml new file mode 100644 index 0000000000..2980019181 --- /dev/null +++ b/core/modules/help_topics/help_topics/security.help_topic.yml @@ -0,0 +1,5 @@ +id: security +label: 'Making your site secure' +top_level: true +related: { } +list_on: { } diff --git a/core/modules/help_topics/help_topics/security_account_settings.help_topic.yml b/core/modules/help_topics/help_topics/security_account_settings.help_topic.yml new file mode 100644 index 0000000000..14dfddaac3 --- /dev/null +++ b/core/modules/help_topics/help_topics/security_account_settings.help_topic.yml @@ -0,0 +1,8 @@ +id: security_account_settings +label: 'Defining how user accounts are created' +top_level: false +related: + - security +list_on: + - config_basic + - security diff --git a/core/modules/help_topics/help_topics/templates/help-topic-config-basic.html.twig b/core/modules/help_topics/help_topics/templates/help-topic-config-basic.html.twig new file mode 100644 index 0000000000..1a5b686c97 --- /dev/null +++ b/core/modules/help_topics/help_topics/templates/help-topic-config-basic.html.twig @@ -0,0 +1,12 @@ +{% set regional_url = render_var(url('system.regional_settings')) %} +{% set information_url = render_var(url('system.site_information_settings')) %} +{% set datetime_url = render_var(url('entity.date_format.collection')) %} +

{% trans %}The settings for your site are configured on various administrative pages, as follows:{% endtrans %}

+
+
{% trans %}Site name, slogan, and email address{% endtrans %}
+
{% trans %}On the Basic site settings page, which you can reach in the main Manage administrative menu, by navigating to Configuration > System > Basic site settings.{% endtrans %}
+
{% trans %}Time zone and country{% endtrans %}
+
{% trans %}On the Regional settings page, which you can reach in the main Manage administrative menu, by navigating to Configuration > Regional and language > Regional settings.{% endtrans %}
+
{% trans %}Date and time formats{% endtrans %}
+
{% trans %}On the Date and time formats page, which you can reach in the main Manage administrative menu, by navigating to Configuration > Regional and language > Date and time formats.{% endtrans %}
+
diff --git a/core/modules/help_topics/help_topics/templates/help-topic-config-error.html.twig b/core/modules/help_topics/help_topics/templates/help-topic-config-error.html.twig new file mode 100644 index 0000000000..32eefdce0d --- /dev/null +++ b/core/modules/help_topics/help_topics/templates/help-topic-config-error.html.twig @@ -0,0 +1,8 @@ +{% set log_settings_url = render_var(url('system.logging_settings')) %} +{% set site_settings_url = render_var(url('system.site_information_settings')) %} +

{% trans %}Configuring 403/404 pages{% endtrans %}

+

{% trans %}The core software provides default responses for 403 response (Not Authorized: when someone tries to visit a page they do not have permission to see) and 404 response (Not Found: when someone tries to visit a page that does not exist). You can change what page is displayed for these responses on the Basic site settings page, which you can reach in the main Manage administrative menu, by navigating to Configuration > System > Basic site settings. Note that the pages you want to use must already exist as either system-provided pages or content that you have created.{% endtrans %}

+

{% trans %}Responding to software errors{% endtrans %}

+

{% trans %}Software errors on your site are logged, if you have a logging module installed (such as the core Database Logging module or the core Syslog module). You can configure whether or not error messages are also shown (to both administrators and other site visitors) on the Logging and errors configuration page, which you can reach in the main Manage administrative menu, by navigating to Configuration > Development > Logging and errors.{% endtrans %}

+

{% trans %}Viewing the site log{% endtrans %}

+

{% trans %}If you have the core Database Logging module installed, you can view recent error and informational messages by navigating in the main Manage administrative menu to Reports > Recent log messages. If you are using the core Syslog module for logging, error messages will be logged in your web server''s log files.{% endtrans %}

diff --git a/core/modules/help_topics/help_topics/templates/help-topic-help-topic-writing.html.twig b/core/modules/help_topics/help_topics/templates/help-topic-help-topic-writing.html.twig new file mode 100644 index 0000000000..ca43f59b18 --- /dev/null +++ b/core/modules/help_topics/help_topics/templates/help-topic-help-topic-writing.html.twig @@ -0,0 +1,7 @@ +

{% trans %}Here are some suggestions for how to make your help topics as useful as possible for readers:{% endtrans %}

+ diff --git a/core/modules/help_topics/help_topics/templates/help-topic-maintenance.html.twig b/core/modules/help_topics/help_topics/templates/help-topic-maintenance.html.twig new file mode 100644 index 0000000000..a42d8b6942 --- /dev/null +++ b/core/modules/help_topics/help_topics/templates/help-topic-maintenance.html.twig @@ -0,0 +1 @@ +

{% trans %}The related topics listed here will help you keep your site running and troubleshoot problems.{% endtrans %}

diff --git a/core/modules/help_topics/help_topics/templates/help-topic-menu-overview.html.twig b/core/modules/help_topics/help_topics/templates/help-topic-menu-overview.html.twig new file mode 100644 index 0000000000..9a119ab0c4 --- /dev/null +++ b/core/modules/help_topics/help_topics/templates/help-topic-menu-overview.html.twig @@ -0,0 +1 @@ +

{% trans %}The related topics listed here describe how to set up various aspects of site navigation and URLs.{% endtrans %}

diff --git a/core/modules/help_topics/help_topics/templates/help-topic-security-account-settings.html.twig b/core/modules/help_topics/help_topics/templates/help-topic-security-account-settings.html.twig new file mode 100644 index 0000000000..6db302beac --- /dev/null +++ b/core/modules/help_topics/help_topics/templates/help-topic-security-account-settings.html.twig @@ -0,0 +1,8 @@ +{% set account_settings_url = render_var(url('entity.user.admin_form')) %} +

{% trans %}On the Account settings page, which you can reach from the Manage administrative menu, by navigating to Configuration > People > Account settings (requires the Administer account settings permission), you can configure several settings related to how user accounts are created:{% endtrans %}

+ diff --git a/core/modules/help_topics/help_topics/templates/help-topic-security.html.twig b/core/modules/help_topics/help_topics/templates/help-topic-security.html.twig new file mode 100644 index 0000000000..4b94bb1af6 --- /dev/null +++ b/core/modules/help_topics/help_topics/templates/help-topic-security.html.twig @@ -0,0 +1 @@ +

{% trans %}The topics listed here will help you make and keep your site secure.{% endtrans %}

diff --git a/core/modules/help_topics/help_topics/templates/help-topic-ui-accessibility.html.twig b/core/modules/help_topics/help_topics/templates/help-topic-ui-accessibility.html.twig new file mode 100644 index 0000000000..0c014af6e6 --- /dev/null +++ b/core/modules/help_topics/help_topics/templates/help-topic-ui-accessibility.html.twig @@ -0,0 +1,5 @@ +

{% trans %}The following features of the administrative user interface may help administrative users with disabilities access your site:{% endtrans %}

+
+
{% trans %}Disabling drag-and-drop functionality{% endtrans %}
+
{% trans %}The default drag-and-drop user interface for ordering tables in the administrative interface presents a challenge for some users, including users of screen readers and other assistive technology. The drag-and-drop interface can be disabled in a table by clicking a link labeled Show row weights above the table. The replacement interface allows users to order the table by choosing numerical weights instead of dragging table rows.{% endtrans %}
+
diff --git a/core/modules/help_topics/help_topics/templates/help-topic-ui-components.html.twig b/core/modules/help_topics/help_topics/templates/help-topic-ui-components.html.twig new file mode 100644 index 0000000000..c33e24d834 --- /dev/null +++ b/core/modules/help_topics/help_topics/templates/help-topic-ui-components.html.twig @@ -0,0 +1 @@ +

{% trans %}The related topics listed here describe various aspects of the administrative interface, and tell how to use them.{% endtrans %}

diff --git a/core/modules/help_topics/help_topics/templates/help-topic-ui-contextual.html.twig b/core/modules/help_topics/help_topics/templates/help-topic-ui-contextual.html.twig new file mode 100644 index 0000000000..431f2b3c47 --- /dev/null +++ b/core/modules/help_topics/help_topics/templates/help-topic-ui-contextual.html.twig @@ -0,0 +1,9 @@ +

{% trans %}What are contextual links?{% endtrans %}

+

{% trans %}Contextual links give users with the Use contextual links permission quick access to administrative tasks related to areas of non-administrative pages. For example, if a page on your site displays a block, the block would have a contextual link that would allow users with permission to configure the block. If the block contains a menu or a view, it would also have a contextual link for editing the menu links or the view. Clicking a contextual link takes you to the related administrative page directly, without needing to navigate through the administrative menu system.{% endtrans %}

+

{% trans %}Displaying and using contextual links{% endtrans %}

+

{% trans %}If you have the core Contextual Links module installed, the contextual links related to an area on a page can be displayed by clicking the contextual links button in that area of the page. In most themes, this button looks like a pencil and is placed in the upper right corner of the page area (upper left for right-to-left languages); however, contextual links buttons are normally hidden. Here are two ways to make contextual links buttons visible:{% endtrans %}

+ +

{% trans %}While the contextual links button for the area of interest is visible, click the button to display the list of links for that area. Click a link in the list to perform the task.{% endtrans %}

diff --git a/core/modules/help_topics/help_topics/templates/help-topic-ui-shortcuts.html.twig b/core/modules/help_topics/help_topics/templates/help-topic-ui-shortcuts.html.twig new file mode 100644 index 0000000000..69536add95 --- /dev/null +++ b/core/modules/help_topics/help_topics/templates/help-topic-ui-shortcuts.html.twig @@ -0,0 +1,6 @@ +

{% trans %}What are shortcuts?{% endtrans %}

+

{% trans %}Shortcuts are quick links to administrative pages; they are managed by the core Shortcut module. A site can have one or more shortcut sets, which can be shared by one or more users; each set contains one or more shortcuts. Users need Use shortcuts permission to view shortcuts; Edit current shortcut set permission to add, delete, or edit the shortcuts in the set assigned to them; and Select any shortcut set permission to select a different shortcut set when editing their user profile. There is also an Administer shortcuts permission, which allows an administrator to do any of these actions, and also permits assigning shortcut sets to other users.{% endtrans %}

+

{% trans %}Creating and deleting shortcuts{% endtrans %}

+

{% trans %}When viewing certain administrative pages, you will see a link that allows you to add the page to your current shortcut set. In the core Seven administrative theme, the link looks like a star, and is displayed next to the page title. If the page is already in your shortcut set, you will instead see a link that allows you to remove it.{% endtrans %}

+

{% trans %}Viewing and using shortcuts{% endtrans %}

+

{% trans %}If you have the core Toolbar module installed, click Shortcuts in the toolbar to display your shortcuts. Once they are displayed, click any link in the shortcut bar to go directly to the administrative page. If you are not using the Toolbar module, you can display shortcuts by placing the Shortcuts block in a region of your theme.{% endtrans %}

diff --git a/core/modules/help_topics/help_topics/templates/help-topic-ui-tours.html.twig b/core/modules/help_topics/help_topics/templates/help-topic-ui-tours.html.twig new file mode 100644 index 0000000000..6a48a54786 --- /dev/null +++ b/core/modules/help_topics/help_topics/templates/help-topic-ui-tours.html.twig @@ -0,0 +1,4 @@ +

{% trans %}What are tours?{% endtrans %}

+

{% trans %}The core Tour module provides users with tours, which are guided tours of the administrative interface. Each tour starts on a particular administrative page, and consists of one or more tips that highlight elements of the page, guide you through a workflow, or explain key concepts. Users need Access tour permission to view tours, and JavaScript must be enabled in their browsers.{% endtrans %}

+

{% trans %}Viewing tours{% endtrans %}

+

{% trans %}If a tour is available on a page, and you have the core Toolbar module installed, a Tour button will appear on the right end of the toolbar (left end for right-to-left languages). Click this button to view the first tip of the tour; click the Next button to advance to the next tip, and End tour at the end to close the tour.{% endtrans %}

diff --git a/core/modules/help_topics/help_topics/ui_accessibility.help_topic.yml b/core/modules/help_topics/help_topics/ui_accessibility.help_topic.yml new file mode 100644 index 0000000000..489f96cdbc --- /dev/null +++ b/core/modules/help_topics/help_topics/ui_accessibility.help_topic.yml @@ -0,0 +1,7 @@ +id: ui_accessibility +label: 'Accessibility features' +top_level: false +related: + - ui_components +list_on: + - ui_components diff --git a/core/modules/help_topics/help_topics/ui_components.help_topic.yml b/core/modules/help_topics/help_topics/ui_components.help_topic.yml new file mode 100644 index 0000000000..098d584491 --- /dev/null +++ b/core/modules/help_topics/help_topics/ui_components.help_topic.yml @@ -0,0 +1,5 @@ +id: ui_components +label: 'Using the administrative interface' +top_level: true +related: { } +list_on: { } diff --git a/core/modules/help_topics/help_topics/ui_contextual.help_topic.yml b/core/modules/help_topics/help_topics/ui_contextual.help_topic.yml new file mode 100644 index 0000000000..4b3c23d3a7 --- /dev/null +++ b/core/modules/help_topics/help_topics/ui_contextual.help_topic.yml @@ -0,0 +1,7 @@ +id: ui_contextual +label: 'Contextual links' +top_level: false +related: + - ui_components +list_on: + - ui_components diff --git a/core/modules/help_topics/help_topics/ui_shortcuts.help_topic.yml b/core/modules/help_topics/help_topics/ui_shortcuts.help_topic.yml new file mode 100644 index 0000000000..24af5d2408 --- /dev/null +++ b/core/modules/help_topics/help_topics/ui_shortcuts.help_topic.yml @@ -0,0 +1,7 @@ +id: ui_shortcuts +label: Shortcuts +top_level: false +related: + - ui_components +list_on: + - ui_components diff --git a/core/modules/help_topics/help_topics/ui_tours.help_topic.yml b/core/modules/help_topics/help_topics/ui_tours.help_topic.yml new file mode 100644 index 0000000000..7f5c9872df --- /dev/null +++ b/core/modules/help_topics/help_topics/ui_tours.help_topic.yml @@ -0,0 +1,7 @@ +id: ui_tours +label: Tours +top_level: false +related: + - ui_components +list_on: + - ui_components diff --git a/core/modules/help_topics/src/Controller/HelpTopicPluginController.php b/core/modules/help_topics/src/Controller/HelpTopicPluginController.php new file mode 100644 index 0000000000..2193dad4a1 --- /dev/null +++ b/core/modules/help_topics/src/Controller/HelpTopicPluginController.php @@ -0,0 +1,145 @@ +helpTopicPluginManager = $help_topic_plugin_manager; + $this->token = $token; + $this->renderer = $renderer; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.help_topic'), + $container->get('token'), + $container->get('renderer') + ); + } + + /** + * Displays a help topic page. + * + * @param string $id + * The plugin ID. Maps to the {id} placeholder in the + * help_topics.help_topic route. + * + * @return array + * A render array with the contents of a help topic page. + */ + public function viewHelpTopic($id) { + $build = []; + + if (!$this->helpTopicPluginManager->hasDefinition($id)) { + throw new AccessDeniedHttpException(); + } + /* @var \Drupal\help_topics\Plugin\HelpTopic\HelpTopicPluginInterface $help_topic */ + $help_topic = $this->helpTopicPluginManager->createInstance($id); + + $build['#body'] = $help_topic->getBody(); + + $this->renderer->addCacheableDependency($build, $help_topic); + + // Build the related topics section, starting with the list this topic + // says are related. + $links = []; + + $related = $help_topic->getRelated(); + foreach ($related as $other_id) { + if ($other_id !== $help_topic->getPluginId()) { + if (!$this->helpTopicPluginManager->hasDefinition($other_id)) { + continue; + } + /** @var \Drupal\help_topics\Plugin\HelpTopic\HelpTopicPluginInterface $topic */ + $topic = $this->helpTopicPluginManager->createInstance($other_id); + if ($topic) { + $links[$other_id] = [ + 'title' => $topic->getLabel(), + 'url' => Url::fromRoute('help_topics.help_topic', ['id' => $other_id]), + ]; + $this->renderer->addCacheableDependency($build, $topic); + } + } + } + + // Add in any plugins that have said "List me on this topic". + $liston = $this->helpTopicPluginManager->getAllListOn($id); + foreach ($liston as $topic) { + $other_id = $topic->getPluginId(); + $links[$other_id] = [ + 'title' => $topic->getLabel(), + 'url' => Url::fromRoute('help_topics.help_topic', ['id' => $other_id]), + ]; + $this->renderer->addCacheableDependency($build, $topic); + } + + if (count($links)) { + uasort($links, function ($a, $b) { + if ($a['title'] == $b['title']) { + return 0; + } + return ($a['title'] < $b['title']) ? -1 : 1; + }); + $build['#related'] = [ + '#theme' => 'links', + '#heading' => [ + 'text' => $this->t('Related topics'), + 'level' => 'h2', + ], + '#links' => $links, + ]; + } + + $build['#theme'] = 'help_topic'; + $build['#title'] = $help_topic->getLabel(); + return $build; + } + +} diff --git a/core/modules/help_topics/src/HelpBreadcrumbBuilder.php b/core/modules/help_topics/src/HelpBreadcrumbBuilder.php new file mode 100644 index 0000000000..586be5303a --- /dev/null +++ b/core/modules/help_topics/src/HelpBreadcrumbBuilder.php @@ -0,0 +1,49 @@ +stringTranslation = $string_translation; + } + + /** + * {@inheritdoc} + */ + public function applies(RouteMatchInterface $route_match) { + return $route_match->getRouteName() == 'help_topics.help_topic'; + } + + /** + * {@inheritdoc} + */ + public function build(RouteMatchInterface $route_match) { + $breadcrumb = new Breadcrumb(); + $breadcrumb->addLink(Link::createFromRoute($this->t('Home'), '')); + $breadcrumb->addLink(Link::createFromRoute($this->t('Administration'), 'system.admin')); + $breadcrumb->addLink(Link::createFromRoute($this->t('Help'), 'help.main')); + $breadcrumb->addCacheContexts(['route.name']); + + return $breadcrumb; + } + +} diff --git a/core/modules/help_topics/src/Plugin/HelpSection/HelpTopicSection.php b/core/modules/help_topics/src/Plugin/HelpSection/HelpTopicSection.php new file mode 100644 index 0000000000..9a63a05f01 --- /dev/null +++ b/core/modules/help_topics/src/Plugin/HelpSection/HelpTopicSection.php @@ -0,0 +1,122 @@ +pluginManager = $plugin_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('plugin.manager.help_topic') + ); + } + + /** + * {@inheritdoc} + */ + public function getCacheTags() { + if (!isset($this->topicList)) { + $this->calculateTopics(); + } + + return $this->cacheTagList; + } + + /** + * {@inheritdoc} + */ + public function getCacheContexts() { + // The links are checked for user access, so we need the user permissions + // context. + return ['user.permissions']; + } + + /** + * {@inheritdoc} + */ + public function listTopics() { + if (!isset($this->topicList)) { + $this->calculateTopics(); + } + + return $this->topicList; + } + + /** + * Calculates the topic list and cache tags. + */ + protected function calculateTopics() { + /** @var \Drupal\help_topics\Plugin\HelpTopic\HelpTopicPluginInterface[] $plugins */ + $plugins = $this->pluginManager->getTopLevelTopics(); + + $this->topicList = []; + $cache_tags = []; + foreach ($plugins as $plugin) { + $this->topicList[$plugin->getPluginId()] = $plugin->toLink(); + foreach ($plugin->getCacheTagsForList() as $tag) { + $cache_tags[] = $tag; + } + } + + $this->cacheTagList = array_unique($cache_tags); + } + +} diff --git a/core/modules/help_topics/src/Plugin/HelpTopic/HelpTopicPluginBase.php b/core/modules/help_topics/src/Plugin/HelpTopic/HelpTopicPluginBase.php new file mode 100644 index 0000000000..b4cc3e2e32 --- /dev/null +++ b/core/modules/help_topics/src/Plugin/HelpTopic/HelpTopicPluginBase.php @@ -0,0 +1,152 @@ +pluginDefinition['provider']; + } + + /** + * {@inheritdoc} + */ + public function getLabel() { + return $this->pluginDefinition['label']; + } + + /** + * {@inheritdoc} + */ + public function isTopLevel() { + return $this->pluginDefinition['top_level']; + } + + /** + * {@inheritdoc} + */ + public function getRelated() { + return $this->pluginDefinition['related']; + } + + /** + * {@inheritdoc} + */ + public function getListOn() { + return $this->pluginDefinition['list_on']; + } + + /** + * {@inheritdoc} + */ + public function getCacheMaxAge() { + return Cache::PERMANENT; + } + + /** + * {@inheritdoc} + */ + public function getCacheContexts() { + return []; + } + + /** + * Gets the help topic plugin manager. + * + * @return \Drupal\help_topics\Plugin\HelpTopic\HelpTopicPluginManagerInterface + * The help topic plugin manager. + */ + protected function getPluginManager() { + if (!isset($this->pluginManager)) { + $this->pluginManager = \Drupal::service('plugin.manager.help_topic'); + } + return $this->pluginManager; + } + + /** + * Makes a cache tag from a help topic plugin ID. + * + * @param string $id + * The plugin ID to make a cache tag from. + * + * @return string|null + * The main cache tag for the topic, or NULL if there is not one. + */ + protected function makeCacheTag($id) { + $definition = $this->getPluginManager()->getDefinition($id); + if (!$definition) { + return NULL; + } + + return $definition['cache_tag']; + } + + /** + * {@inheritdoc} + */ + public function getCacheTags() { + $tags = []; + if ($this->pluginDefinition['cache_tag']) { + $tags[] = $this->pluginDefinition['cache_tag']; + } + + foreach ($this->pluginDefinition['related'] as $topic) { + $tag = $this->makeCacheTag($topic); + if ($tag) { + $tags[] = $tag; + } + } + return $tags; + } + + /** + * {@inheritdoc} + */ + public function getCacheTagsForList() { + $tags = []; + // By default, there are no list cache tags, but we do want the cache + // tags for this plugin. + if ($this->pluginDefinition['cache_tag']) { + $tags[] = $this->pluginDefinition['cache_tag']; + } + + return $tags; + } + + /** + * {@inheritdoc} + */ + public function toUrl(array $options = []) { + return Url::fromRoute('help_topics.help_topic', ['id' => $this->getPluginId()], $options); + } + + /** + * {@inheritdoc} + */ + public function toLink($text = NULL, array $options = []) { + if (!$text) { + $text = $this->getLabel(); + } + return Link::createFromRoute($text, 'help_topics.help_topic', ['id' => $this->getPluginId()], $options); + } + +} diff --git a/core/modules/help_topics/src/Plugin/HelpTopic/HelpTopicPluginInterface.php b/core/modules/help_topics/src/Plugin/HelpTopic/HelpTopicPluginInterface.php new file mode 100644 index 0000000000..619a8e4d60 --- /dev/null +++ b/core/modules/help_topics/src/Plugin/HelpTopic/HelpTopicPluginInterface.php @@ -0,0 +1,92 @@ + '', + // The title of the help topic plugin. + 'label' => '', + // Whether or not the topic should appear on the help topics list. + 'top_level' => '', + // List of related topic machine names. + 'related' => [], + // List of topics this one should be listed on. + 'list_on' => [], + 'class' => HelpTopicTwig::class, + 'cache_tag' => '', + ]; + + /** + * The object that discovers plugins managed by this manager. + * + * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface + */ + protected $discovery; + + /** + * The object that instantiates plugins managed by this manager. + * + * @var \Drupal\Component\Plugin\Factory\FactoryInterface + */ + protected $factory; + + /** + * The module handler. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface + */ + protected $moduleHandler; + + /** + * The theme handler. + * + * @var \Drupal\Core\Extension\ThemeHandlerInterface + */ + protected $themeHandler; + + /** + * Constructs a new HelpTopicManager object. + * + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler. + * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler + * The theme handler. + */ + public function __construct(ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) { + $this->moduleHandler = $module_handler; + $this->themeHandler = $theme_handler; + } + + /** + * Performs extra processing on plugin definitions. + * + * By default we add defaults for the type to the definition. If a type has + * additional processing logic, the logic can be added by replacing or + * extending this method. + * + * @param array $definition + * The definition to be processed and modified by reference. + * @param string $plugin_id + * The ID of the plugin this definition is being used for. + */ + public function processDefinition(&$definition, $plugin_id) { + $definition = NestedArray::mergeDeep($this->defaults, $definition); + $definition['id'] = $plugin_id; + } + + /** + * {@inheritdoc} + */ + protected function getDiscovery() { + if (!isset($this->discovery)) { + // We want to find help topic plugins in both modules and themes in + // a sub-directory called help_topics. + $directories = array_merge($this->moduleHandler->getModuleDirectories(), $this->themeHandler->getThemeDirectories()); + + $directories = array_map(function ($dir) { + return [$dir . '/help_topics']; + }, $directories); + + $file_cache_key_suffix = 'help_topic'; + $id_key = 'id'; + $this->discovery = new YamlDirectoryDiscovery($directories, $file_cache_key_suffix, $id_key); + } + return $this->discovery; + } + + /** + * Gets the plugin factory. + * + * @return \Drupal\Component\Plugin\Factory\FactoryInterface + * An instance of the ContainerFactory object. + */ + protected function getFactory() { + if (!isset($this->factory)) { + $this->factory = new ContainerFactory($this); + } + return $this->factory; + } + + /** + * Checks to see if cached plugin definitions exist. + * If they do, then it returns the cached definitions. + * Otherwise, findDefinitions() is called. + * + * @see \Drupal\Core\Plugin\DefaultPluginManager::findDefinitions() + * + * @return array|\mixed[]|null + */ + public function getDefinitions() { + return parent::getDefinitions(); + } + + /** + * {@inheritdoc} + */ + protected function findDefinitions() { + $definitions = $this->getDiscovery()->getDefinitions(); + + foreach ($definitions as $plugin_id => &$definition) { + $definition['id'] = $plugin_id; + $this->processDefinition($definition, $plugin_id); + } + + $this->definitions = $definitions; + return $definitions; + } + + /** + * Checks to see if plugin is provided by an uninstalled module or theme. + */ + public function alterDefinitions(&$definitions) { + parent::alterDefinitions($definitions); + + // If this plugin was provided by a module that does not exist, remove the + // plugin definition. + // @todo Address what to do with an invalid plugin. + // https://www.drupal.org/node/2302623 + foreach ($definitions as $plugin_id => $plugin_definition) { + if (!empty($plugin_definition['provider']) && !$this->moduleHandler->moduleExists($plugin_definition['provider']) && + (!$this->themeHandler->themeExists($plugin_definition['provider']))) { + unset($definitions[$plugin_id]); + } + } + } + + /** + * {@inheritdoc} + */ + public function getTopLevelTopics() { + $topics = []; + + foreach ($this->getDefinitions() as $definition) { + if ($definition['top_level']) { + /* @var \Drupal\help_topics\Plugin\HelpTopic\HelpTopicPluginInterface $topic */ + $topic = $this->createInstance($definition['id']); + $label = (string) $topic->getLabel(); + $topics[$label] = $topic; + } + } + + ksort($topics); + return $topics; + } + + /** + * {@inheritdoc} + */ + public function getAllListOn($id) { + $topics = []; + + foreach ($this->getDefinitions() as $definition) { + if (in_array($id, $definition['list_on'])) { + $topics[] = $this->createInstance($definition['id']); + } + } + + return $topics; + } + + /** + * {@inheritdoc} + */ + public function findMatches($text) { + $topics = []; + foreach ($this->getDefinitions() as $definition) { + if ((stripos($definition['id'], $text) !== FALSE) || + (stripos($definition['label'], $text) !== FALSE)) { + $topics[$definition['label']] = $definition['id']; + } + } + + ksort($topics); + return $topics; + } + +} diff --git a/core/modules/help_topics/src/Plugin/HelpTopic/HelpTopicPluginManagerInterface.php b/core/modules/help_topics/src/Plugin/HelpTopic/HelpTopicPluginManagerInterface.php new file mode 100644 index 0000000000..d4906b8444 --- /dev/null +++ b/core/modules/help_topics/src/Plugin/HelpTopic/HelpTopicPluginManagerInterface.php @@ -0,0 +1,45 @@ +stringTranslation = $container->get('string_translation'); + parent::__construct($configuration, $plugin_id, $plugin_definition); + } + + /** + * Creates a HelpTopicDefaultPlugin. + * + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container + * The dependency injection container. + * @param array $configuration + * The plugin configuration (not actually used). + * @param string $plugin_id + * The plugin ID. + * @param array $plugin_definition + * The plugin definition. + * + * @return static + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static($container, $configuration, $plugin_id, $plugin_definition); + } + + /** + * {@inheritdoc} + */ + public function getLabel() { + return new TranslatableMarkup(parent::getLabel()); + } + + /** + * {@inheritdoc} + */ + public function getBody() { + return [ + '#theme' => self::getThemeHook($this->getPluginId()), + ]; + } + + /** + * Gets the theme hook from then plugin ID. + * + * @param string $plugin_id + * Plugin id. + * + * @return string + * Theme hook. + */ + public static function getThemeHook($plugin_id) { + return 'help_topic_' . $plugin_id; + } + +} diff --git a/core/modules/help_topics/templates/help-topic.html.twig b/core/modules/help_topics/templates/help-topic.html.twig new file mode 100644 index 0000000000..49c8f2550f --- /dev/null +++ b/core/modules/help_topics/templates/help-topic.html.twig @@ -0,0 +1,16 @@ +{# +/** + * @file + * Default theme implementation to display a help topic. + * + * Available variables: + * - body: The body of the topic. + * - related: List of related topic links. + * + * @ingroup themeable + */ +#} +
+ {{ body }} + {{ related }} +
diff --git a/core/modules/help_topics/tests/modules/help_topics_test/help_topics/help_test.help_topic.yml b/core/modules/help_topics/tests/modules/help_topics_test/help_topics/help_test.help_topic.yml new file mode 100644 index 0000000000..ccaed3d529 --- /dev/null +++ b/core/modules/help_topics/tests/modules/help_topics_test/help_topics/help_test.help_topic.yml @@ -0,0 +1,6 @@ +id: help_test +label: 'ABC Help Test module' +top_level: true +related: + - help_test_linked +list_on: { } diff --git a/core/modules/help_topics/tests/modules/help_topics_test/help_topics/help_test_additional.help_topic.yml b/core/modules/help_topics/tests/modules/help_topics_test/help_topics/help_test_additional.help_topic.yml new file mode 100644 index 0000000000..ae331663a1 --- /dev/null +++ b/core/modules/help_topics/tests/modules/help_topics_test/help_topics/help_test_additional.help_topic.yml @@ -0,0 +1,6 @@ +id: help_test_additional +label: 'Additional topic' +top_level: false +related: { } +list_on: + - help_test diff --git a/core/modules/help_topics/tests/modules/help_topics_test/help_topics/help_test_linked.help_topic.yml b/core/modules/help_topics/tests/modules/help_topics_test/help_topics/help_test_linked.help_topic.yml new file mode 100644 index 0000000000..2c572a244e --- /dev/null +++ b/core/modules/help_topics/tests/modules/help_topics_test/help_topics/help_test_linked.help_topic.yml @@ -0,0 +1,5 @@ +id: help_test_linked +label: 'Linked topic' +top_level: false +related: { } +list_on: { } diff --git a/core/modules/help_topics/tests/modules/help_topics_test/help_topics/templates/help-topic-help-test-additional.html.twig b/core/modules/help_topics/tests/modules/help_topics_test/help_topics/templates/help-topic-help-test-additional.html.twig new file mode 100644 index 0000000000..7d8f2f9549 --- /dev/null +++ b/core/modules/help_topics/tests/modules/help_topics_test/help_topics/templates/help-topic-help-test-additional.html.twig @@ -0,0 +1 @@ +

{% trans %}This topic should get listed automatically on the Help test topic.{% endtrans %}

diff --git a/core/modules/help_topics/tests/modules/help_topics_test/help_topics/templates/help-topic-help-test-linked.html.twig b/core/modules/help_topics/tests/modules/help_topics_test/help_topics/templates/help-topic-help-test-linked.html.twig new file mode 100644 index 0000000000..2205cf45ad --- /dev/null +++ b/core/modules/help_topics/tests/modules/help_topics_test/help_topics/templates/help-topic-help-test-linked.html.twig @@ -0,0 +1 @@ +

{% trans %}This topic is not supposed to be top-level.{% endtrans %}

diff --git a/core/modules/help_topics/tests/modules/help_topics_test/help_topics/templates/help-topic-help-test.html.twig b/core/modules/help_topics/tests/modules/help_topics_test/help_topics/templates/help-topic-help-test.html.twig new file mode 100644 index 0000000000..65a7a5e86c --- /dev/null +++ b/core/modules/help_topics/tests/modules/help_topics_test/help_topics/templates/help-topic-help-test.html.twig @@ -0,0 +1,2 @@ +{% set help_topic_url = render_var(url('help_topics.help_topic', {id: 'help_topic_writing'})) %} +

{% trans %}This is a test. It should link to the writing good help topic. Also there should be a related topic link below to the Help module topic page and the linked topic.{% endtrans %}

diff --git a/core/modules/help_topics/tests/modules/help_topics_test/help_topics_test.info.yml b/core/modules/help_topics/tests/modules/help_topics_test/help_topics_test.info.yml new file mode 100644 index 0000000000..155c43d565 --- /dev/null +++ b/core/modules/help_topics/tests/modules/help_topics_test/help_topics_test.info.yml @@ -0,0 +1,7 @@ +# The name of this module is deliberately different from its machine +# name to test the presented order of help topics. +name: 'ABC Help Test' +type: module +description: 'Support module for help testing.' +package: Testing +core: 8.x diff --git a/core/modules/help_topics/tests/modules/help_topics_test/help_topics_test.module b/core/modules/help_topics/tests/modules/help_topics_test/help_topics_test.module new file mode 100644 index 0000000000..a6724446cf --- /dev/null +++ b/core/modules/help_topics/tests/modules/help_topics_test/help_topics_test.module @@ -0,0 +1,18 @@ +install(['seven']); + \Drupal::service('config.factory')->getEditable('system.theme')->set('admin', 'seven')->save(); + + // Place various blocks. + $settings = [ + 'theme' => 'seven', + 'region' => 'help', + ]; + $this->placeBlock('help_block', $settings); + $this->placeBlock('local_tasks_block', $settings); + $this->placeBlock('local_actions_block', $settings); + $this->placeBlock('page_title_block', $settings); + + // Create users. + $this->adminUser = $this->createUser([ + 'access administration pages', + 'view the administration theme', + 'administer permissions', + 'view help topics', + ]); + $this->anyUser = $this->createUser([]); + } + + /** + * Tests the main help page and individual pages for topics. + */ + public function testHelp() { + // Log in the regular user. + $this->drupalLogin($this->anyUser); + $this->verifyHelp(403); + + // Log in the admin user. + $this->drupalLogin($this->adminUser); + $this->verifyHelp(); + $this->verifyHelpLinks(); + + // Verify that help topics text appears on admin/help. + $this->drupalGet('admin/help'); + $session = $this->assertSession(); + $session->responseContains('

Topics

'); + $session->pageTextContains('Topics can be provided by modules or themes'); + + // Verify the cache tag for the cache context for user permissions as well + // as the standard URL based ones. + $this->assertCacheContexts(['user.permissions', 'route', 'url.query_args:_wrapper_format']); + + // Verify links for for help topics and order. + $page_text = $this->getTextContent(); + $start = strpos($page_text, 'Topics can be provided'); + $pos = $start; + foreach ($this->getTopicList() as $info) { + $name = $info['name']; + $session->linkExists($name); + $new_pos = strpos($page_text, $name, $start); + $this->assertTrue($new_pos > $pos, 'Order of ' . $name . ' is correct on page'); + $pos = $new_pos; + } + + // Uninstall the test module and verify the topics are gone, after + // reloading page. + $this->container->get('module_installer')->uninstall(['help_topics_test']); + $this->drupalGet('admin/help'); + $session = $this->assertSession(); + $session->linkNotExists('ABC Help Test module'); + $session->linkNotExists('ABC Help Test'); + } + + /** + * Verifies the logged in user has access to various help links and pages. + * + * @param int $response + * (optional) The HTTP response code to test for. If it's 200 (default), + * the test verifies the user sees the help; if it's not, it verifies they + * are denied access. + */ + protected function verifyHelp($response = 200) { + // Verify access to help topic pages. + foreach ($this->getTopicList() as $topic => $info) { + // View help topic page. + $this->drupalGet('admin/help/topic/' . $topic); + $session = $this->assertSession(); + $session->statusCodeEquals($response); + if ($response == 200) { + $name = $info['name']; + $session->titleEquals($name . ' | Drupal'); + $session->responseContains('

' . $name . '

'); + } + } + } + + /** + * Verifies links on the test help topic page and other pages. + * + * Assumes an admin user is logged in. + */ + protected function verifyHelpLinks() { + // Verify links on the test top-level page. + $page = 'admin/help/topic/help_test'; + $links = [ + 'link to the writing good help topic' => 'Writing good help', + 'Linked topic' => 'This topic is not supposed to be top-level', + 'Additional topic' => 'This topic should get listed automatically', + ]; + foreach ($links as $link_text => $page_text) { + $this->drupalGet($page); + $this->clickLink($link_text); + $session = $this->assertSession(); + $session->pageTextContains($page_text); + } + + // Verify that the non-top-level topics do not appear on the Help page. + $this->drupalGet('admin/help'); + $session = $this->assertSession(); + $session->linkNotExists('Linked topic'); + $session->linkNotExists('Additional topic'); + } + + /** + * Gets a list of topic IDs to test. + * + * @return array + * A list of topics to test, in the order in which they should appear. The + * keys are the machine names of the topics. The values are arrays with the + * following elements: + * - name: Displayed name. + * - cache_tags: Cache tags to verify are present on the topic display page. + */ + protected function getTopicList() { + return [ + 'help_test' => [ + 'name' => 'ABC Help Test module', + ], + 'help_topic_writing' => [ + 'name' => 'Writing good help', + ], + ]; + } + +} diff --git a/core/modules/help_topics/tests/src/Kernel/HelpTopicTokensTest.php b/core/modules/help_topics/tests/src/Kernel/HelpTopicTokensTest.php new file mode 100644 index 0000000000..cdf02d0b90 --- /dev/null +++ b/core/modules/help_topics/tests/src/Kernel/HelpTopicTokensTest.php @@ -0,0 +1,87 @@ +installSchema('system', ['router', 'sequences']); + + // Set up as multi-lingual with English and Spanish, so that we can + // test for cache metadata from URL generation. + $this->installConfig(['language']); + $this->installEntitySchema('configurable_language'); + ConfigurableLanguage::create(['id' => 'es'])->save(); + $this + ->config('language.negotiation') + ->set('url.prefixes', [ + 'en' => 'en', + 'es' => 'es', + ]) + ->save(); + \Drupal::service('kernel')->rebuildContainer(); + \Drupal::service('router.builder')->rebuild(); + } + + /** + * Tests that help topic tokens work. + */ + public function testHelpTopicTokens() { + // Verify a URL token for a help topic that is a plugin. + $bubbleable_metadata = new BubbleableMetadata(); + $text = 'This should Link to help topic'; + $replaced = \Drupal::token()->replace($text, [], [], $bubbleable_metadata); + $this->assertTrue(strpos($replaced, 'getCacheContexts(); + $this->assertTrue(in_array('languages:language_url', $contexts, 'Language negotiation cache context was added')); + + // Verify correct URL if we tell the Token system to use Spanish. + $bubbleable_metadata = new BubbleableMetadata(); + $replaced = \Drupal::token()->replace($text, [], ['langcode' => 'es'], $bubbleable_metadata); + $spanish = \Drupal::languageManager()->getLanguage('es'); + $this->assertTrue(strpos($replaced, 'replace($text); + $this->assertTrue(strpos($replaced, '[help_topic:url:nonexistent]') !== FALSE, 'Nonexistent help topic did not get replaced'); + + // Check for cache metadata. It should have a cache context for language + // negotiation and a tag for the text format. + $tags = $bubbleable_metadata->getCacheTags(); + $contexts = $bubbleable_metadata->getCacheContexts(); + $this->assertTrue(in_array('languages:language_url', $contexts, 'Language negotiation cache context was added')); + } + +}