Projet

Général

Profil

Paste
Télécharger (25,9 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / pathauto / pathauto.module @ a45e4bc1

1
<?php
2

    
3
/**
4
 * @defgroup pathauto Pathauto: Automatically generates aliases for content
5
 *
6
 * The Pathauto module automatically generates path aliases for various kinds of
7
 * content (nodes, categories, users) without requiring the user to manually
8
 * specify the path alias. This allows you to get aliases like
9
 * /category/my-node-title.html instead of /node/123. The aliases are based upon
10
 * a "pattern" system which the administrator can control.
11
 */
12

    
13
/**
14
 * @file
15
 * Main file for the Pathauto module, which automatically generates aliases for content.
16
 *
17
 * @ingroup pathauto
18
 */
19

    
20
/**
21
 * The default ignore word list.
22
 */
23
define('PATHAUTO_IGNORE_WORDS', 'a, an, as, at, before, but, by, for, from, is, in, into, like, of, off, on, onto, per, since, than, the, this, that, to, up, via, with');
24

    
25
/**
26
 * Implements hook_hook_info().
27
 */
28
function pathauto_hook_info() {
29
  $info['pathauto'] = array('group' => 'pathauto');
30
  $info['path_alias_types'] = array('group' => 'pathauto');
31
  return $info;
32
}
33

    
34
/**
35
 * Implements hook_module_implements_alter().
36
 *
37
 * Adds pathauto support for core modules.
38
 */
39
function pathauto_module_implements_alter(&$implementations, $hook) {
40
  $hooks = pathauto_hook_info();
41
  if (isset($hooks[$hook])) {
42
    $modules = array('node', 'taxonomy', 'user', 'forum', 'blog');
43
    foreach ($modules as $module) {
44
      if (module_exists($module)) {
45
        $implementations[$module] = TRUE;
46
      }
47
    }
48
    // Move pathauto.module to get included first since it is responsible for
49
    // other modules.
50
    unset($implementations['pathauto']);
51
    $implementations = array_merge(array('pathauto' => 'pathauto'), $implementations);
52
  }
53
}
54

    
55
/**
56
 * Implements hook_help().
57
 */
58
function pathauto_help($path, $arg) {
59
  switch ($path) {
60
    case 'admin/help#pathauto':
61
      module_load_include('inc', 'pathauto');
62
      $output = '<h3>' . t('About') . '</h3>';
63
      $output .= '<p>' . t('Provides a mechanism for modules to automatically generate aliases for the content they manage.') . '</p>';
64
      $output .= '<h3>' . t('Settings') . '</h3>';
65
      $output .= '<dl>';
66
      $output .= '<dt>' . t('Maximum alias and component length') . '</dt>';
67
      $output .= '<dd>' . t('The <strong>maximum alias length</strong> and <strong>maximum component length</strong> values default to 100 and have a limit of @max from Pathauto. This length is limited by the length of the "alias" column of the url_alias database table. The default database schema for this column is @max. If you set a length that is equal to that of the one set in the "alias" column it will cause problems in situations where the system needs to append additional words to the aliased URL. You should enter a value that is the length of the "alias" column minus the length of any strings that might get added to the end of the URL. The length of strings that might get added to the end of your URLs depends on which modules you have enabled and on your Pathauto settings. The recommended and default value is 100.', array('@max' => _pathauto_get_schema_alias_maxlength())) . '</dd>';
68
      $output .= '</dl>';
69
      return $output;
70
  }
71
}
72

    
73
/**
74
 * Implements hook_permission().
75
 */
76
function pathauto_permission() {
77
  return array(
78
    'administer pathauto' => array(
79
      'title' => t('Administer pathauto'),
80
      'description' => t('Allows a user to configure patterns for automated aliases and bulk delete URL-aliases.'),
81
    ),
82
    'notify of path changes' => array(
83
      'title' => t('Notify of Path Changes'),
84
      'description' => t('Determines whether or not users are notified.'),
85
    ),
86
  );
87
}
88

    
89
/**
90
 * Implements hook_menu().
91
 */
92
function pathauto_menu() {
93
  $items['admin/config/search/path/patterns'] = array(
94
    'title' => 'Patterns',
95
    'page callback' => 'drupal_get_form',
96
    'page arguments' => array('pathauto_patterns_form'),
97
    'access arguments' => array('administer pathauto'),
98
    'type' => MENU_LOCAL_TASK,
99
    'weight' => 10,
100
    'file' => 'pathauto.admin.inc',
101
  );
102
  $items['admin/config/search/path/settings'] = array(
103
    'title' => 'Settings',
104
    'page callback' => 'drupal_get_form',
105
    'page arguments' => array('pathauto_settings_form'),
106
    'access arguments' => array('administer pathauto'),
107
    'type' => MENU_LOCAL_TASK,
108
    'weight' => 20,
109
    'file' => 'pathauto.admin.inc',
110
  );
111
  $items['admin/config/search/path/update_bulk'] = array(
112
    'title' => 'Bulk update',
113
    'page callback' => 'drupal_get_form',
114
    'page arguments' => array('pathauto_bulk_update_form'),
115
    'access arguments' => array('administer url aliases'),
116
    'type' => MENU_LOCAL_TASK,
117
    'weight' => 30,
118
    'file' => 'pathauto.admin.inc',
119
  );
120
  $items['admin/config/search/path/delete_bulk'] = array(
121
    'title' => 'Delete aliases',
122
    'page callback' => 'drupal_get_form',
123
    'page arguments' => array('pathauto_admin_delete'),
124
    'access arguments' => array('administer url aliases'),
125
    'type' => MENU_LOCAL_TASK,
126
    'weight' => 40,
127
    'file' => 'pathauto.admin.inc',
128
  );
129

    
130
  return $items;
131
}
132

    
133
/**
134
 * Load an URL alias pattern by entity, bundle, and language.
135
 *
136
 * @param $entity
137
 *   An entity (e.g. node, taxonomy, user, etc.)
138
 * @param $bundle
139
 *   A bundle (e.g. content type, vocabulary ID, etc.)
140
 * @param $language
141
 *   A language code, defaults to the LANGUAGE_NONE constant.
142
 */
143
function pathauto_pattern_load_by_entity($entity, $bundle = '', $language = LANGUAGE_NONE) {
144
  $patterns = &drupal_static(__FUNCTION__, array());
145

    
146
  $pattern_id = "$entity:$bundle:$language";
147
  if (!isset($patterns[$pattern_id])) {
148
    $variables = array();
149
    if ($language != LANGUAGE_NONE) {
150
      $variables[] = "pathauto_{$entity}_{$bundle}_{$language}_pattern";
151
    }
152
    if ($bundle) {
153
      $variables[] = "pathauto_{$entity}_{$bundle}_pattern";
154
    }
155
    $variables[] = "pathauto_{$entity}_pattern";
156

    
157
    foreach ($variables as $variable) {
158
      if ($pattern = trim(variable_get($variable, ''))) {
159
        break;
160
      }
161
    }
162

    
163
    $patterns[$pattern_id] = $pattern;
164
  }
165

    
166
  return $patterns[$pattern_id];
167
}
168

    
169
/**
170
 * Delete multiple URL aliases.
171
 *
172
 * Intent of this is to abstract a potential path_delete_multiple() function
173
 * for Drupal 7 or 8.
174
 *
175
 * @param $pids
176
 *   An array of path IDs to delete.
177
 */
178
function pathauto_path_delete_multiple($pids) {
179
  foreach ($pids as $pid) {
180
    path_delete(array('pid' => $pid));
181
  }
182
}
183

    
184
/**
185
 * Delete an URL alias and any of its sub-paths.
186
 *
187
 * Given a source like 'node/1' this function will delete any alias that have
188
 * that specific source or any sources that match 'node/1/%'.
189
 *
190
 * @param $source
191
 *   An string with a source URL path.
192
 */
193
function pathauto_path_delete_all($source) {
194
  $sql = "SELECT pid FROM {url_alias} WHERE source = :source OR source LIKE :source_wildcard";
195
  $pids = db_query($sql, array(':source' => $source, ':source_wildcard' => $source . '/%'))->fetchCol();
196
  if ($pids) {
197
    pathauto_path_delete_multiple($pids);
198
  }
199
}
200

    
201
/**
202
 * Delete an entity URL alias and any of its sub-paths.
203
 *
204
 * This function also checks to see if the default entity URI is different from
205
 * the current entity URI and will delete any of the default aliases.
206
 *
207
 * @param $entity_type
208
 *   A string with the entity type.
209
 * @param $entity
210
 *   An entity object.
211
 * @param $default_uri
212
 *   The optional default uri path for the entity.
213
 */
214
function pathauto_entity_path_delete_all($entity_type, $entity, $default_uri = NULL) {
215
  $uri = entity_uri($entity_type, $entity);
216
  pathauto_path_delete_all($uri['path']);
217
  if (isset($default_uri) && $uri['path'] != $default_uri) {
218
    pathauto_path_delete_all($default_uri);
219
  }
220
}
221

    
222
/**
223
 * Implements hook_field_attach_rename_bundle().
224
 *
225
 * Respond to machine name changes for pattern variables.
226
 */
227
function pathauto_field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) {
228
  $variables = db_select('variable', 'v')
229
    ->fields('v', array('name'))
230
    ->condition('name', db_like("pathauto_{$entity_type}_{$bundle_old}_") . '%', 'LIKE')
231
    ->execute()
232
    ->fetchCol();
233
  foreach ($variables as $variable) {
234
    $value = variable_get($variable, '');
235
    variable_del($variable);
236
    $variable = strtr($variable, array("{$entity_type}_{$bundle_old}" => "{$entity_type}_{$bundle_new}"));
237
    variable_set($variable, $value);
238
  }
239
}
240

    
241
/**
242
 * Implements hook_field_attach_delete_bundle().
243
 *
244
 * Respond to sub-types being deleted, their patterns can be removed.
245
 */
