3 namespace Drupal\path\Form;
5 use Drupal\Core\Form\FormBase;
6 use Drupal\Core\Form\FormStateInterface;
7 use Drupal\Core\Language\LanguageInterface;
8 use Drupal\Core\Path\AliasManagerInterface;
9 use Drupal\Core\Path\AliasStorageInterface;
10 use Drupal\Core\Path\PathValidatorInterface;
11 use Drupal\Core\Routing\RequestContext;
12 use Symfony\Component\DependencyInjection\ContainerInterface;
15 * Provides a base class for path add/edit forms.
17 abstract class PathFormBase extends FormBase {
20 * An array containing the path ID, source, alias, and language code.
27 * The path alias storage.
29 * @var \Drupal\Core\Path\AliasStorageInterface
31 protected $aliasStorage;
34 * The path alias manager.
36 * @var \Drupal\Core\Path\AliasManagerInterface
38 protected $aliasManager;
43 * @var \Drupal\Core\Path\PathValidatorInterface
45 protected $pathValidator;
48 * The request context.
50 * @var \Drupal\Core\Routing\RequestContext
52 protected $requestContext;
55 * Constructs a new PathController.
57 * @param \Drupal\Core\Path\AliasStorageInterface $alias_storage
58 * The path alias storage.
59 * @param \Drupal\Core\Path\AliasManagerInterface $alias_manager
60 * The path alias manager.
61 * @param \Drupal\Core\Path\PathValidatorInterface $path_validator
63 * @param \Drupal\Core\Routing\RequestContext $request_context
64 * The request context.
66 public function __construct(AliasStorageInterface $alias_storage, AliasManagerInterface $alias_manager, PathValidatorInterface $path_validator, RequestContext $request_context) {
67 $this->aliasStorage = $alias_storage;
68 $this->aliasManager = $alias_manager;
69 $this->pathValidator = $path_validator;
70 $this->requestContext = $request_context;
76 public static function create(ContainerInterface $container) {
78 $container->get('path.alias_storage'),
79 $container->get('path.alias_manager'),
80 $container->get('path.validator'),
81 $container->get('router.request_context')
86 * Builds the path used by the form.
88 * @param int|null $pid
89 * Either the unique path ID, or NULL if a new one is being created.
91 abstract protected function buildPath($pid);
96 public function buildForm(array $form, FormStateInterface $form_state, $pid = NULL) {
97 $this->path = $this->buildPath($pid);
99 '#type' => 'textfield',
100 '#title' => $this->t('Existing system path'),
101 '#default_value' => $this->path['source'],
104 '#description' => $this->t('Specify the existing path you wish to alias. For example: /node/28, /forum/1, /taxonomy/term/1.'),
105 '#field_prefix' => $this->requestContext->getCompleteBaseUrl(),
109 '#type' => 'textfield',
110 '#title' => $this->t('Path alias'),
111 '#default_value' => $this->path['alias'],
114 '#description' => $this->t('Specify an alternative path by which this data can be accessed. For example, type "/about" when writing an about page.'),
115 '#field_prefix' => $this->requestContext->getCompleteBaseUrl(),
119 // A hidden value unless language.module is enabled.
120 if (\Drupal::moduleHandler()->moduleExists('language')) {
121 $languages = \Drupal::languageManager()->getLanguages();
122 $language_options = [];
123 foreach ($languages as $langcode => $language) {
124 $language_options[$langcode] = $language->getName();
127 $form['langcode'] = [
129 '#title' => $this->t('Language'),
130 '#options' => $language_options,
131 '#empty_value' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
132 '#empty_option' => $this->t('- None -'),
133 '#default_value' => $this->path['langcode'],
135 '#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 <em>- None -</em>.'),
139 $form['langcode'] = [
141 '#value' => $this->path['langcode']
145 $form['actions'] = ['#type' => 'actions'];
146 $form['actions']['submit'] = [
148 '#value' => $this->t('Save'),
149 '#button_type' => 'primary',
158 public function validateForm(array &$form, FormStateInterface $form_state) {
159 $source = &$form_state->getValue('source');
160 $source = $this->aliasManager->getPathByAlias($source);
161 $alias = &$form_state->getValue('alias');
163 // Trim the submitted value of whitespace and slashes. Ensure to not trim
164 // the slash on the left side.
165 $alias = rtrim(trim(trim($alias), ''), "\\/");
167 if ($source[0] !== '/') {
168 $form_state->setErrorByName('source', 'The source path has to start with a slash.');
170 if ($alias[0] !== '/') {
171 $form_state->setErrorByName('alias', 'The alias path has to start with a slash.');
174 // Language is only set if language.module is enabled, otherwise save for all
176 $langcode = $form_state->getValue('langcode', LanguageInterface::LANGCODE_NOT_SPECIFIED);
178 if ($this->aliasStorage->aliasExists($alias, $langcode, $this->path['source'])) {
179 $stored_alias = $this->aliasStorage->load(['alias' => $alias, 'langcode' => $langcode]);
180 if ($stored_alias['alias'] !== $alias) {
181 // The alias already exists with different capitalization as the default
182 // implementation of AliasStorageInterface::aliasExists is
184 $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.', [
186 '%stored_alias' => $stored_alias['alias'],
190 $form_state->setErrorByName('alias', t('The alias %alias is already in use in this language.', ['%alias' => $alias]));
194 if (!$this->pathValidator->isValid(trim($source, '/'))) {
195 $form_state->setErrorByName('source', t("Either the path '@link_path' is invalid or you do not have access to it.", ['@link_path' => $source]));
202 public function submitForm(array &$form, FormStateInterface $form_state) {
203 // Remove unnecessary values.
204 $form_state->cleanValues();
206 $pid = $form_state->getValue('pid', 0);
207 $source = $form_state->getValue('source');
208 $alias = $form_state->getValue('alias');
209 // Language is only set if language.module is enabled, otherwise save for all
211 $langcode = $form_state->getValue('langcode', LanguageInterface::LANGCODE_NOT_SPECIFIED);
213 $this->aliasStorage->save($source, $alias, $langcode, $pid);
215 drupal_set_message($this->t('The alias has been saved.'));
216 $form_state->setRedirect('path.admin_overview');