Simpletest Coverage - modules/path/path.module

1 <?php
2 // $Id: path.module,v 1.164 2009/08/15 15:45:07 dries Exp $
3
4 /**
5 * @file
6 * Enables users to rename URLs.
7 */
8
9 /**
10 * Implement hook_help().
11 */
12 function path_help($path, $arg) {
13 switch ($path) {
14 case 'admin/help#path':
15 $output = '<p>' . t('The path module allows you to specify aliases for Drupal URLs. Such aliases improve readability of URLs for your users and may help internet search engines to index your content more effectively. More than one alias may be created for a given page.') . '</p>';
16 $output .= '<p>' . t('Some examples of URL aliases are:') . '</p>';
17 $output .= '<ul><li>' . t('%alias for the path %path', array('%alias' => 'login', '%path' => 'user/login')) . '</li>';
18 $output .= '<li>' . t('%alias for the path %path', array('%alias' => 'store', '%path' => 'image/tid/16')) . '</li>';
19 $output .= '<li>' . t('%alias for the path %path', array('%alias' => 'store/products/whirlygigs', '%path' => 'taxonomy/term/7+19+20+21')) . '</li>';
20 $output .= '<li>' . t('%alias for the path %path', array('%alias' => 'contact', '%path' => 'node/3')) . '</li></ul>';
21 $output .= '<p>' . t('The path module enables appropriately permissioned users to specify an optional alias in all node input and editing forms, and provides an interface to view and edit all URL aliases. The two permissions related to URL aliasing are <em>administer url aliases</em> and <em>create url aliases</em>.') . ' </p>';
22 $output .= '<p>' . t('This module also provides user-defined mass URL aliasing capabilities, which is useful if you wish to uniformly use URLs different from the default. For example, you may want to have your URLs presented in a different language. Access to the Drupal source code on the web server is required to set up mass URL aliasing.') . ' </p>';
23 $output .= '<p>' . t('For more information, see the online handbook entry for <a href="@path">Path module</a>.', array('@path' => 'http://drupal.org/handbook/modules/path/')) . '</p>';
24 return $output;
25 case 'admin/settings/path':
26 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>';
27 case 'admin/settings/path/add':
28 return '<p>' . t('Enter the path you wish to create the alias for, followed by the name of the new alias.') . '</p>';
29 }
30 }
31
32 /**
33 * Implement hook_menu().
34 */
35 function path_menu() {
36 $items['admin/settings/path'] = array(
37 'title' => 'URL aliases',
38 'description' => "Change your site's URL paths by aliasing them.",
39 'page callback' => 'path_admin_overview',
40 'access arguments' => array('administer url aliases'),
41 );
42 $items['admin/settings/path/edit'] = array(
43 'title' => 'Edit alias',
44 'page callback' => 'path_admin_edit',
45 'access arguments' => array('administer url aliases'),
46 'type' => MENU_CALLBACK,
47 );
48 $items['admin/settings/path/delete'] = array(
49 'title' => 'Delete alias',
50 'page callback' => 'drupal_get_form',
51 'page arguments' => array('path_admin_delete_confirm'),
52 'access arguments' => array('administer url aliases'),
53 'type' => MENU_CALLBACK,
54 );
55 $items['admin/settings/path/list'] = array(
56 'title' => 'List',
57 'type' => MENU_DEFAULT_LOCAL_TASK,
58 'weight' => -10,
59 );
60 $items['admin/settings/path/add'] = array(
61 'title' => 'Add alias',
62 'page callback' => 'path_admin_edit',
63 'access arguments' => array('administer url aliases'),
64 'type' => MENU_LOCAL_TASK,
65 );
66
67 return $items;
68 }
69
70 /**
71 * Post-confirmation; delete an URL alias.
72 */
73 function path_admin_delete($pid = 0) {
74 db_delete('url_alias')
75 ->condition('pid', $pid)
76 ->execute();
77 drupal_set_message(t('The alias has been deleted.'));
78 }
79
80 /**
81 * Set an aliased path for a given Drupal path, preventing duplicates.
82 */
83 function path_set_alias($path = NULL, $alias = NULL, $pid = NULL, $language = '') {
84 $path = urldecode($path);
85 $alias = urldecode($alias);
86 // First we check if we deal with an existing alias and delete or modify it based on pid.
87 if ($pid) {
88 // An existing alias.
89 if (!$path || !$alias) {
90 // Delete the alias based on pid.
91 db_delete('url_alias')
92 ->condition('pid', $pid)
93 ->execute();
94 }
95 else {
96 // Update the existing alias.
97 db_update('url_alias')
98 ->fields(array(
99 'src' => $path,
100 'dst' => $alias,
101 'language' => $language))
102 ->condition('pid', $pid)
103 ->execute();
104 }
105 }
106 elseif ($path && $alias) {
107 // Check for existing aliases.
108 if ($alias == drupal_get_path_alias($path, $language)) {
109 // There is already such an alias, neutral or in this language.
110 // Update the alias based on alias; setting the language if not yet done.
111 db_update('url_alias')
112 ->fields(array(
113 'src' => $path,
114 'dst' => $alias,
115 'language' => $language
116 ))
117 ->condition('dst', $alias)
118 ->execute();
119 }
120 else {
121 // A new alias. Add it to the database.
122 db_insert('url_alias')
123 ->fields(array(
124 'src' => $path,
125 'dst' => $alias,
126 'language' => $language,
127 ))
128 ->execute();
129 }
130 }
131 else {
132 // Delete the alias.
133 if ($alias) {
134 db_delete('url_alias')
135 ->condition('dst', $alias)
136 ->execute();
137 }
138 else {
139 db_delete('url_alias')
140 ->condition('src', $path)
141 ->execute();
142 }
143 }
144 drupal_clear_path_cache();
145 }
146
147 /**
148 * Implement hook_node_validate().
149 */
150 function path_node_validate($node, $form) {
151 if (user_access('create url aliases') || user_access('administer url aliases')) {
152 if (isset($node->path)) {
153 $language = isset($node->language) ? $node->language : '';
154 $node->path = trim($node->path);
155 $has_alias = db_query("SELECT COUNT(dst) FROM {url_alias} WHERE src <> :src AND dst = :dst AND language = :language", array(
156 ':src' => "node/$node->nid",
157 ':dst' => $node->path,
158 ':language' => $language,
159 ))
160 ->fetchField();
161
162 if ($has_alias) {
163 form_set_error('path', t('The path is already in use.'));
164 }
165 }
166 }
167 }
168
169 /**
170 * Implement hook_node_load().
171 */
172 function path_node_load($nodes, $types) {
173 foreach ($nodes as $node) {
174 $language = isset($node->language) ? $node->language : '';
175 $path = 'node/' . $node->nid;
176 $alias = drupal_get_path_alias($path, $language);
177 if ($path != $alias) {
178 $node->path = $alias;
179 }
180 }
181 }
182
183 /**
184 * Implement hook_node_insert().
185 */
186 function path_node_insert($node) {
187 if (user_access('create url aliases') || user_access('administer url aliases')) {
188 $language = isset($node->language) ? $node->language : '';
189 // Don't try to insert if path is NULL. We may have already set
190 // the alias ahead of time.
191 if (isset($node->path)) {
192 path_set_alias('node/' . $node->nid, $node->path, NULL, $language);
193 }
194 }
195 }
196
197 /**
198 * Implement hook_node_update().
199 */
200 function path_node_update($node) {
201 if (user_access('create url aliases') || user_access('administer url aliases')) {
202 $language = isset($node->language) ? $node->language : '';
203 path_set_alias('node/' . $node->nid, isset($node->path) ? $node->path : NULL, isset($node->pid) ? $node->pid : NULL, $language);
204 }
205 }
206
207 /**
208 * Implement hook_node_delete().
209 */
210 function path_node_delete($node) {
211 path_set_alias('node/' . $node->nid);
212 }
213
214 /**
215 * Implement hook_taxonomy_term_delete().
216 */
217 function path_taxonomy_term_delete($term) {
218 path_set_alias('taxonomy/term/' . $term->tid);
219 }
220
221 /**
222 * Implement hook_form_alter().
223 */
224 function path_form_alter(&$form, $form_state, $form_id) {
225 if (!empty($form['#node_edit_form'])) {
226 $path = isset($form['#node']->path) ? $form['#node']->path : NULL;
227 $form['path'] = array(
228 '#type' => 'fieldset',
229 '#title' => t('URL path settings'),
230 '#collapsible' => TRUE,
231 '#collapsed' => empty($path),
232 '#group' => 'additional_settings',
233 '#attached_js' => array(drupal_get_path('module', 'path') . '/path.js'),
234 '#access' => user_access('create url aliases'),
235 '#weight' => 30,
236 );
237 $form['path']['path'] = array(
238 '#type' => 'textfield',
239 '#title' => t('URL alias'),
240 '#default_value' => $path,
241 '#maxlength' => 255,
242 '#collapsible' => TRUE,
243 '#collapsed' => TRUE,
244 '#description' => t('Optionally specify an alternative URL by which this node 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.'),
245 );
246 if ($path) {
247 $form['path']['pid'] = array(
248 '#type' => 'value',
249 '#value' => db_query("SELECT pid FROM {url_alias} WHERE dst = :dst AND language = :language", array(
250 ':dst' => $path,
251 ':language' => $form['#node']->language
252 ))
253 ->fetchField(),
254 );
255 }
256 }
257 }
258
259 /**
260 * Implement hook_form_FORM_ID_alter().
261 */
262 function path_form_taxonomy_form_term_alter(&$form, $form_state) {
263 // Make sure this does not show up on the delete confirmation form.
264 if (empty($form_state['confirm_delete'])) {
265 // After a new term is added, populate the path field if it was set.
266 if (!empty($form['#term']['path'])) {
267 $path = $form['#term']['path'];
268 }
269 else {
270 $url = 'taxonomy/term/' . $form['#term']['tid'];
271 $alias = drupal_get_path_alias($url);
272
273 // Since drupal_get_path_alias() can return the default path, check if we really have an alias.
274 if ($alias != $url) {
275 $path = $alias;
276 }
277 else {
278 $path = NULL;
279 }
280 }
281 $form['#validate'][] = 'path_taxonomy_term_validate';
282 $form['#submit'][] = 'path_taxonomy_term_submit';
283 $form['identification']['path'] = array(
284 '#type' => 'textfield',
285 '#title' => t('URL alias'),
286 '#default_value' => $path,
287 '#maxlength' => 255,
288 '#weight' => 0,
289 '#access' => (user_access('create url aliases') || user_access('administer url aliases')),
290 '#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."),
291 );
292 if ($path) {
293 // Populate with pid so we can update existing path entry instead of creating a new one.
294 $form['identification']['path']['pid'] = array(
295 '#type' => 'value',
296 '#access' => (user_access('create url aliases') || user_access('administer url aliases')),
297 '#value' => db_query("SELECT pid FROM {url_alias} WHERE dst = :dst", array(':dst' => $path))->fetchField(),
298 );
299 }
300 }
301 }
302
303 /**
304 * Path validation callback for taxonomy_form_term.
305 */
306 function path_taxonomy_term_validate($form, &$form_state) {
307 $pid = db_query("SELECT pid FROM {url_alias} WHERE dst = :dst", array(':dst' => $form_state['values']['path']))->fetchField();
308 if ($pid) {
309 // If the pid matches the one in use for this term then we are fine.
310 if (isset($form_state['values']['pid']) && $pid == $form_state['values']['pid']) {
311 return;
312 }
313 form_set_error('path', 'The URL alias is already in use.');
314 }
315 }
316
317 /**
318 * Path submission callback for taxonomy_form_term.
319 */
320 function path_taxonomy_term_submit($form, &$form_state) {
321 // Make sure this is not triggered on the delete confirmation form.
322 if (empty($form_state['confirm_delete'])) {
323 $url = 'taxonomy/term/' . $form_state['tid'];
324 $alias = isset($form_state['values']['path']) ? $form_state['values']['path'] : NULL;
325 $pid = isset($form_state['values']['pid']) ? $form_state['values']['pid'] : NULL;
326 path_set_alias($url, $alias, $pid);
327 }
328 }
329
330 /**
331 * Implement hook_permission().
332 */
333 function path_permission() {
334 return array(
335 'administer url aliases' => array(
336 'title' => t('Administer URL aliases'),
337 'description' => t('Manage URL aliases across the entire website.'),
338 ),
339 'create url aliases' => array(
340 'title' => t('Create URL aliases'),
341 'description' => t('Manage URL aliases on content.'),
342 ),
343 );
344 }
345
346 /**
347 * Fetch a specific URL alias from the database.
348 */
349 function path_load($pid) {
350 return db_query('SELECT * FROM {url_alias} WHERE pid = :pid', array(':pid' => $pid))->fetchAssoc();
351 }
352

Legend

Missed
lines code that were not excersized during program execution.
Covered
lines code were excersized during program execution.
Comment/non executable
Comment or non-executable line of code.
Dead
lines of code that according to xdebug could not be executed. This is counted as coverage code because in almost all cases it is code that runnable.