246
function pathauto_field_attach_delete_bundle($entity_type, $bundle) {
247
  $variables = db_select('variable', 'v')
248
    ->fields('v', array('name'))
249
    ->condition('name', db_like("pathauto_{$entity_type}_{$bundle}_") . '%', 'LIKE')
250
    ->execute()
251
    ->fetchCol();
252
  foreach ($variables as $variable) {
253
    variable_del($variable);
254
  }
255
}
256

    
257
/**
258
 * Implements hook_field_attach_form().
259
 *
260
 * Add the automatic alias form elements to an existing path form fieldset.
261
 */
262
function pathauto_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
263
  list($id, , $bundle) = entity_extract_ids($entity_type, $entity);
264

    
265
  if (!isset($form['path'])) {
266
    // This entity must be supported by core's path.module first.
267
    // @todo Investigate removing this and supporting all fieldable entities.
268
    return;
269
  }
270
  else {
271
    // Taxonomy terms do not have an actual fieldset for path settings.
272
    // Merge in the defaults.
273
    $form['path'] += array(
274
      '#type' => 'fieldset',
275
      '#title' => t('URL path settings'),
276
      '#collapsible' => TRUE,
277
      '#collapsed' => empty($form['path']['alias']),
278
      '#group' => 'additional_settings',
279
      '#attributes' => array(
280
        'class' => array('path-form'),
281
      ),
282
      '#access' => user_access('create url aliases') || user_access('administer url aliases'),
283
      '#weight' => 30,
284
      '#tree' => TRUE,
285
      '#element_validate' => array('path_form_element_validate'),
286
    );
287
  }
