aliasStorage = $alias_storage; $this->aliasManager = $alias_manager; $this->pathValidator = $path_validator; $this->requestContext = $request_context; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('path.alias_storage'), $container->get('path.alias_manager'), $container->get('path.validator'), $container->get('router.request_context') ); } /** * Builds the path used by the form. * * @param int|null $pid * Either the unique path ID, or NULL if a new one is being created. */ abstract protected function buildPath($pid); /** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, $pid = NULL) { $this->path = $this->buildPath($pid); $form['source'] = [ '#type' => 'textfield', '#title' => $this->t('Existing system path'), '#default_value' => $this->path['source'], '#maxlength' => 255, '#size' => 45, '#description' => $this->t('Specify the existing path you wish to alias. For example: /node/28, /forum/1, /taxonomy/term/1.'), '#field_prefix' => $this->requestContext->getCompleteBaseUrl(), '#required' => TRUE, ]; $form['alias'] = [ '#type' => 'textfield', '#title' => $this->t('Path alias'), '#default_value' => $this->path['alias'], '#maxlength' => 255, '#size' => 45, '#description' => $this->t('Specify an alternative path by which this data can be accessed. For example, type "/about" when writing an about page.'), '#field_prefix' => $this->requestContext->getCompleteBaseUrl(), '#required' => TRUE, ]; // A hidden value unless language.module is enabled. if (\Drupal::moduleHandler()->moduleExists('language')) { $languages = \Drupal::languageManager()->getLanguages(); $language_options = []; foreach ($languages as $langcode => $language) { $language_options[$langcode] = $language->getName(); } $form['langcode'] = [ '#type' => 'select', '#title' => $this->t('Language'), '#options' => $language_options, '#empty_value' => LanguageInterface::LANGCODE_NOT_SPECIFIED, '#empty_option' => $this->t('- None -'), '#default_value' => $this->path['langcode'], '#weight' => -10, '#description' => $this->t('A path alias set for a specific language will always be used when displaying this page in that language, and takes precedence over path aliases set as - None -.'), ]; } else { $form['langcode'] = [ '#type' => 'value', '#value' => $this->path['langcode'] ]; } $form['actions'] = ['#type' => 'actions']; $form['actions']['submit'] = [ '#type' => 'submit', '#value' => $this->t('Save'), '#button_type' => 'primary', ]; return $form; } /** * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { $source = &$form_state->getValue('source'); $source = $this->aliasManager->getPathByAlias($source); $alias = &$form_state->getValue('alias'); // Trim the submitted value of whitespace and slashes. Ensure to not trim // the slash on the left side. $alias = rtrim(trim(trim($alias), ''), "\\/"); if ($source[0] !== '/') { $form_state->setErrorByName('source', 'The source path has to start with a slash.'); } if ($alias[0] !== '/') { $form_state->setErrorByName('alias', 'The alias path has to start with a slash.'); } // Language is only set if language.module is enabled, otherwise save for all // languages. $langcode = $form_state->getValue('langcode', LanguageInterface::LANGCODE_NOT_SPECIFIED); if ($this->aliasStorage->aliasExists($alias, $langcode, $this->path['source'])) { $stored_alias = $this->aliasStorage->load(['alias' => $alias, 'langcode' => $langcode]); if ($stored_alias['alias'] !== $alias) { // The alias already exists with different capitalization as the default // implementation of AliasStorageInterface::aliasExists is // case-insensitive. $form_state->setErrorByName('alias', t('The alias %alias could not be added because it is already in use in this language with different capitalization: %stored_alias.', [ '%alias' => $alias, '%stored_alias' => $stored_alias['alias'], ])); } else { $form_state->setErrorByName('alias', t('The alias %alias is already in use in this language.', ['%alias' => $alias])); } } if (!$this->pathValidator->isValid(trim($source, '/'))) { $form_state->setErrorByName('source', t("Either the path '@link_path' is invalid or you do not have access to it.", ['@link_path' => $source])); } } /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { // Remove unnecessary values. $form_state->cleanValues(); $pid = $form_state->getValue('pid', 0); $source = $form_state->getValue('source'); $alias = $form_state->getValue('alias'); // Language is only set if language.module is enabled, otherwise save for all // languages. $langcode = $form_state->getValue('langcode', LanguageInterface::LANGCODE_NOT_SPECIFIED); $this->aliasStorage->save($source, $alias, $langcode, $pid); $this->messenger()->addStatus($this->t('The alias has been saved.')); $form_state->setRedirect('path.admin_overview'); } }