Updated: Comment #N

Problem/Motivation

There are a couple of problems with how we are doing hook_help() implementations currently in Drupal 8 and all previous versions. Here is a typical implementation:

/**
 * Implements hook_help().
 */
function book_help($path, $arg) {
  switch ($path) {
    case 'admin/help#book':
      $output = '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('The Book module is used for creating structured, multi-page content, such as site resource guides, manuals, and wikis. It allows you to create content that has chapters, sections, subsections, or any similarly-tiered structure. For more information, see the <a href="!book">online documentation for the Book module</a>.', array('!book' => 'https://drupal.org/documentation/modules/book')) . '</p>';
      $output .= '<h3>' . t('Uses') . '</h3>';
      $output .= '<dl>';
      $output .= '<dt>' . t('Adding and managing book content') . '</dt>';
      $output .= '<dd>' . t('You can assign separate permissions for <em>creating new books</em> as well as <em>creating</em>, <em>editing</em> and <em>deleting</em> book content. Users with the <em>Administer book outlines</em> permission can add <em>any</em> type of content to a book by selecting the appropriate book outline while editing the content. They can also view a list of all books, and edit and rearrange section titles on the <a href="!admin-book">Book administration page</a>.', array('!admin-book' => \Drupal::url('book.admin'))) . '</dd>';
      $output .= '<dt>' . t('Book navigation') . '</dt>';
 ...

Here are some problems with the current hook_help() standard, which this issue may be able to fix, and some additional concerns:

  1. Generally, returning HTML markup and text from a PHP function like this is frowned upon. Markup should be in Twig templates instead.
  2. The current syntax is difficult for Documentation writers, who may not be PHP programmers.
  3. Ideally, it would be good to make it easy for people to follow the standard format of "About" / "Uses" (and individual uses items). Note that in some cases, the individual Uses items have more than one paragraph. Currently this is just done in an ad-hoc way (we publish a page that has the standards for how to write hook_help() and hope people follow it).
  4. We need the help text to be translated (which it is currently -- can't lose that).
  5. When translating the individual strings in the current syntax, the context can get lost. However, we also don't want the markup, or any other stuff like Twig directives, to be in the translation strings, and we don't want translated strings to be very long (because fixing a small typo or grammatical error would mean a completely new string for translators to tackle, as opposed to only a small chunk to re-translate). See #1918856-45: Put each module's help into a separate Twig file for details on this subject.
  6. As a note, the help has a lot of links in it, in general. Some go to external URLs and some to within-site pages.

Proposed resolution

There are several possible ways to solve this problem:

0. Since we want to keep translation text chunks relatively small and without markup, would it be possible to use translation context to help group them? [This is probably independent of how the rest of the issues are solved.]

1. We could make a single "standard help" Twig template, which would output the standard About/Uses markup. Then hook_help() could return a renderable array something like this:

return array(
  '#theme' => 'help-standard',
  '#about' => t('The about text goes here'),
  '#uses' => array(
      array(
        '#header' => t('Using this module'),
        '#text' => t('Description here'),
     ),
     array(
       '#header' => t('Doing something else'),
       '#text' => array(t('First paragraph'), t('Second paragraph')),
    ),
);

Presumably if a hook_help() wanted to return something completely different, or add something after the standard About/Uses, they could do something different in their render array.

2. We could put the About/Uses text into some kind of a YML file. Docs writers are already using YML for Tours and it's much easier to deal with than PHP concatenation. Question: If it is a YML config file, what happens when Core has an update and a site already has its help config stored -- would it get updated? And if it is some other type of YML file (not part of the config system), would it be automatically translated and what would that buy us?

3. There's a proposal on #1918856: Put each module's help into a separate Twig file to make each individual hook_help() implementation have its own Twig template.

4. Some kind of README file with Markdown format.

5. There may be other ideas?

Remaining tasks

a) Figure out which idea is the best for documentation writers, module developers, and translators.

b) Implement it in a patch.

User interface changes

None.

API changes

hook_help() would be changed in some way (yet to be determined).

Comments

jhodgdon’s picture

Issue summary: View changes
jhodgdon’s picture

Issue summary: View changes

sorry, syntax in summary problems again

batigolix’s picture

Issue summary: View changes

I added translation problem to list

jhodgdon’s picture

Issue summary: View changes

Rearranged issue summary slightly, with new item added by batigolix.

jhodgdon’s picture

Issue summary: View changes

One more iteration on the translation problem.

batigolix’s picture

This is an example of what a hook_help text could look like in twig

<h3>{{ 'About'|t }}</h3>
  <p>{{ 'The Book module is used for creating structured, multi-page content, such as site resource guides, manuals, and wikis. It allows you to create content that has chapters, sections, subsections, or any similarly-tiered structure. For more information, see the <a href="!book">online documentation for the Book module</a>.'|t({'!book': 'https://drupal.org/documentation/modules/book'}) }}</p>
<h3>{{ 'Uses'|t }}</h3>
  <dl>
    <dt>{{ 'Adding and managing book content'|t }}</dt>
    <dd>{{ 'You can assign separate permissions for <em>creating new books</em> as well as <em>creating</em>, <em>editing</em> and <em>deleting</em> book content. Users with the <em>Administer book outlines</em> permission can add <em>any</em> type of content to a book by selecting the appropriate book outline while editing the content. They can also view a list of all books, and edit and rearrange section titles on the <a href="!admin-book">Book administration page</a>.'t({'!admin-book':url('book.admin')}) }}</dd>;

This example is based on the patch in #32 of #1918856: Put each module's help into a separate Twig file

sun’s picture

I don't think that options 1. (structured standard) and 2. (YAML) in the issue summary would improve the situation in any way. Here's why:

  1. While core can make some level of assumptions of what is sensible and may be best to document for a module, it cannot unilaterally apply these assumptions to all contrib and custom modules. Just because the About/Uses structure happens to work for core modules doesn't mean that it works for any kind of module.

    By restricting the sections to the assumptions, (1) Help module would cease to work and be suitable for some modules and (2) such a hard-coded structure would prevent everyone from thinking out of the box and "doing better."

  2. YAML files are reserved for static and declarative information. YAML is not an interpreted/scripted language format, it's a data serialization format. Due to that, the problem of establishing context, formatting output, as well as producing conditional and dynamic output will only (substantially) increase.

    → The moment we start to turn YAML into an interpreted/scripted language, we have a serious architectural/technical misunderstanding.

    I can only guess/hope that the current Tour plugins are acceptable, because the actual tips are (hopefully) just raw text strings without any further script-alike processing. (If that is not the case, then the definition/provision of Tour plugins has to be re-architected from scratch.)

In addition, I'd like to point out that the proclaimed goal and/or problem statement of "Get rid of hard-coded markup" in the issue title is not something I'd agree with:

→ Part of the whole point of #1918856: Put each module's help into a separate Twig file is that manually producing exactly the HTML template/markup that you want and need is actually a good fit for the main module help pages.

Yes, you could produce more or less the same output via render arrays, but why?

In an ideal world, we should end up with a "DX" that is identical to simply writing a README.[txt|md] file. Because that's what most module authors do anyway already.

larowlan’s picture

I can only guess/hope that the current Tour plugins are acceptable, because the actual tips are (hopefully) just raw text strings without any further script-alike processing. (If that is not the case, then the definition/provision of Tour plugins has to be re-architected from scratch.)

Yep, rest-assured - Tours hold a plugin bag containing Tip plugins.
There is only one tip-plugin in core, which provides text - and expects a body of text. The plugin does parse the body for tokens, so supports our defacto 'dynamic values in a large chunk of text' functionality. But this is why Tour fits the 'static declaration' requirement for Yaml.
There is an image plugin in tests, just to test that plugins work as expected.
I've also seen Youtube plugins built as a proof of concept.
So the tip-architecture is no different to any other plugin-bag in core, if you need something funky, you write a new tip plugin, the configuration matches what you need, and the plugin handles generating the output. This maintains the 'static declaration' requirement, as each plugin declares configuration for what it needs for its output, and the Yaml only defines this configuration, same as any other plugin bag/config entity pair in core.

Back to the topic at hand, I think #6 is a) better than what we have now and b) keeps translators happy. But I think those who write help frequently need to be happy before we move further.

jhodgdon’s picture

Regarding option #1 in the issue summary, the idea is to have hook_help() return a render array, which is (I think) what most functions that return text and markup are supposed to return in Drupal, right?

If a module developer wants to use the Core standard format, they can use the (proposed) core standard help theme function in their render array.

If they want to do something else, they can do something else -- either return a string with markup in a #markup element, or define their own theme template, or whatever. I think that is a good tradeoff -- still flexible enough but also providing the guidance of the standard structure for people who want to follow it.

Either way... returning a render array is something we normally do in core, and it seems like a good practice for hook_help() to follow?

jhodgdon’s picture

Also option #1 does not prevent any module that wants to to define their own completely custom theme template and using it in their module (see comment #6 for an example).

lostkangaroo’s picture

#8 Wouldn't that require a dependency for the help module to tour to view help texts?

The things that would make me happy and I am sure many others including contrib maintainers regarding these help texts are pretty simple. Remove markup from the actual text so that a template can be used to handle the output.

**Major Pain Point Alert** In doing this, make help texts available when a module is not enabled. If this text is to function as a readme it just makes sense to allow it to be viewed at any time, enabled or not requiring a decoupled approach for the help module towards .module files. Hook_help should have died along time ago due to this limitation. YML could be used to do its intended purpose to configure, in this case templates to routes.

batigolix’s picture

In the hook_help() implementations in the various core modules you find:

  1. Long text (average 250 words (rough estimate)) explaining the general purpose and the usage of the module to site-builders. These texts could be considered readme files for core modules. It is available via admin/help (if help module is enabled)
  2. Short texts (average 1.5 sentence) giving additional information about a particular page. This is displayed in the system help block (if help & block are enabled) which is often located somewhere between the title and the content

I think the short help texts (2) are not the issue here, neither is killing hook_help. The short hook_help texts are a useful addition on admin pages whose UI may not be obvious to new users.

The long help texts (1) are written for Site builders. They only explain the UI. If these texts were to become readme (txt,md,twig,yml) files then the audience might be extended (to developers) as well. This isn't necessarily a problem but it can cause the content of the help text to expand and shift.

From an author's point of view a text or markdown file would be the most comfortable. Currently both the php and html formatting disturbs a normal authoring flow when editing long help texts. Using Twig templates for help texts would only solve this problem partially: it cures concatenation madness, but it introduces bracket chaos.

I dont think we need to worry about conditional blocks ({% if has_node %}bla bla{%endif}) in the help texts as demonstrated in this comment. It is very uncommon to encounter such code inside help texts.

URLs on the other hand are very common in help texts. I'm not sure if is required use tokens and \Drupal::url() to print links. I suppose this done to make strings easier to translate?

The main concern when changing the format of the text should be to keep it translatable.

larowlan’s picture

No reason we couldn't use the token api for links, the main reason is so that urls resolve, ie we can't assume /admin cause someone might install in /drupal but the [site:url] token would fix that

bill richardson’s picture

Why not move help files to drupal.org ( More detailed instructions, captured images of the screens or even video explaining how to use the different modules,etc could be provided ).
A simple help button could be at top of admin pages that would take you to the detail page of the page that you are working on ( eg. How to create an article when on the create article page ).

jhodgdon’s picture

Thanks for the suggestion! However, there are several reasons we do not want to do that. The main one is that hook_help() is in Drupal, which is translated into roughly 160 languages. Drupal.org is only in English. So we need to have the help text within Drupal so it can appear in the user's own language, rather than only providing links to an English-language site. The links could also be localized I suppose to point to a site in another language, but they don't necessarily have the quantity of documentation that is on drupal.org.

Another reason is that not everyone has Internet access available -- you can perfectly well run Drupal on a local server while not being connected to the Internet. So our usual policy is that all necessary help (at least the basics) should be provided in what you download from Drupal.org, so that you can get this vital information without a later Internet link.

ram4nd’s picture

Assigned: Unassigned » ram4nd
ram4nd’s picture

Assigned: ram4nd » Unassigned
jhodgdon’s picture

I've filed a new meta issue to collect all the problems with the current help system and discuss the best route to fixing them; this issue is being added as Related there, and all of its concerns are listed in the Problem/Motivation section:
#2592487: [meta] Help system overhaul

jhodgdon’s picture

There are two approaches in two separate issues that are being discussed now. Both would allow us to get rid of the hard-coded markup in hook_help() implementations. Adding them as Related.

We will hopefully get one of these two approaches into Core for 8.2.x. If you prefer one or the other, please comment there. The plugin approach also has a patch that needs review.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

andypost’s picture

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Status: Active » Postponed (maintainer needs more info)

With help transition to help topics is this issue still relevant?

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

andypost’s picture

I think it could be closed as duplicate of #3031642: Deprecate hook_help() and combine with Topics

But it looks more like duplicate of #2698035: Add markdown system for HTML-formatted text

PS: we have docs gate for core and before we can deprecate help it needs policy issue

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.