288

    
289
  $pattern = pathauto_pattern_load_by_entity($entity_type, $bundle, $langcode);
290
  if (empty($pattern)) {
291
    return;
292
  }
293

    
294
  if (!isset($entity->path['pathauto'])) {
295
    if (!empty($id)) {
296
      module_load_include('inc', 'pathauto');
297
      $uri = entity_uri($entity_type, $entity);
298
      $path = drupal_get_path_alias($uri['path'], $langcode);
299
      $pathauto_alias = pathauto_create_alias($entity_type, 'return', $uri['path'], array($entity_type => $entity), $bundle, $langcode);
300
      $entity->path['pathauto'] = ($path != $uri['path'] && $path == $pathauto_alias);
301
    }
302
    else {
303
      $entity->path['pathauto'] = TRUE;
304
    }
305
  }
306

    
307
  // Add JavaScript that will disable the path textfield when the automatic
308
  // alias checkbox is checked.
309
  $form['path']['alias']['#states']['!enabled']['input[name="path[pathauto]"]'] = array('checked' => TRUE);
310

    
311
  // Override path.module's vertical tabs summary.
312
  $form['path']['#attached']['js'] = array(
313
    'vertical-tabs' => drupal_get_path('module', 'pathauto') . '/pathauto.js'
314
  );
