/**
  * {@inheritdoc}
  */
 public function save(array $path, $existing_alias = NULL, $op = NULL)
 {
     $config = $this->configFactory->get('pathauto.settings');
     // Alert users if they are trying to create an alias that is the same as the
     // internal path.
     if ($path['source'] == $path['alias']) {
         $this->messenger->addMessage($this->t('Ignoring alias %alias because it is the same as the internal path.', array('%alias' => $path['alias'])));
         return NULL;
     }
     // Skip replacing the current alias with an identical alias.
     if (empty($existing_alias) || $existing_alias['alias'] != $path['alias']) {
         $path += array('pathauto' => TRUE, 'original' => $existing_alias, 'pid' => NULL);
         // If there is already an alias, respect some update actions.
         if (!empty($existing_alias)) {
             switch ($config->get('update_action')) {
                 case PathautoGeneratorInterface::UPDATE_ACTION_NO_NEW:
                     // Do not create the alias.
                     return NULL;
                 case PathautoGeneratorInterface::UPDATE_ACTION_LEAVE:
                     // Create a new alias instead of overwriting the existing by leaving
                     // $path['pid'] empty.
                     break;
                 case PathautoGeneratorInterface::UPDATE_ACTION_DELETE:
                     // The delete actions should overwrite the existing alias.
                     $path['pid'] = $existing_alias['pid'];
                     break;
             }
         }
         // Save the path array.
         $this->aliasStorage->save($path['source'], $path['alias'], $path['language'], $path['pid']);
         if (!empty($existing_alias['pid'])) {
             $this->messenger->addMessage($this->t('Created new alias %alias for %source, replacing %old_alias.', array('%alias' => $path['alias'], '%source' => $path['source'], '%old_alias' => $existing_alias['alias'])));
         } else {
             $this->messenger->addMessage($this->t('Created new alias %alias for %source.', array('%alias' => $path['alias'], '%source' => $path['source'])));
         }
         return $path;
     }
 }
 /**
  * {@inheritdoc}
  */
 public function createAlias($module, $op, $source, $data, $type = NULL, $langcode = LanguageInterface::LANGCODE_NOT_SPECIFIED)
 {
     $config = $this->configFactory->get('pathauto.settings');
     // Retrieve and apply the pattern for this content type.
     $pattern = $this->getPatternByEntity($module, $type, $langcode);
     // Allow other modules to alter the pattern.
     $context = array('module' => $module, 'op' => $op, 'source' => $source, 'data' => $data, 'type' => $type, 'language' => &$langcode);
     $this->moduleHandler->alter('pathauto_pattern', $pattern, $context);
     if (empty($pattern)) {
         // No pattern? Do nothing (otherwise we may blow away existing aliases...)
         return NULL;
     }
     // Special handling when updating an item which is already aliased.
     $existing_alias = NULL;
     if ($op == 'update' || $op == 'bulkupdate') {
         if ($existing_alias = $this->aliasStorageHelper->loadBySource($source, $langcode)) {
             switch ($config->get('update_action')) {
                 case PathautoManagerInterface::UPDATE_ACTION_NO_NEW:
                     // If an alias already exists,
                     // and the update action is set to do nothing,
                     // then gosh-darn it, do nothing.
                     return NULL;
             }
         }
     }
     // Replace any tokens in the pattern.
     // Uses callback option to clean replacements. No sanitization.
     // Pass empty BubbleableMetadata object to explicitly ignore cacheablity,
     // as the result is never rendered.
     $alias = $this->token->replace($pattern, $data, array('clear' => TRUE, 'callback' => array($this->aliasCleaner, 'cleanTokenValues'), 'langcode' => $langcode, 'pathauto' => TRUE), new BubbleableMetadata());
     // Check if the token replacement has not actually replaced any values. If
     // that is the case, then stop because we should not generate an alias.
     // @see token_scan()
     $pattern_tokens_removed = preg_replace('/\\[[^\\s\\]:]*:[^\\s\\]]*\\]/', '', $pattern);
     if ($alias === $pattern_tokens_removed) {
         return NULL;
     }
     $alias = $this->aliasCleaner->cleanAlias($alias);
     // Allow other modules to alter the alias.
     $context['source'] =& $source;
     $context['pattern'] = $pattern;
     $this->moduleHandler->alter('pathauto_alias', $alias, $context);
     // If we have arrived at an empty string, discontinue.
     if (!Unicode::strlen($alias)) {
         return NULL;
     }
     // If the alias already exists, generate a new, hopefully unique, variant.
     $original_alias = $alias;
     $this->aliasUniquifier->uniquify($alias, $source, $langcode);
     if ($original_alias != $alias) {
         // Alert the user why this happened.
         $this->messenger->addMessage($this->t('The automatically generated alias %original_alias conflicted with an existing alias. Alias changed to %alias.', array('%original_alias' => $original_alias, '%alias' => $alias)), $op);
     }
     // Return the generated alias if requested.
     if ($op == 'return') {
         return $alias;
     }
     // Build the new path alias array and send it off to be created.
     $path = array('source' => $source, 'alias' => $alias, 'language' => $langcode);
     return $this->aliasStorageHelper->save($path, $existing_alias, $op);
 }