Score:1

Example hook_pathauto_pattern_alter

cn flag

I do not understand the hook. I would expect, that "pattern_alter" would allow me to "alter" the "pattern". But this seems to be not the case.

I tried also to alter the alias... which also does not seem to have an effect.

Could somebody show me a working example please?

function xxx_pathauto_pattern_alter(\Drupal\pathauto\PathautoPatternInterface &$pattern, array $context) {

  /* //////////////////////////////////////////////////////////////////////////////////
  ////    article_type - override path logic for *archived* nodes ('/archiv/[node::title]')
  /* ///////////////////////////////////////////////////////////////////////////////////*/
  if( $context['op'] === "update" && $context['bundle'] === "news") {

    $node = $context['data']['node'];
    $archived = $node->get('field_archived')->getString() === "1";
    if ($archived) {

      $pattern->setPattern('/archive/[node::title]');
      dpm($pattern); //WORKS !!! in object only. Pattern will not change in real world.
    }
  }
}

function xxx_pathauto_alias_alter(&$alias, array &$context) {
  /* //////////////////////////////////////////////////////////////////////////////////
    ////    article_type - override path logic for *archived* nodes ('/archive/[node::title]')
    /* ///////////////////////////////////////////////////////////////////////////////////*/
  if ($context['op'] === "update" && $context['bundle'] === "news") {

    $node = $context['data']['node'];
    $archived = $node->get('field_archived')->getString() === "1";
    if ($archived) {
      $alias = "/archive/nope";
      dpm($alias); //WORKS !!! in function only. Alias will not change in real world.
    }
  }
Score:2
us flag

hook_pathauto_pattern_alter() is only invoked when:

  • The entity has a path field
  • Pathauto processing is enabled
  • For entities that support revisions, the entity is using the default revision
  • A default pattern has been set for that entity
  • $entity->toUrl()->getInternalPath() doesn't throw a EntityMalformedException, UndefinedLinkTemplateException, or UnexpectedValueException exception

The shown hook is also only invoked when an entity is updated, not when an entity is created.
When the Pathauto module has been set not to change an existing path alias, even if hook_pathauto_pattern_alter() were invoked, the path alias wouldn't be changed.

As side note, the hook could should first check the entity for which the hook is invoked is a node, which is what the example hook in pathauto.api.php does.

/**
 * Alter the pattern to be used before an alias is generated by Pathauto.
 *
 * This hook will only be called if a default pattern is configured (on
 * admin/config/search/path/patterns).
 *
 * @param \Drupal\pathauto\PathautoPatternInterface $pattern
 *   The Pathauto pattern to be used.
 * @param array $context
 *   An associative array of additional options, with the following elements:
 *   - 'module': The module or entity type being aliased.
 *   - 'op': A string with the operation being performed on the object being
 *     aliased. Can be either 'insert', 'update', 'return', or 'bulkupdate'.
 *   - 'source': A string of the source path for the alias (e.g. 'node/1').
 *   - 'data': An array of keyed objects to pass to token_replace().
 *   - 'bundle': The sub-type or bundle of the object being aliased.
 *   - 'language': A string of the language code for the alias (e.g. 'en').
 *     This can be altered by reference.
 */
function hook_pathauto_pattern_alter(\Drupal\pathauto\PathautoPatternInterface $pattern, array $context) {
  // Switch out any [node:created:*] tokens with [node:updated:*] on update.
  if ($context['module'] == 'node' && ($context['op'] == 'update')) {
    $pattern->setPattern(preg_replace('/\[node:created(\:[^]]*)?\]/', '[node:updated$1]', $pattern->getPattern()));
  }
}

The code for the shown hook would be similar to the following one.


use Drupal\pathauto\PathautoPatternInterface;

function mymodule_pathauto_pattern_alter(PathautoPatternInterface $pattern, array $context) {
  if ($context['module'] == 'node' && $context['op'] === "update" && $context['bundle'] === "news") {
    $node = $context['data']['node'];
    $archived = $node->get('field_archived')->getString() === "1";
    if ($archived) {
      $pattern->setPattern('/archive/[node::title]');
    }
  }
}

Objects are already passed by reference; it's not necessary to define the first parameter as &$pattern.

I would also verify there aren't other modules implementing hook_pathauto_pattern_alter() for which their implementation is invoked after the implementation shown in the question, and that is altering the pattern for the same entity and the same bundle.

References

mogio avatar
cn flag
Apaderno. Thanks for your long and detailed answer! .. seems to work!
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.