315

    
316
  $form['path']['pathauto'] = array(
317
    '#type' => 'checkbox',
318
    '#title' => t('Generate automatic URL alias'),
319
    '#default_value' => $entity->path['pathauto'],
320
    '#description' => t('Uncheck this to create a custom alias below.'),
321
    '#weight' => -1,
322
  );
323

    
324
  // Add a shortcut link to configure URL alias patterns.
325
  if (drupal_valid_path('admin/config/search/path/patterns')) {
326
    $form['path']['pathauto']['#description'] .= ' ' . l(t('Configure URL alias patterns.'), 'admin/config/search/path/patterns');
327
  }
328

    
329
  if ($entity->path['pathauto'] && !empty($entity->old_alias) && empty($entity->path['alias'])) {
330
    $form['path']['alias']['#default_value'] = $entity->old_alias;
331
    $entity->path['alias'] = $entity->old_alias;
332
  }
333

    
334
  // For Pathauto to remember the old alias and prevent the Path module from
335
  // deleting it when Pathauto wants to preserve it.
336
  if (!empty($entity->path['alias'])) {
337
    $form['path']['old_alias'] = array(
338
      '#type' => 'value',
339
      '#value' => $entity->path['alias'],
340
    );
341
  }
342
}
343

    
344
/**
345
 * Implements hook_entity_presave().
346
 */
347
function pathauto_entity_presave($entity, $type) {
348
  // About to be saved (before insert/update)
349
  if (!empty($entity->path['pathauto']) && isset($entity->path['old_alias'])
350
      && $entity->path['alias'] == '' && $entity->path['old_alias'] != '') {
351
    /**
352
     * There was an old alias, but when pathauto_perform_alias was checked
353
     * the javascript disabled the textbox which led to an empty value being
354
     * submitted. Restoring the old path-value here prevents the Path module
355
     * from deleting any old alias before Pathauto gets control.
356
     */
357
    $entity->path['alias'] = $entity->path['old_alias'];
358
  }
359

    
360
  // Help prevent errors with progromatically creating entities by defining
361
  // path['alias'] as an empty string.
362
  // @see http://drupal.org/node/1328180
363
  // @see http://drupal.org/node/1576552
364
  if (isset($entity->path['pathauto']) && !isset($entity->path['alias'])) {
365
    $entity->path['alias'] = '';
366
  }
367
}
368

    
369
/**
370
 * Implements hook_action_info().
371
 */
372
function pathauto_action_info() {
373
  $info['pathauto_node_update_action'] = array(
374
    'type' => 'node',
375
    'label' => t('Update node alias'),
376
    'configurable' => FALSE,
377
  );
378
  $info['pathauto_taxonomy_term_update_action'] = array(
379
    'type' => 'taxonomy_term',
380
    'label' => t('Update taxonomy term alias'),
381
    'configurable' => FALSE,
382
  );
383
  $info['pathauto_user_update_action'] = array(
384
    'type' => 'user',
385
    'label' => t('Update user alias'),
386
    'configurable' => FALSE,
387
  );
388

    
389
  return $info;
390
}
391

    
392
/**
393
 * Returns the language code of the given entity.
394
 *
395
 * Backward compatibility layer to ensure that installations running an older
396
 * version of core where entity_language() is not avilable do not break.
397
 *
398
 * @param string $entity_type
399
 *   An entity type.
400
 * @param object $entity
401
 *   An entity object.
402
 * @param bool $check_language_property
403
 *   A boolean if TRUE, will attempt to fetch the language code from
404
 *   $entity->language if the entity_language() function failed or does not
405
 *   exist. Default is TRUE.
406
 */
