diff -u b/core/modules/help_topics/help_topics.module b/core/modules/help_topics/help_topics.module --- b/core/modules/help_topics/help_topics.module +++ b/core/modules/help_topics/help_topics.module @@ -22,7 +22,7 @@ $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. The content of the topic is contained in a matching Twig file in help_topics/templates. 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("Modules and themes can provide help topics as Twig-file-based plugins in a project sub-directory called help_topics. 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')) ? Url::fromRoute('help.page', ['name' => 'locale'])->toString() : '#']) . '
'; $output .= ''; diff -u b/core/modules/help_topics/src/HelpTopicDiscovery.php b/core/modules/help_topics/src/HelpTopicDiscovery.php --- b/core/modules/help_topics/src/HelpTopicDiscovery.php +++ b/core/modules/help_topics/src/HelpTopicDiscovery.php @@ -10,7 +10,15 @@ use Drupal\Core\StringTranslation\TranslatableMarkup; /** - * Discovers help topic plugins from twig templates in help_topics directories. + * Discovers help topic plugins from Twig files in help_topics directories. + * + * @see \Drupal\help_topics\HelpTopicTwig + * @see \Drupal\help_topics\HelpTopicTwigLoader + * + * @internal + * Help Topic is currently experimental and should only be leveraged by + * experimental modules and development releases of contributed modules. + * See https://www.drupal.org/core/experimental for more information. */ class HelpTopicDiscovery implements DiscoveryInterface { @@ -91,11 +99,12 @@ // '.html.twig' is removed 'id' => substr(basename($file), 0, -10), 'provider' => $provider, + 'class' => HelpTopicTwig::class, static::FILE_KEY => $file, ]; // Get the rest of the plugin definition from meta tags contained in the - // help topic twig template. + // help topic Twig file. foreach (get_meta_tags($file) as $key => $value) { $key = substr($key, 11); switch ($key) { @@ -112,6 +121,9 @@ throw new DiscoveryException("The $file contains invalid meta tag with name='$key'"); } } + if (!isset($data['label'])) { + throw new DiscoveryException("The $file contains does not contain the required meta tag with name='label'"); + } $all[$provider][$data['id']] = $data; $file_cache->set($file, $data); diff -u b/core/modules/help_topics/src/HelpTopicPluginInterface.php b/core/modules/help_topics/src/HelpTopicPluginInterface.php --- b/core/modules/help_topics/src/HelpTopicPluginInterface.php +++ b/core/modules/help_topics/src/HelpTopicPluginInterface.php @@ -9,11 +9,7 @@ /** * Defines an interface for help topic plugin classes. * - * Help topics can be created by adding a help_topics folder to your module. - * Each help topic has a {topic_id}.help_topic.yml file. The default - * implementation relies on a corresponding Twig template. - * - * @see \Drupal\help_topics\HelpTopicTwig + * @see \Drupal\help_topics\HelpTopicPluginManager * * @internal * Help Topic is currently experimental and should only be leveraged by diff -u b/core/modules/help_topics/src/HelpTopicPluginManager.php b/core/modules/help_topics/src/HelpTopicPluginManager.php --- b/core/modules/help_topics/src/HelpTopicPluginManager.php +++ b/core/modules/help_topics/src/HelpTopicPluginManager.php @@ -10,11 +10,30 @@ /** * Provides the default help_topic manager. * - * Modules and themes can provide help topics in YAML files called - * name_of_topic.help_topic.yml inside the module or theme sub-directory + * Modules and themes can provide help topics in .html.twig files called + * name-of-topic.help_topic.html.twig inside the module or theme sub-directory * help_topics. * + * The Twig file must contain a meta tag named 'help_topic:label'. It can also + * contain meta tags named 'help_topic:top_level' and 'help_topic:related'. For + * example: + * @code + * + * + * + * + * + * + * + * + * @endcode + * + * @see \Drupal\help_topics\HelpTopicDiscovery * @see \Drupal\help_topics\HelpTopicTwig + * @see \Drupal\help_topics\HelpTopicTwigLoader + * @see \Drupal\help_topics\HelpTopicPluginInterface + * @see \Drupal\help_topics\HelpTopicPluginBase + * @see hook_help_topics_info_alter() * * @internal * Help Topic is currently experimental and should only be leveraged by @@ -29,7 +48,7 @@ * @var array */ protected $defaults = [ - // The plugin ID. Set by the plugin system based on the top-level YAML key. + // The plugin ID. 'id' => '', // The title of the help topic plugin. 'label' => '', @@ -37,7 +56,8 @@ 'top_level' => '', // List of related topic machine names. 'related' => [], - 'class' => HelpTopicTwig::class, + // The class used to instantiate the plugin. + 'class' => '', 'cache_tag' => '', ]; @@ -59,6 +79,8 @@ * Cache backend instance to use. */ public function __construct(ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler, CacheBackendInterface $cache_backend) { + // Note that the parent construct is not called because this not use + // annotated class discovery. $this->moduleHandler = $module_handler; $this->themeHandler = $theme_handler; $this->alterInfo('help_topics_info'); @@ -91,7 +113,7 @@ } /** - * Checks to see if plugin is provided by an uninstalled module or theme. + * {@inheritdoc} */ public function alterDefinitions(&$definitions) { parent::alterDefinitions($definitions); @@ -105,7 +127,8 @@ unset($definitions[$plugin_id]['related'][$key]); continue; } - // Ensure that the other plugin is related to this ID. + // Ensures that related topics are bi-directional. That is, ensures the + // other plugin is related to this one. if (isset($definitions[$related_id]) && !in_array($plugin_id, $definitions[$related_id]['related'], TRUE)) { $definitions[$related_id]['related'][] = $plugin_id; } diff -u b/core/modules/help_topics/src/HelpTopicTwig.php b/core/modules/help_topics/src/HelpTopicTwig.php --- b/core/modules/help_topics/src/HelpTopicTwig.php +++ b/core/modules/help_topics/src/HelpTopicTwig.php @@ -6,15 +6,10 @@ use Symfony\Component\DependencyInjection\ContainerInterface; /** - * Represents a help topic plugin whose definition comes from a YAML file. + * Represents a help topic plugin whose definition comes from a Twig file. * - * The YAML files are stored in subdirectory help_topics, and must be named - * id.help_topic.yaml, where id is the plugin ID. Each YAML file has a - * corresponding Twig template inside help_topics/templates. The Twig file - * should be named help-topic-{topic-id}.html.twig, where {topic-id} is the - * topic ID used in the YAML file, with the underscores swapped for hyphens. - * For example: help_topics/basic_pages.help_topic.yml would have a - * corresponding help_topics/templates/help-topic-basic-pages.html.twig. + * @see \Drupal\help_topics\HelpTopicDiscovery + * @see \Drupal\help_topics\HelpTopicTwigLoader * * @internal * Help Topic is currently experimental and should only be leveraged by @@ -41,6 +36,8 @@ * The plugin implementation definition. * @param \Drupal\help_topics\HelpTopicPluginManagerInterface $plugin_manager * The help topic plugin manager. + * @param \Drupal\Core\Template\TwigEnvironment $twig + * The Twig environment. */ public function __construct(array $configuration, $plugin_id, $plugin_definition, HelpTopicPluginManagerInterface $plugin_manager, TwigEnvironment $twig) { parent::__construct($configuration, $plugin_id, $plugin_definition, $plugin_manager); diff -u b/core/modules/help_topics/src/HelpTopicTwigLoader.php b/core/modules/help_topics/src/HelpTopicTwigLoader.php --- b/core/modules/help_topics/src/HelpTopicTwigLoader.php +++ b/core/modules/help_topics/src/HelpTopicTwigLoader.php @@ -6,12 +6,14 @@ use Drupal\Core\Extension\ThemeHandlerInterface; /** - * Loads help topic templates from the filesystem. + * Loads help topic Twig files from the filesystem. * * This loader adds module and theme help topic paths to a help_topics namespace - * to the Twig filesystem loader so that help_topics can be referenced, like + * to the Twig filesystem loader so that help_topics can be referenced, using + * '@help-topic/pluginId.html.twig'. * - * @help-topic/config-basic.html.twig + * @see \Drupal\help_topics\HelpTopicDiscovery + * @see \Drupal\help_topics\HelpTopicTwig * * @internal * Help Topic is currently experimental and should only be leveraged by @@ -37,23 +39,23 @@ */ public function __construct($root_path, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) { parent::__construct([], $root_path); - // Add help_topics namespaced paths for modules and themes. - foreach ($module_handler->getModuleList() as $name => $extension) { - $this->addPath($extension->getPath() . '/help_topics'); - } - foreach ($theme_handler->listInfo() as $name => $extension) { - $this->addPath($extension->getPath() . '/help_topics'); - } - + // Add help_topics directories for modules and themes in the 'help_topic' + // namespace. + array_map([$this, 'addExtension'], $module_handler->getModuleDirectories()); + array_map([$this, 'addExtension'], $theme_handler->getThemeDirectories()); } /** - * {@inheritdoc} + * Adds an extensions help_topics directory to the Twig loader. + * + * @param $path + * The path to the extension. */ - public function addPath($path, $namespace = self::MAIN_NAMESPACE) { + protected function addExtension($path) { + $path .= DIRECTORY_SEPARATOR . 'help_topics'; if (is_dir($path)) { $this->cache = $this->errorCache = []; - $this->paths[$namespace][] = rtrim($path, '/\\'); + $this->paths[self::MAIN_NAMESPACE][] = rtrim($path, '/\\'); } } diff -u b/core/modules/help_topics/tests/src/Functional/HelpTopicTest.php b/core/modules/help_topics/tests/src/Functional/HelpTopicTest.php --- b/core/modules/help_topics/tests/src/Functional/HelpTopicTest.php +++ b/core/modules/help_topics/tests/src/Functional/HelpTopicTest.php @@ -170,7 +170,7 @@ $this->drupalGet('admin/help/topic/help-test-theme'); $session->pageTextContains('This is a theme provided topic.'); $this->clickLink('Additional topic'); - $this->assertLink('XYZ Help Test theme'); + $session->linkExists('XYZ Help Test theme'); // Verify that the non-top-level topics do not appear on the Help page. $this->drupalGet('admin/help'); only in patch2: unchanged: --- /dev/null +++ b/core/modules/help_topics/help_topics.api.php @@ -0,0 +1,25 @@ +