Problem/Motivation

The examples in the API documentation for the menu system say that the "machine name" for e.g. a local action should match that for the route. However:

  1. The API documentation in question doesn't explain what "machine name" means, or is used for, nor do they link to a standard explanation.
  2. It also doesn't explain why e.g. the menu action machine name should be the same as the route name, and what the consequences are if they're not the same (even if it's "a human reading the YAML might get confused or lose track.")
  3. The Routing documentation linked to doesn't explain what "machine name" is either.
  4. The Coding standards don't seem to even mention machine names. If they're discussed in a subpage of the coding standards, it isn't obvious which one (e.g. they're not on Services and extending Symfony.)

Proposed resolution

The API documentation as a whole needs to make clear what "machine name" means, either: with reference other API documentation or a coding standard; or by writing new documentation to clarify.

The API documentation for the menu and routing components (and any other relevant components) needs to make clear why e.g. local action machine names should match route names, and what the consequences are if they don't

Remaining tasks

  1. Either find existing documentation on "machine name", or:
    1. Agree on what is and is not a machine name (allowed characters, namespacing, uniqueness etc.)
    2. Turn that agreement into something easy to read and find a place for it either in Drupal core or on d.o e.g. in the coding standards.
  2. Link to this documentation from Drupal Core's API documentation wherever "machine name" is used (menu, routing - and anywhere else.)
  3. Explain in the menu documentation in Drupal Core why e.g. local action machine names must not only conform to the standard for "machine name", but should also match the route name; and explain what happens if they don't match, if anything.

User interface changes

None.

API changes

None.

Data model changes

None.

Comments

jp.stacey created an issue. See original summary.

cilefen’s picture

There is a form element validator.

/**
   * Form element validation handler for machine_name elements.
   *
   * Note that #maxlength is validated by _form_validate() already.
   *
   * This checks that the submitted value:
   * - Does not contain the replacement character only.
   * - Does not contain disallowed characters.
   * - Is unique; i.e., does not already exist.
   * - Does not exceed the maximum length (via #maxlength).
   * - Cannot be changed after creation (via #disabled).
   */
  public static function validateMachineName(&$element, FormStateInterface $form_state, &$complete_form) {
    // Verify that the machine name not only consists of replacement tokens.
    if (preg_match('@^' . $element['#machine_name']['replace'] . '+$@', $element['#value'])) {
      $form_state->setError($element, t('The machine-readable name must contain unique characters.'));
    }

    // Verify that the machine name contains no disallowed characters.
    if (preg_match('@' . $element['#machine_name']['replace_pattern'] . '@', $element['#value'])) {
      if (!isset($element['#machine_name']['error'])) {
        // Since a hyphen is the most common alternative replacement character,
        // a corresponding validation error message is supported here.
        if ($element['#machine_name']['replace'] == '-') {
          $form_state->setError($element, t('The machine-readable name must contain only lowercase letters, numbers, and hyphens.'));
        }
        // Otherwise, we assume the default (underscore).
        else {
          $form_state->setError($element, t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
        }
      }
      else {
        $form_state->setError($element, $element['#machine_name']['error']);
      }
    }

    // Verify that the machine name is unique.
    if ($element['#default_value'] !== $element['#value']) {
      $function = $element['#machine_name']['exists'];
      if (call_user_func($function, $element['#value'], $element, $form_state)) {
        $form_state->setError($element, t('The machine-readable name is already in use. It must be unique.'));
      }
    }
  }
jp.stacey’s picture

@cilefen thanks for hunting that out: it certainly gives us a framework for how to start describing what a machine name *is*!

There's a lot left unspecifieid within the context of just this method, though:

* the replacement character (it says "usually a hyphen", although I'd have gone for an underscore) for - disallowed characters? I note it doesn't do any replacement itself, just checks that the machine name is not just e.g. "-" or "_"
* the disallowed characters (a pattern can be passed in)

So maybe the phrase "machine name" is context-sensitive, and the docs should instead talk about "YAML machine names" or even "Routing YAML machine names"? I'll dig further and see what code is specifically checking the validation in the context of this particular documentation bug.

jp.stacey’s picture

There appears to be no validation of the machine name (basically $plugin_id) in \Drupal\Core\Menu\LocalTaskManager#processDefinition().

I added weird characters to my own example .links.task.yml keys, to try to fire some kind of error: one key ended up including whitespace and punctuation: test.sub_page_ !"$£$^%^*&^()task.

I then ran a drush cr, added a var_dump in processDefinition(), and refreshed the page.

Result? a load of YAML keys dumped out, including my wacky one above: and no errors. The particular task with the weird key showed up just fine as a tab.

This suggests that, even though the docs specify machine names for YAML keys, the format is not mandatory. So where do we go from here? :)

jp.stacey’s picture

Component: menu system » documentation
Issue tags: -documentation bug +menu, +machine name
jp.stacey’s picture

Another link that @ekes has unearthed:

https://www.drupal.org/docs/7/understanding-drupal/glossary#machine-name

However (a) it's a pretty empty definition when it comes to giving newbies guidance and (b) it doesn't help explain the contextualness of different naming guidelines e.g. why module names shouldn't have dots in them, but route names can and indeed should (dots being an informal namespace separator.)

Ideally we could do with something as unambiguous as we have for nodes or views....

joachim’s picture

In D7 at least, a machine name was something matching /[a-z0-9_]+/, possibly with the additional condition that it not start with a number.

I would be inclined to say that is still true in D8, and that routes have names, not machine names, and configuration has keys, not machine names. (And that those terms need to be clearly explained too.)

It would be interesting to see which uses of that validator allow a hyphen.

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.

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.

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.

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.