407
function pathauto_entity_language($entity_type, $entity, $check_language_property = TRUE) {
408
  $langcode = NULL;
409

    
410
  if (function_exists('entity_language')) {
411
    $langcode = entity_language($entity_type, $entity);
412
  }
413
  elseif ($check_language_property && !empty($entity->language)) {
414
    $langcode = $entity->language;
415
  }
416

    
417
  return !empty($langcode) ? $langcode : LANGUAGE_NONE;
418
}
419

    
420
if (!function_exists('path_field_extra_fields')) {
421
/**
422
 * Implements hook_field_extra_fields() on behalf of path.module.
423
 *
424
 * Add support for the 'URL path settings' to be re-ordered by the user on the
425
 * 'Manage Fields' tab of content types and vocabularies.
426
 */
427
function path_field_extra_fields() {
428
  $info = array();
429

    
430
  foreach (node_type_get_types() as $node_type) {
431
    if (!isset($info['node'][$node_type->type]['form']['path'])) {
432
      $info['node'][$node_type->type]['form']['path'] = array(
433
        'label' => t('URL path settings'),
434
        'description' => t('Path module form elements'),
435
        'weight' => 30,
436
      );
437
    }
438
  }
439

    
440
  if (module_exists('taxonomy')) {
441
    $vocabularies = taxonomy_get_vocabularies();
442
    foreach ($vocabularies as $vocabulary) {
443
      if (!isset($info['taxonomy_term'][$vocabulary->machine_name]['form']['path'])) {
444
        $info['taxonomy_term'][$vocabulary->machine_name]['form']['path'] = array(
445
          'label' => t('URL path settings'),
446
          'description' => t('Path module form elements'),
447
          'weight' => 30,
448
        );
449
      }
450
    }
451
  }
452

    
453
  return $info;
454
}
455
}
456

    
457
/**
458
 * @name pathauto_node Pathauto integration for the core node module.
459
 * @{
460
 */
461

    
462
/**
463
 * Implements hook_node_insert().
464
 */
465
function pathauto_node_insert($node) {
466
  // @todo Remove the next line when http://drupal.org/node/1025870 is fixed.
467
  unset($node->uri);
468
  pathauto_node_update_alias($node, 'insert');
469
}
470

    
471
/**
472
 * Implements hook_node_update().
473
 */
474
function pathauto_node_update($node) {
475
  pathauto_node_update_alias($node, 'update');
476
}
477

    
478
/**
479
 * Implements hook_node_delete().
480
 */
481
function pathauto_node_delete($node) {
482
  pathauto_entity_path_delete_all('node', $node, "node/{$node->nid}");
483
}
484

    
485
/**
486
 * Implements hook_form_BASE_FORM_ID_alter().
487
 *
488
 * Add the Pathauto settings to the node form.
489
 */
490
function pathauto_form_node_form_alter(&$form, &$form_state) {
491
  $node = $form_state['node'];
492
  $langcode = pathauto_entity_language('node', $node);
493
  pathauto_field_attach_form('node', $node, $form, $form_state, $langcode);
494
}
495

    
496
/**
497
 * Implements hook_node_operations().
498
 */
499
function pathauto_node_operations() {
500
  $operations['pathauto_update_alias'] = array(
501
    'label' => t('Update URL alias'),
502
    'callback' => 'pathauto_node_update_alias_multiple',
503
    'callback arguments' => array('bulkupdate', array('message' => TRUE)),
504
  );
505
  return $operations;
506
}
507

    
508
/**
509
 * Update the URL aliases for an individual node.
510
 *
511
 * @param $node
512
 *   A node object.
513
 * @param $op
514
 *   Operation being performed on the node ('insert', 'update' or 'bulkupdate').
515
 * @param $options
516
 *   An optional array of additional options.
517
 */
