Issue #1393846 by tedbow, Albert Volkman: Fixed path_form_element_validate() executes...
[project/drupal.git] / modules / path / path.module
CommitLineData
2ba974d2 1<?php
2ba974d2
SW
2
3/**
4 * @file
5 * Enables users to rename URLs.
6 */
7
8/**
1da26fad 9 * Implements hook_help().
2ba974d2 10 */
9e6ef53c
H
11function path_help($path, $arg) {
12 switch ($path) {
2ba974d2 13 case 'admin/help#path':
88df1738
AB
14 $output = '';
15 $output .= '<h3>' . t('About') . '</h3>';
28714aa3 16 $output .= '<p>' . t('The Path module allows you to specify an alias, or custom URL, for any existing internal system path. Aliases should not be confused with URL redirects, which allow you to forward a changed or inactive URL to a new URL. In addition to making URLs more readable, aliases also help search engines index content more effectively. Multiple aliases may be used for a single internal system path. To automate the aliasing of paths, you can install the contributed module <a href="@pathauto">Pathauto</a>. For more information, see the online handbook entry for the <a href="@path">Path module</a>.', array('@path' => 'http://drupal.org/handbook/modules/path', '@pathauto' => 'http://drupal.org/project/pathauto')) . '</p>';
88df1738
AB
17 $output .= '<h3>' . t('Uses') . '</h3>';
18 $output .= '<dl>';
19 $output .= '<dt>' . t('Creating aliases') . '</dt>';
92ad4274 20 $output .= '<dd>' . t('Users with sufficient <a href="@permissions">permissions</a> can create aliases under the <em>URL path settings</em> section when they create or edit content. Some examples of aliases are: ', array('@permissions' => url('admin/people/permissions', array('fragment' => 'module-path'))));
88df1738
AB
21 $output .= '<ul><li>' . t('<em>member/jane-smith</em> aliased to internal path <em>user/123</em>') . '</li>';
22 $output .= '<li>' . t('<em>about-us/team</em> aliased to internal path <em>node/456</em>') . '</li>';
23 $output .= '</ul></dd>';
24 $output .= '<dt>' . t('Managing aliases') . '</dt>';
28714aa3 25 $output .= '<dd>' . t('The Path module provides a way to search and view a <a href="@aliases">list of all aliases</a> that are in use on your website. Aliases can be added, edited and deleted through this list.', array('@aliases' => url('admin/config/search/path'))) . '</dd>';
88df1738 26 $output .= '</dl>';
2ba974d2 27 return $output;
0fa300a6 28
43db68b6 29 case 'admin/config/search/path':
d3c9cbfc 30 return '<p>' . t("An alias defines a different name for an existing URL path - for example, the alias 'about' for the URL path 'node/1'. A URL path can have multiple aliases.") . '</p>';
0fa300a6 31
43db68b6 32 case 'admin/config/search/path/add':
56d2664a 33 return '<p>' . t('Enter the path you wish to create the alias for, followed by the name of the new alias.') . '</p>';
2ba974d2
SW
34 }
35}
36
37/**
1da26fad 38 * Implements hook_permission().
0fa300a6
DB
39 */
40function path_permission() {
41 return array(
42 'administer url aliases' => array(
43 'title' => t('Administer URL aliases'),
0fa300a6
DB
44 ),
45 'create url aliases' => array(
29368b46 46 'title' => t('Create and edit URL aliases'),
0fa300a6
DB
47 ),
48 );
49}
50
51/**
1da26fad 52 * Implements hook_menu().
2ba974d2 53 */
03752e35 54function path_menu() {
43db68b6 55 $items['admin/config/search/path'] = array(
7d4f2836
DB
56 'title' => 'URL aliases',
57 'description' => "Change your site's URL paths by aliasing them.",
68a7999c 58 'page callback' => 'path_admin_overview',
03752e35 59 'access arguments' => array('administer url aliases'),
6b24718e 60 'weight' => -5,
2c552193 61 'file' => 'path.admin.inc',
03752e35 62 );
977d635b 63 $items['admin/config/search/path/edit/%path'] = array(
7d4f2836 64 'title' => 'Edit alias',
5a09fc07 65 'page callback' => 'path_admin_edit',
977d635b 66 'page arguments' => array(5),
21576021 67 'access arguments' => array('administer url aliases'),
2c552193 68 'file' => 'path.admin.inc',
03752e35 69 );
977d635b 70 $items['admin/config/search/path/delete/%path'] = array(
7d4f2836 71 'title' => 'Delete alias',
03752e35 72 'page callback' => 'drupal_get_form',
977d635b 73 'page arguments' => array('path_admin_delete_confirm', 5),
21576021 74 'access arguments' => array('administer url aliases'),
2c552193 75 'file' => 'path.admin.inc',
03752e35 76 );
43db68b6 77 $items['admin/config/search/path/list'] = array(
7d4f2836 78 'title' => 'List',
03752e35
DB
79 'type' => MENU_DEFAULT_LOCAL_TASK,
80 'weight' => -10,
81 );
43db68b6 82 $items['admin/config/search/path/add'] = array(
7d4f2836 83 'title' => 'Add alias',
5a09fc07 84 'page callback' => 'path_admin_edit',
03752e35 85 'access arguments' => array('administer url aliases'),
e6eb4899 86 'type' => MENU_LOCAL_ACTION,
2c552193 87 'file' => 'path.admin.inc',
03752e35 88 );
2ba974d2
SW
89
90 return $items;
91}
92
93/**
eaee909a 94 * Implements hook_form_BASE_FORM_ID_alter().
2ba974d2 95 */
eaee909a
DB
96function path_form_node_form_alter(&$form, $form_state) {
97 $path = array();
98 if (!empty($form['#node']->nid)) {
99 $conditions = array('source' => 'node/' . $form['#node']->nid);
100 if ($form['#node']->language != LANGUAGE_NONE) {
101 $conditions['language'] = $form['#node']->language;
102 }
103 $path = path_load($conditions);
104 if ($path === FALSE) {
105 $path = array();
87567f89
DB
106 }
107 }
eaee909a
DB
108 $path += array(
109 'pid' => NULL,
110 'source' => isset($form['#node']->nid) ? 'node/' . $form['#node']->nid : NULL,
111 'alias' => '',
112 'language' => isset($form['#node']->language) ? $form['#node']->language : LANGUAGE_NONE,
113 );
114
115 $form['path'] = array(
116 '#type' => 'fieldset',
117 '#title' => t('URL path settings'),
118 '#collapsible' => TRUE,
119 '#collapsed' => empty($path['alias']),
120 '#group' => 'additional_settings',
ae85abb9
DB
121 '#attributes' => array(
122 'class' => array('path-form'),
123 ),
eaee909a
DB
124 '#attached' => array(
125 'js' => array(drupal_get_path('module', 'path') . '/path.js'),
126 ),
127 '#access' => user_access('create url aliases') || user_access('administer url aliases'),
128 '#weight' => 30,
129 '#tree' => TRUE,
130 '#element_validate' => array('path_form_element_validate'),
131 );
132 $form['path']['alias'] = array(
133 '#type' => 'textfield',
134 '#title' => t('URL alias'),
135 '#default_value' => $path['alias'],
136 '#maxlength' => 255,
137 '#collapsible' => TRUE,
138 '#collapsed' => TRUE,
6d0ca97b 139 '#description' => t('Optionally specify an alternative URL by which this content can be accessed. For example, type "about" when writing an about page. Use a relative path and don\'t add a trailing slash or the URL alias won\'t work.'),
eaee909a
DB
140 );
141 $form['path']['pid'] = array('#type' => 'value', '#value' => $path['pid']);
142 $form['path']['source'] = array('#type' => 'value', '#value' => $path['source']);
143 $form['path']['language'] = array('#type' => 'value', '#value' => $path['language']);
87567f89 144}
2ba974d2 145
87567f89 146/**
0fa300a6 147 * Form element validation handler for URL alias form element.
87567f89 148 */
0fa300a6 149function path_form_element_validate($element, &$form_state, $complete_form) {
d6710e41 150 // Trim the submitted value.
151 $alias = trim($form_state['values']['path']['alias']);
152 if (!empty($alias)) {
0fa300a6
DB
153 form_set_value($element['alias'], $alias, $form_state);
154 // Node language (Locale module) needs special care. Since the language of
155 // the URL alias depends on the node language, and the node language can be
156 // switched right within the same form, we need to conditionally overload
157 // the originally assigned URL alias language.
158 // @todo Remove this after converting Path module to a field, and, after
159 // stopping Locale module from abusing the content language system.
160 if (isset($form_state['values']['language'])) {
161 form_set_value($element['language'], $form_state['values']['language'], $form_state);
977d635b 162 }
0fa300a6
DB
163
164 $path = $form_state['values']['path'];
165
166 // Ensure that the submitted alias does not exist yet.
167 $query = db_select('url_alias')
168 ->condition('alias', $path['alias'])
169 ->condition('language', $path['language']);
170 if (!empty($path['source'])) {
171 $query->condition('source', $path['source'], '<>');
172 }
173 $query->addExpression('1');
174 $query->range(0, 1);
175 if ($query->execute()->fetchField()) {
176 form_set_error('alias', t('The alias is already in use.'));
58b0235a 177 }
87567f89
DB
178 }
179}
2ba974d2 180
87567f89 181/**
1da26fad 182 * Implements hook_node_insert().
87567f89 183 */
4d46b7cd 184function path_node_insert($node) {
0fa300a6
DB
185 if (isset($node->path)) {
186 $path = $node->path;
187 $path['alias'] = trim($path['alias']);
188 // Only save a non-empty alias.
189 if (!empty($path['alias'])) {
190 // Ensure fields for programmatic executions.
191 $path['source'] = 'node/' . $node->nid;
0baad49d 192 $path['language'] = isset($node->language) ? $node->language : LANGUAGE_NONE;
0fa300a6 193 path_save($path);
87567f89
DB
194 }
195 }
196}
2ba974d2 197
87567f89 198/**
1da26fad 199 * Implements hook_node_update().
87567f89 200 */
4d46b7cd 201function path_node_update($node) {
0fa300a6
DB
202 if (isset($node->path)) {
203 $path = $node->path;
204 $path['alias'] = trim($path['alias']);
205 // Delete old alias if user erased it.
206 if (!empty($path['pid']) && empty($path['alias'])) {
207 path_delete($path['pid']);
977d635b 208 }
0fa300a6
DB
209 // Only save a non-empty alias.
210 if (!empty($path['alias'])) {
211 // Ensure fields for programmatic executions.
212 $path['source'] = 'node/' . $node->nid;
0baad49d 213 $path['language'] = isset($node->language) ? $node->language : LANGUAGE_NONE;
0fa300a6 214 path_save($path);
977d635b 215 }
87567f89
DB
216 }
217}
2ba974d2 218
87567f89 219/**
1da26fad 220 * Implements hook_node_delete().
87567f89 221 */
4d46b7cd 222function path_node_delete($node) {
0fa300a6
DB
223 // Delete all aliases associated with this node.
224 path_delete(array('source' => 'node/' . $node->nid));
2ba974d2
SW
225}
226
2ba974d2 227/**
1da26fad 228 * Implements hook_form_FORM_ID_alter().
bf8e86f7
DB
229 */
230function path_form_taxonomy_form_term_alter(&$form, $form_state) {
231 // Make sure this does not show up on the delete confirmation form.
232 if (empty($form_state['confirm_delete'])) {
0fa300a6
DB
233 $path = (isset($form['#term']['tid']) ? path_load('taxonomy/term/' . $form['#term']['tid']) : array());
234 if ($path === FALSE) {
235 $path = array();
bf8e86f7 236 }
0fa300a6
DB
237 $path += array(
238 'pid' => NULL,
239 'source' => isset($form['#term']['tid']) ? 'taxonomy/term/' . $form['#term']['tid'] : NULL,
240 'alias' => '',
0baad49d 241 'language' => LANGUAGE_NONE,
0fa300a6 242 );
d7a7ec64 243 $form['path'] = array(
0fa300a6
DB
244 '#access' => user_access('create url aliases') || user_access('administer url aliases'),
245 '#tree' => TRUE,
246 '#element_validate' => array('path_form_element_validate'),
247 );
d7a7ec64 248 $form['path']['alias'] = array(
bf8e86f7
DB
249 '#type' => 'textfield',
250 '#title' => t('URL alias'),
977d635b 251 '#default_value' => $path['alias'],
bf8e86f7
DB
252 '#maxlength' => 255,
253 '#weight' => 0,
bf8e86f7
DB
254 '#description' => t("Optionally specify an alternative URL by which this term can be accessed. Use a relative path and don't add a trailing slash or the URL alias won't work."),
255 );
d7a7ec64
DB
256 $form['path']['pid'] = array('#type' => 'value', '#value' => $path['pid']);
257 $form['path']['source'] = array('#type' => 'value', '#value' => $path['source']);
258 $form['path']['language'] = array('#type' => 'value', '#value' => $path['language']);
bf8e86f7
DB
259 }
260}
261
262/**
1da26fad 263 * Implements hook_taxonomy_term_insert().
bf8e86f7 264 */
0fa300a6
DB
265function path_taxonomy_term_insert($term) {
266 if (isset($term->path)) {
267 $path = $term->path;
268 $path['alias'] = trim($path['alias']);
269 // Only save a non-empty alias.
270 if (!empty($path['alias'])) {
271 // Ensure fields for programmatic executions.
272 $path['source'] = 'taxonomy/term/' . $term->tid;
0baad49d 273 $path['language'] = LANGUAGE_NONE;
0fa300a6 274 path_save($path);
bf8e86f7 275 }
bf8e86f7
DB
276 }
277}
278
279/**
1da26fad 280 * Implements hook_taxonomy_term_update().
bf8e86f7 281 */
0fa300a6
DB
282function path_taxonomy_term_update($term) {
283 if (isset($term->path)) {
284 $path = $term->path;
285 $path['alias'] = trim($path['alias']);
286 // Delete old alias if user erased it.
287 if (!empty($path['pid']) && empty($path['alias'])) {
288 path_delete($path['pid']);
289 }
290 // Only save a non-empty alias.
291 if (!empty($path['alias'])) {
292 // Ensure fields for programmatic executions.
293 $path['source'] = 'taxonomy/term/' . $term->tid;
0baad49d 294 $path['language'] = LANGUAGE_NONE;
0fa300a6
DB
295 path_save($path);
296 }
bf8e86f7
DB
297 }
298}
299
300/**
1da26fad 301 * Implements hook_taxonomy_term_delete().
2ba974d2 302 */
0fa300a6
DB
303function path_taxonomy_term_delete($term) {
304 // Delete all aliases associated with this term.
305 path_delete(array('source' => 'taxonomy/term/' . $term->tid));
2ba974d2 306}