518
function pathauto_node_update_alias(stdClass $node, $op, array $options = array()) {
519
  // Skip processing if the user has disabled pathauto for the node.
520
  if (isset($node->path['pathauto']) && empty($node->path['pathauto'])) {
521
    return;
522
  }
523

    
524
  $options += array('language' => pathauto_entity_language('node', $node));
525

    
526
  // Skip processing if the node has no pattern.
527
  if (!pathauto_pattern_load_by_entity('node', $node->type, $options['language'])) {
528
    return;
529
  }
530

    
531
  module_load_include('inc', 'pathauto');
532
  $uri = entity_uri('node', $node);
533
  pathauto_create_alias('node', $op, $uri['path'], array('node' => $node), $node->type, $options['language']);
534
}
535

    
536
/**
537
 * Update the URL aliases for multiple nodes.
538
 *
539
 * @param $nids
540
 *   An array of node IDs.
541
 * @param $op
542
 *   Operation being performed on the nodes ('insert', 'update' or
543
 *   'bulkupdate').
544
 * @param $options
545
 *   An optional array of additional options.
546
 */
547
function pathauto_node_update_alias_multiple(array $nids, $op, array $options = array()) {
548
  $options += array('message' => FALSE);
549

    
550
  $nodes = node_load_multiple($nids);
551
  foreach ($nodes as $node) {
552
    pathauto_node_update_alias($node, $op, $options);
553
  }
554

    
555
  if (!empty($options['message'])) {
556
    drupal_set_message(format_plural(count($nids), 'Updated URL alias for 1 node.', 'Updated URL aliases for @count nodes.'));
557
  }
558
}
559

    
560
/**
561
 * Update action wrapper for pathauto_node_update_alias().
562
 */
563
function pathauto_node_update_action($node, $context = array()) {
564
  pathauto_node_update_alias($node, 'bulkupdate', array('message' => TRUE));
565
}
566

    
567
/**
568
 * @} End of "name pathauto_node".
569
 */
570

    
571
/**
572
 * @name pathauto_taxonomy Pathauto integration for the core taxonomy module.
573
 * @{
574
 */
575

    
576
/**
577
 * Implements hook_taxonomy_term_insert().
578
 */
579
function pathauto_taxonomy_term_insert($term) {
580
  pathauto_taxonomy_term_update_alias($term, 'insert');
581
}
582

    
583
/**
584
 * Implements hook_taxonomy_term_update().
585
 */
586
function pathauto_taxonomy_term_update($term) {
587
  pathauto_taxonomy_term_update_alias($term, 'update', array('alias children' => TRUE));
588
}
589

    
590
/**
591
 * Implements hook_taxonomy_term_delete().
592
 */
593
function pathauto_taxonomy_term_delete($term) {
594
  pathauto_entity_path_delete_all('taxonomy_term', $term, "taxonomy/term/{$term->tid}");
595
}
596

    
597
/**
598
 * Implements hook_form_FORM_ID_alter().
599
 *
600
 * Add the Pathauto settings to the taxonomy term form.
601
 */
602
function pathauto_form_taxonomy_form_term_alter(&$form, $form_state) {
603
  $term = $form_state['term'];
604
  $langcode = pathauto_entity_language('taxonomy_term', $term);
605
  pathauto_field_attach_form('taxonomy_term', $term, $form, $form_state, $langcode);
606
}
607

    
608
/**
609
 * Update the URL aliases for an individual taxonomy term.
610
 *
611
 * @param $term
612
 *   A taxonomy term object.
613
 * @param $op
614
 *   Operation being performed on the term ('insert', 'update' or 'bulkupdate').
615
 * @param $options
616
 *   An optional array of additional options.
617
 */
618
function pathauto_taxonomy_term_update_alias(stdClass $term, $op, array $options = array()) {
619
  // Skip processing if the user has disabled pathauto for the term.
620
  if (isset($term->path['pathauto']) && empty($term->path['pathauto'])) {
621
    return;
622
  }
623

    
624
  $module = 'taxonomy_term';
625
  if ($term->vid == variable_get('forum_nav_vocabulary', '')) {
626
    if (module_exists('forum')) {
627
      $module = 'forum';
628
    }
629
    else {
630
      return;
631
    }
632
  }
633

    
634
  // Check that the term has its bundle, which is the vocabulary's machine name.
635
  if (!isset($term->vocabulary_machine_name)) {
636
    $vocabulary = taxonomy_vocabulary_load($term->vid);
637
    $term->vocabulary_machine_name = $vocabulary->machine_name;
638
  }
639

    
640
  $options += array(
641
    'alias children' => FALSE,
642
    'language' => pathauto_entity_language('taxonomy_term', $term),
643
  );
644

    
645
  // Skip processing if the term has no pattern.
646
  if (!pathauto_pattern_load_by_entity($module, $term->vocabulary_machine_name)) {
647
    return;
648
  }
649

    
650
  module_load_include('inc', 'pathauto');
651
  $uri = entity_uri('taxonomy_term', $term);
652
  pathauto_create_alias($module, $op, $uri['path'], array('term' => $term), $term->vocabulary_machine_name, $options['language']);
653

    
654
  if (!empty($options['alias children'])) {
655
    // For all children generate new aliases.
656
    $options['alias children'] = FALSE;
657
    unset($options['language']);
658
    foreach (taxonomy_get_tree($term->vid, $term->tid) as $subterm) {
659
      pathauto_taxonomy_term_update_alias($subterm, $op, $options);
660
    }
661
  }
662
}
663

    
664
/**
665
 * Update the URL aliases for multiple taxonomy terms.
666
 *
667
 * @param $tids
668
 *   An array of term IDs.
669
 * @param $op
670
 *   Operation being performed on the nodes ('insert', 'update' or
671
 *   'bulkupdate').
672
 * @param $options
673
 *   An optional array of additional options.
674
 */
675
function pathauto_taxonomy_term_update_alias_multiple(array $tids, $op, array $options = array()) {
676
  $options += array('message' => FALSE);
677

    
678
  $terms = taxonomy_term_load_multiple($tids);
679
  foreach ($terms as $term) {
680
    pathauto_taxonomy_term_update_alias($term, $op, $options);
681
  }
682

    
683
  if (!empty($options['message'])) {
684
    drupal_set_message(format_plural(count($tids), 'Updated URL alias for 1 term.', 'Updated URL aliases for @count terms.'));
685
  }
686
}
687

    
688
/**
689
 * Update action wrapper for pathauto_taxonomy_term_update_alias().
690
 */
691
function pathauto_taxonomy_term_update_action($term, $context = array()) {
692
  pathauto_taxonomy_term_update_alias($term, 'bulkupdate', array('message' => TRUE));
693
}
694

    
695
/**
696
 * @} End of "name pathauto_taxonomy".
697
 */
698

    
699
/**
700
 * @name pathauto_user Pathauto integration for the core user and blog modules.
701
 * @{
702
 */
703

    
704
/**
705
 * Implements hook_user_insert().
706
 */
707
function pathauto_user_insert(&$edit, $account, $category) {
708
  pathauto_user_update_alias($account, 'insert');
709
}
710

    
711
/**
712
 * Implements hook_user_update().
713
 */
714
function pathauto_user_update(&$edit, $account, $category) {
715
  pathauto_user_update_alias($account, 'update');
716
}
717

    
718
/**
719
 * Implements hook_user_delete().
720
 */
721
function pathauto_user_delete($account) {
722
  pathauto_entity_path_delete_all('user', $account, "user/{$account->uid}");
723
  pathauto_path_delete_all("blog/{$account->uid}");
724
}
725

    
726
/**
727
 * Implements hook_user_operations().
728
 */
729
function pathauto_user_operations() {
730
  $operations['pathauto_update_alias'] = array(
731
    'label' => t('Update URL alias'),
732
    'callback' => 'pathauto_user_update_alias_multiple',
733
    'callback arguments' => array('bulkupdate', array('message' => TRUE)),
734
  );
735
  return $operations;
736
}
737

    
738
/**
739
 * Update the URL aliases for an individual user account.
740
 *
741
 * @param $account
742
 *   A user account object.
743
 * @param $op
744
 *   Operation being performed on the account ('insert', 'update' or
745
 *   'bulkupdate').
746
 * @param $options
747
 *   An optional array of additional options.
748
 */
749
function pathauto_user_update_alias(stdClass $account, $op, array $options = array()) {
750
  // Skip processing if the user has disabled pathauto for the account.
751
  if (isset($account->path['pathauto']) && empty($account->path['pathauto'])) {
752
    return;
753
  }
754

    
755
  $options += array(
756
    'alias blog' => module_exists('blog'),
757
    // $user->language is not the user entity language, thus we need to skip
758
    // the property fallback check.
759
    'language' => pathauto_entity_language('user', $account, FALSE),
760
  );
761

    
762
  // Skip processing if the account has no pattern.
763
  if (!pathauto_pattern_load_by_entity('user', '', $options['language'])) {
764
    return;
765
  }
766

    
767
  module_load_include('inc', 'pathauto');
768
  $uri = entity_uri('user', $account);
769
  pathauto_create_alias('user', $op, $uri['path'], array('user' => $account), NULL, $options['language']);
770

    
771
  // Because blogs are also associated with users, also generate the blog paths.
772
  if (!empty($options['alias blog'])) {
773
    pathauto_blog_update_alias($account, $op, $options);
774
  }
775
}
776

    
777
/**
778
 * Update the URL aliases for multiple user accounts.
779
 *
780
 * @param $uids
781
 *   An array of user account IDs.
782
 * @param $op
783
 *   Operation being performed on the accounts ('insert', 'update' or
784
 *   'bulkupdate').
785
 * @param $options
786
 *   An optional array of additional options.
787
 */
788
function pathauto_user_update_alias_multiple(array $uids, $op, array $options = array()) {
789
  $options += array('message' => FALSE);
790

    
791
  $accounts = user_load_multiple($uids);
792
  foreach ($accounts as $account) {
793
    pathauto_user_update_alias($account, $op, $options);
794
  }
795

    
796
  if (!empty($options['message'])) {
797
    drupal_set_message(format_plural(count($uids), 'Updated URL alias for 1 user account.', 'Updated URL aliases for @count user accounts.'));
798
  }
799
}
800

    
801
/**
802
 * Update action wrapper for pathauto_user_update_alias().
803
 */
804
function pathauto_user_update_action($account, $context = array()) {
805
  pathauto_user_update_alias($account, 'bulkupdate', array('message' => TRUE));
806
}
807

    
808
/**
809
 * Update the blog URL aliases for an individual user account.
810
 *
811
 * @param $account
812
 *   A user account object.
813
 * @param $op
814
 *   Operation being performed on the blog ('insert', 'update' or
815
 *   'bulkupdate').
816
 * @param $options
817
 *   An optional array of additional options.
818
 */
819
function pathauto_blog_update_alias(stdClass $account, $op, array $options = array()) {
820
  // Skip processing if the blog has no pattern.
821
  if (!pathauto_pattern_load_by_entity('blog')) {
822
    return;
823
  }
824

    
825
  $options += array(
826
    'language' => LANGUAGE_NONE,
827
  );
828

    
829
  module_load_include('inc', 'pathauto');
830
  if (node_access('create', 'blog', $account)) {
831
    pathauto_create_alias('blog', $op, "blog/{$account->uid}", array('user' => $account), NULL, $options['language']);
832
  }
833
  else {
834
    pathauto_path_delete_all("blog/{$account->uid}");
835
  }
836
}
837

    
838
/**
839
 * @} End of "name pathauto_user".
840
 */