Project

General

Profile

Paste
Download (41.9 KB) Statistics
| Branch: | Revision:

root / drupal7 / sites / all / modules / taxonomy_menu / taxonomy_menu.module @ 6d8023f2

1
<?php
2

    
3
/**
4
 * @file
5
 * Adds links to taxonomy terms into a menu.
6
 */
7

    
8
// Include the database layer.
9
module_load_include('inc', 'taxonomy_menu', 'taxonomy_menu.database');
10

    
11
// Include the batch functions.
12
module_load_include('inc', 'taxonomy_menu', 'taxonomy_menu.batch');
13

    
14
/**
15
 * Implements hook_help().
16
 */
17
function taxonomy_menu_help($path, $arg) {
18
  switch ($path) {
19
    case 'admin/help#taxonomy_menu':
20
      $output = '';
21
      $output .= '<p>' . t('The Taxonomy Menu module transforms your taxonomy vocabularies into menus.') . '</p>';
22
      $output .= '<p>' . t('For more information, please visit the official <a href="@url">project page</a> on Drupal.org.', array('@url' => 'https://www.drupal.org/project/taxonomy_menu')) . '</p>';
23
      return $output;
24
  }
25
}
26

    
27
/**
28
 * Implements hook_form_alter().
29
 *
30
 * Modify the form at admin/content/taxonomy/edit/vocabulary/xx. We add
31
 * our taxonomy_menu options in here on a per-vocab basis.
32
 */
33
function taxonomy_menu_form_alter(&$form, &$form_state, $form_id) {
34
  if ($form_id == 'taxonomy_form_vocabulary') {
35
    // Do not alter on deletion.
36
    if (isset($form_state['confirm_delete']) && isset($form_state['values']['vid'])) {
37
      return;
38
    }
39
    // Choose a menu to add link items to.
40
    $menus = menu_get_menus();
41
    array_unshift($menus, t('- Disabled -'));
42

    
43
    // Options for path if tokens are not enabled.
44
    $paths = _taxonomy_menu_get_paths();
45

    
46
    $form['taxonomy_menu'] = array(
47
      '#type' => 'fieldset',
48
      '#collapsible' => TRUE,
49
      '#title' => t('Taxonomy menu'),
50
      '#weight' => 10,
51
      '#tree' => TRUE,
52
    );
53
    // This turns the vocab terms into menu items.
54
    $item['mlid'] = 0;
55

    
56
    $menu_items = menu_parent_options(menu_get_menus(), $item);
57

    
58
    array_unshift($menu_items, '= DISABLED =');
59

    
60
    // The vid isn't set when a new vocabulary is being created.
61
    if (isset($form['vid']['#value'])) {
62
      $default = variable_get(_taxonomy_menu_build_variable('vocab_menu', $form['vid']['#value']), NULL) . ':' .
63
                 variable_get(_taxonomy_menu_build_variable('vocab_parent', $form['vid']['#value']), NULL);
64
      if (!isset($menu_items[$default])) {
65
        $default = 0;
66
      }
67
    }
68
    else {
69
      $default = 0;
70
    }
71

    
72
    $form['taxonomy_menu']['vocab_parent'] = array(
73
      '#type' => 'select',
74
      '#title' => t('Menu location'),
75
      '#default_value' => $default,
76
      '#options' => $menu_items,
77
      '#description' => t('Taxonomy menu items will be inserted below the item selected here.'),
78
      '#attributes' => array('class' => array('menu-title-select')),
79
    );
80

    
81
    $form['taxonomy_menu']['path'] = array(
82
      '#type' => 'select',
83
      '#title' => t('Menu path type'),
84
      '#default_value' => isset($form['vid']['#value']) ? variable_get(_taxonomy_menu_build_variable('path', $form['vid']['#value']), 0) : 0,
85
      '#options' => $paths,
86
      '#description' => t('The path will be taxonomy/term/tid if <em>Default</em> has been selected.<br />The menu path will be passed through drupal_get_path_alias() function so all aliases will be applied.'),
87
    );
88

    
89
    // Get taxonomy menu form options.
90
    if (isset($form['vid']) && $form['vid']['#value']) {
91
      $vid = $form['vid']['#value'];
92
    }
93
    else {
94
      $vid = 0;
95
    }
96
    $form['taxonomy_menu']['options'] = _taxonomy_menu_create_options($vid);
97

    
98
    // Rebuild the menu.
99
    $form['taxonomy_menu']['options']['rebuild'] = array(
100
      '#type' => 'checkbox',
101
      '#title' => t('Rebuild the menu on submit'),
102
      '#default_value' => 0,
103
      '#weight' => 20,
104
      '#description' => t('<strong>Warning</strong>: This will delete then re-create all of the menu items. Only use this option if you are experiencing issues like missing menu items or other inconsistencies.'),
105
    );
106
    // Move the buttons to the bottom of the form.
107
    $form['submit']['#weight'] = 49;
108
    $form['delete']['#weight'] = 50;
109

    
110
    // Add an extra submit handler to save these settings.
111
    $form['#submit'][] = 'taxonomy_menu_vocab_submit';
112

    
113
  }
114
  elseif ($form_id == "taxonomy_overview_terms") {
115
    // Add an extra submit handler to sync the rearranged terms with menu.
116
    // @ TODO: using hook_taxonomy_vocabulary_update is nicer then callback,
117
    // But gives less info and does not always fire.
118
    $form['#submit'][] = 'taxonomy_menu_overview_submit';
119
  }
120
}
121

    
122
/**
123
 * Submit handler for the extra settings added to the taxonomy vocab form.
124
 *
125
 * Check to see if the user has selected a different menu, and only rebuild
126
 * if this is the case.
127
 */
128
function taxonomy_menu_vocab_submit($form, &$form_state) {
129
  $vid = $form_state['values']['vid'];
130
  $changed = FALSE;
131

    
132
  if (is_numeric($form_state['values']['taxonomy_menu']['vocab_parent'])) {
133
    // Menu location has been set to disabled, don't want to throw notices.
134
    $form_state['values']['taxonomy_menu']['vocab_parent'] = '0:0';
135
  }
136

    
137
  // Split the menu location into menu name and menu item id.
138
  list($vocab_parent['vocab_menu'], $vocab_parent['vocab_parent']) = explode(':', $form_state['values']['taxonomy_menu']['vocab_parent']);
139

    
140
  // Init flag variables to avoid notices if changes haven't happened.
141
  $changed_menu = FALSE;
142
  $change_vocab_item = FALSE;
143
  $changed_path = FALSE;
144

    
145
  // Set the menu name and check for changes.
146
  $variable_name = _taxonomy_menu_build_variable('vocab_menu', $vid);
147
  if (_taxonomy_menu_check_variable($variable_name, $vocab_parent['vocab_menu'])) {
148
    $changed_menu = TRUE;
149
  }
150
  variable_set($variable_name, $vocab_parent['vocab_menu']);
151

    
152
  // Set the menu parent item and check for changes.
153
  $variable_name = _taxonomy_menu_build_variable('vocab_parent', $vid);
154
  if (_taxonomy_menu_check_variable($variable_name, $vocab_parent['vocab_parent'])) {
155
    $changed_menu = TRUE;
156
  }
157
  variable_set($variable_name, $vocab_parent['vocab_parent']);
158

    
159
  // Set the path and check for changes.
160
  $variable_name = _taxonomy_menu_build_variable('path', $vid);
161
  if (_taxonomy_menu_check_variable($variable_name, $form_state['values']['taxonomy_menu']['path'])) {
162
    $changed_path = TRUE;
163
  }
164
  variable_set($variable_name, $form_state['values']['taxonomy_menu']['path']);
165

    
166
  foreach ($form_state['values']['taxonomy_menu']['options'] as $key => $value) {
167
    // Create the variable name
168
    $variable_name = _taxonomy_menu_build_variable($key, $vid);
169

    
170
    // Check to see if the vocab enable options has changed.
171
    if ($key == 'voc_item') {
172
      if (_taxonomy_menu_check_variable($variable_name, $value)) {
173
        $change_vocab_item = TRUE;
174
      }
175
    }
176

    
177
    // If $changed is already set to true, then don't bother checking any others.
178
    if (!$changed) {
179
      // Check to see if the variable has changed.
180
      if (_taxonomy_menu_check_variable($variable_name, $value)) {
181
        $changed = TRUE;
182
      }
183
    }
184
    // Save variable.
185
    variable_set($variable_name, $value);
186
  }
187

    
188
  // If the menu hasn't changed and the menu is disabled then do not do anything else.
189
  if ($form_state['values']['taxonomy_menu']['options']['rebuild'] ||
190
      $changed_menu ||
191
      (!$changed_menu && variable_get(_taxonomy_menu_build_variable('vocab_menu', $vid), FALSE) == 0)) {
192
    // Rebuild if rebuild is selected, menu has changed or vocabulary option changed.
193
    if ($form_state['values']['taxonomy_menu']['options']['rebuild'] || $changed_menu || $change_vocab_item || $changed_path) {
194
      $message = _taxonomy_menu_rebuild($vid);
195
    }
196
    // If setting has changed and a menu item is enabled, then update all of the menu items.
197
    elseif ($changed && variable_get(_taxonomy_menu_build_variable('vocab_menu', $vid), FALSE)) {
198
      $message = _taxonomy_menu_update_link_items($vid);
199
    }
200

    
201
    // Do a full menu rebuild in case we have removed the menu or moved it between menus.
202
    variable_set('menu_rebuild_needed', TRUE);
203
    // Only send a message if one has been created.
204
    if (isset($message) && $message) {
205
      // $message is sanitized coming out of its source function,
206
      // No need to reclean it here.
207
      drupal_set_message($message, 'status');
208
    }
209
  }
210
}
211

    
212
/**
213
 * Submit handler, reacting on form ID: taxonomy_overview_terms.
214
 */
215
function taxonomy_menu_overview_submit(&$form, &$form_state) {
216
  // Only sync if taxonomy_menu is enabled for this vocab and the 'sync'
217
  // option has been checked.
218

    
219
  // This form has the following flow of buttons:
220
  // 1. [Save] --> rebuild taxonomy_menu
221
  // 2. [Reset to alphabetical] --> no rebuild yet
222
  // 3. [Reset to alphabetical][Reset to alphabetical] --> rebuild
223
  // 4. [Reset to alphabetical][Cancel] --> no rebuild
224
  // The code below avoids rebuilding after situation 2.
225

    
226
  if ($form_state['rebuild'] == FALSE && isset($form['#vocabulary']->vid) ) {
227
    // Try to catch the 'Save' button.
228
    $vid = $form['#vocabulary']->vid;
229
  }
230
  elseif ($form_state['rebuild'] == TRUE && isset($form['#vocabulary']->vid) ) {
231
    // Try to catch the 'Reset to alphabetical' button.
232
    $vid = NULL;
233
  }
234
  elseif ($form_state['rebuild'] == FALSE && isset($form['vid']['#value']) ) {
235
    // Try to catch the second (confirming) 'Reset to alphabetical' button.
236
    $vid = $form['vid']['#value'];
237
  }
238
  else {
239
    // The button [Reset to alphabetical] [Cancel] does not call this page.
240
    $vid = NULL;
241
  }
242

    
243
  if (isset($vid)) {
244
    $menu_name = variable_get(_taxonomy_menu_build_variable('vocab_menu', $vid), 0);
245
    $sync = variable_get(_taxonomy_menu_build_variable('sync', $vid), 0);
246
    if ($menu_name && $sync) {
247
      // Update all menu items (do not rebuild the menu).
248
      $message = _taxonomy_menu_update_link_items($vid);
249

    
250
      // Report status.
251
      if (isset($message)) {
252
        // Message is sanitized coming out of _taxonomy_menu_update_link_items
253
        // no need to reclean it here.
254
        drupal_set_message($message, 'status');
255
      }
256

    
257
      // Rebuild the menu.
258
      menu_cache_clear($menu_name);
259
    }
260
  }
261
}
262

    
263
/**
264
 * Rebuilds a menu.
265
 *
266
 * @param int $vid
267
 *   Vocabulary ID.
268
 *
269
 * @return string
270
 *   Message that is displayed.
271
 */
272
function _taxonomy_menu_rebuild($vid) {
273
  // Remove all of the menu items for this vocabulary.
274
  _taxonomy_menu_delete_all($vid);
275

    
276
  // Only insert the links if a menu is set.
277
  if (variable_get(_taxonomy_menu_build_variable('vocab_menu', $vid), FALSE)) {
278
    _taxonomy_menu_insert_link_items($vid);
279
    menu_rebuild();
280
    return t('The Taxonomy Menu has been rebuilt.');
281
  }
282

    
283
  menu_rebuild();
284
  return t('The Taxonomy Menu has been removed.');
285
}
286

    
287
/**
288
 * Checks to see if the variable has changed.
289
 *
290
 * @param string $variable
291
 *   Name of variable.
292
 *
293
 * @return bool
294
 *   TRUE if it has changed
295
 */
296
function _taxonomy_menu_check_variable($variable, $new_value) {
297
  if ($new_value != variable_get($variable, FALSE)) {
298
    return TRUE;
299
  }
300
  return FALSE;
301
}
302

    
303
/**
304
 * Updates the menu items.
305
 *
306
 * @param $vid
307
 *   Vocabulary ID.
308
 */
309
function _taxonomy_menu_update_link_items($vid) {
310
  $menu_name = variable_get(_taxonomy_menu_build_variable('vocab_menu', $vid), FALSE);
311
  $depth = variable_get(_taxonomy_menu_build_variable('max_depth', $vid), 0);
312

    
313
  // Get a list of the current tid - menu_link combinations.
314
  $menu_links = _taxonomy_menu_get_menu_items($vid);
315

    
316
  // Cycle through the menu links.
317
  foreach ($menu_links as $tid => $mlid) {
318
    if (!_taxonomy_menu_term_too_deep($tid, $depth))
319
    // $args must be reset each time through.
320
    $args = array(
321
      'menu_name' => $menu_name,
322
      'mlid' => $mlid,
323
    );
324

    
325
    if ($tid == 0) {
326
      $args['vid'] = $vid;
327
    }
328
    else {
329
      $args['term'] = taxonomy_term_load($tid);
330
    }
331

    
332
    // Update the menu link.
333
    taxonomy_menu_handler('update', $args);
334
  }
335

    
336
  return t('The Taxonomy Menu %menu_name has been updated.', array('%menu_name' => $menu_name));
337
}
338

    
339
/**
340
 * Creates new link items for the vocabulary.
341
 *
342
 * @param $vid
343
 *   Vocabulary ID.
344
 */
345
function _taxonomy_menu_insert_link_items($vid) {
346
  $menu_name = variable_get(_taxonomy_menu_build_variable('vocab_menu', $vid), FALSE);
347
  // Check to see if we should had a vocab item.
348
  if (variable_get(_taxonomy_menu_build_variable('voc_item', $vid), FALSE)) {
349
      $args = array(
350
        'vid' => $vid,
351
        'menu_name' => $menu_name,
352
      );
353
      taxonomy_menu_handler('insert', $args);
354
    }
355
  // Let batch api take care of inserting the menu items.
356
  _taxonomy_menu_insert_link_items_batch($vid);
357
}
358

    
359
/**
360
 * Implements hook_taxonomy_vocabulary_delete().
361
 */
362
function taxonomy_menu_taxonomy_vocabulary_delete($vocabulary) {
363
  // Delete the menu items for this vocab.
364
  _taxonomy_menu_delete_all($vocabulary->vid);
365
  $menu_name = variable_get(_taxonomy_menu_build_variable('vocab_menu', $vocabulary->vid), 0);
366
  menu_cache_clear($menu_name);
367

    
368
  // Delete all the variables for this vocab.
369
  $variable_prefixes = array(
370
    'taxonomy_menu_vocab_menu_',
371
    'taxonomy_menu_vocab_parent_',
372
    'taxonomy_menu_voc_item_',
373
    'taxonomy_menu_display_num_',
374
    'taxonomy_menu_hide_empty_terms_',
375
    'taxonomy_menu_expanded_',
376
    'taxonomy_menu_rebuild_',
377
    'taxonomy_menu_path_',
378
    'taxonomy_menu_menu_end_all_',
379
    'taxonomy_menu_display_descendants_',
380
    'taxonomy_menu_voc_name_',
381
    'taxonomy_menu_sync_',
382
  );
383
  foreach ($variable_prefixes as $prefix) {
384
    variable_del($prefix . $vocabulary->name);
385
  }
386
}
387

    
388
/**
389
 * Implements hook_taxonomy_term_insert($term).
390
 */
391
function taxonomy_menu_taxonomy_term_insert($term) {
392
  _taxonomy_menu_taxonomy_termapi_helper($term, 'insert');
393
}
394

    
395
/**
396
 * Implements hook_taxonomy_term_update().
397
 */
398
function taxonomy_menu_taxonomy_term_update($term) {
399
  _taxonomy_menu_taxonomy_termapi_helper($term, 'update');
400
}
401

    
402
/**
403
 * Implements hook_taxonomy_term_delete().
404
 */
405
function taxonomy_menu_taxonomy_term_delete($term) {
406
  _taxonomy_menu_taxonomy_termapi_helper($term, 'delete');
407
}
408

    
409
/**
410
 * Implements hook_node_insert().
411
 */
412
function taxonomy_menu_node_insert($node) {
413
  $terms_old = &drupal_static('taxonomy_menu_terms_old');
414
  // We use this direct table pull to avoid the cache and because
415
  // free tags are not formatted in a matter where extrating the
416
  // tid's is easy.
417
  $terms_new = _taxonomy_menu_get_node_terms($node);
418

    
419
  // Merge current terms and previous terms to update both menu items.
420
  $terms = array_unique(array_merge((array)$terms_new, (array)$terms_old));
421
  _taxonomy_menu_nodeapi_helper('insert', $terms, $node);
422
}
423

    
424
/**
425
 * Implements hook_node_update().
426
 */
427
function taxonomy_menu_node_update($node) {
428
  if (isset($node->original->status) and $node->original->status != $node->status) {
429
    $terms_old = &drupal_static('taxonomy_menu_terms_old');
430
    // We use this direct table pull to avoid the cache and because
431
    // free tags are not formatted in a matter where extracting the
432
    // tid's is easy.
433
    $terms_new = _taxonomy_menu_get_node_terms($node);
434

    
435
    // Merge current terms and previous terms to update both menu items.
436
    $terms = array_unique(array_merge((array)$terms_new, (array)$terms_old));
437
    _taxonomy_menu_nodeapi_helper('update', $terms, $node);
438
  }
439
}
440

    
441
/**
442
 * Implements hook_node_presave().
443
 */
444
function taxonomy_menu_node_presave($node) {
445
  $terms_old = &drupal_static('taxonomy_menu_terms_old');
446
  // Get the terms from the database before the changes are made. These will be
447
  // used to update the menu item's name if needed we go directly to the db to
448
  // bypass any caches.
449
  if (isset($node->nid)) {
450
    $node_old = node_load($node->nid);
451
    $terms_old = _taxonomy_menu_get_node_terms($node_old);
452
  }
453
  else {
454
    $terms_old = array();
455
  }
456
}
457

    
458
/**
459
 * Implements hook_node_delete().
460
 */
461
function taxonomy_menu_node_delete($node) {
462
  // Since the delete operation is run after the data is deleted pull the terms
463
  // from the node object.
464
  $terms =  _taxonomy_menu_get_node_terms($node);
465
  _taxonomy_menu_nodeapi_helper('delete', $terms, $node);
466
}
467

    
468
/**
469
 * Abstraction of hook_taxonomy_term_<operation>()
470
 */
471
function _taxonomy_menu_taxonomy_termapi_helper($term, $operation) {
472
  // Only sync if taxonomy_menu is enabled for this vocab and the 'sync'
473
  // option has been checked.
474
  $menu_name = variable_get(_taxonomy_menu_build_variable('vocab_menu', $term->vid), 0);
475
  $sync = variable_get(_taxonomy_menu_build_variable('sync', $term->vid), 0);
476
  $depth = variable_get(_taxonomy_menu_build_variable('max_depth', $term->vid), 0);
477

    
478
  if ($menu_name && $sync && !_taxonomy_menu_term_too_deep($term->tid, $depth)) {
479
    $item = array(
480
      'tid' => $term->tid,
481
      'vid' => $term->vid,
482
      'term' => $term,
483
      'menu_name' => $menu_name,
484
      'mlid' => _taxonomy_menu_get_mlid($term->tid, $term->vid),
485
    );
486

    
487
    switch ($operation) {
488
      case 'insert':
489
        $text = 'Added term %term to taxonomy menu %menu_name.';
490
        break;
491
      case 'update':
492
        $text = 'Updated term %term in taxonomy menu %menu_name.';
493
        break;
494
      case 'delete':
495
        $text = 'Deleted term %term from taxonomy menu %menu_name.';
496
        break;
497
    }
498
    $message = t($text, array('%term' => $term->name, '%menu_name' => $menu_name));
499

    
500
    // Run function.
501
    taxonomy_menu_handler($operation, $item);
502

    
503
    // Report status.
504
    drupal_set_message($message, 'status');
505

    
506
    // Rebuild the menu.
507
    menu_cache_clear($menu_name);
508
  }
509
}
510

    
511
/**
512
 * Builds argument arrays calls taxonomy_menu_handler.
513
 *
514
 * @param string $op
515
 *   The operation to be performed [update|insert|delete]
516
 * @param array $terms
517
 *   The taxonomy terms.
518
 * @param $node
519
 *   The node object.
520
 */
521
function _taxonomy_menu_nodeapi_helper($op, $terms = array(), $node) {
522
  foreach ($terms as $key => $tid) {
523
    // If taxonomy $term is false, then go to the next $term.
524
    // taxonomy_term_load($tid) returns FALSE if the term was not found.
525
    if (!$term = taxonomy_term_load($tid)) {
526
      continue;
527
    }
528

    
529
    // Update the menu for each term if necessary.
530
    $menu_name = variable_get(_taxonomy_menu_build_variable('vocab_menu', $term->vid), FALSE);
531
    $vocb_sync = variable_get(_taxonomy_menu_build_variable('sync', $term->vid), TRUE);
532
    $menu_num = variable_get(_taxonomy_menu_build_variable('display_num', $term->vid), TRUE);
533
    $menu_num_inc_children = variable_get(_taxonomy_menu_build_variable('display_num_incl_children', $term->vid), TRUE);
534
    $hide_empty = variable_get(_taxonomy_menu_build_variable('hide_empty_terms', $term->vid), FALSE);
535
    if ($menu_name && $vocb_sync && ($menu_num || $hide_empty)) {
536
      // Build argument array to save menu_item.
537
      $args = array(
538
        'tid' => $term->tid,
539
        'vid' => $term->vid,
540
        'term' => $term,
541
        'menu_name' => $menu_name,
542
        'mlid' => _taxonomy_menu_get_mlid($term->tid, $term->vid),
543
      );
544

    
545
      if ($op == 'delete') {
546
        /* Turn the op to 'update' here since we really do want to update the item
547
        * and not delete/recreate it, since the latter will break hierarchy and
548
        * customizations.
549
        */
550
        $op = 'update';
551
      }
552

    
553
      taxonomy_menu_handler($op, $args, $node);
554
      if ($hide_empty || $menu_num && $menu_num_inc_children) {
555
        _taxonomy_menu_update_all_parents($term, $menu_name);
556
      }
557
    }
558
  }
559
}
560

    
561
/**
562
 * Updates all parent items.
563
 *
564
 * @param string $op
565
 *   options are 'insert', 'update', 'delete' or path.
566
 * @param $node
567
 *   The node object.
568
 */
569
function _taxonomy_menu_update_all_parents($term, $menu_name) {
570
  $parents = taxonomy_get_parents($term->tid);
571
  if ($parents) {
572
    foreach ($parents as $parent) {
573
      $parent->parents = array_keys(taxonomy_get_parents($parent->tid));
574
      $item = array(
575
        'term' => $parent,
576
        'menu_name' => $menu_name,
577
        'mlid' => _taxonomy_menu_get_mlid($parent->tid, $parent->vid),
578
        'remove' => FALSE,
579
      );
580
      taxonomy_menu_handler('update', $item);
581
      _taxonomy_menu_update_all_parents($parent, $menu_name);
582
    }
583
  }
584
}
585

    
586
/**
587
 * Taxonomy Menu Handler: Creates a menu item for each taxonomy term.
588
 *
589
 * @param $op
590
 *   options are 'insert', 'update', 'delete' or path.
591
 * @param $args
592
 *  if $op == 'insert' then args is an array with the following key/value pairs:
593
 *     'term': taxonomy term object,
594
 *     'menu_name' : menu that the item is set to apply to
595
 *  if $op == 'delete' then then args is an array with the following key/value pairs:
596
 *     'tid': TermID
597
 *     'mlid': Menu ID
598
 *  if $op == 'update' then then args is an array with the following key/value pairs:
599
 *     'term': term object,
600
 *     'menu_name': menu that the item is set to apply to
601
 *     'mlid': Menu ID
602
 * @param $node
603
 *   The node object.
604
 * @param $item array
605
 *   Taxonomy menu item.
606
 *
607
 * @return array
608
 *   Menu link ID for the taxonomy menu item.
609
 */
610
function taxonomy_menu_handler($op, $args = array(), $node = NULL, $item = array()) {
611
  // Get the initial $item.
612
  if (empty($item)) {
613
    $item = _taxonomy_menu_create_item($args, $node);
614
  }
615

    
616
  // Let other modules make edits.
617
  $hook = 'taxonomy_menu_' . $op;
618
  foreach (module_implements($hook) as $module) {
619
    $function = $module . '_' . $hook;
620
    $function($item);
621
  }
622

    
623
  // Update the menu and return the mlid if the remove element is not true.
624
  if ($op != 'delete') {
625
    return _taxonomy_menu_save($item);
626
  }
627
}
628

    
629
/**
630
 * Adds/Updates a taxonomy menu item.
631
 *
632
 * We use a custom data array $item as a parameter, instead of using a
633
 * standard taxonomy $term object. This is because this function is also
634
 * called from hook_taxonomy(), which doesn't have a $term object. Rather
635
 * have one consistent method of passing the data.
636
 *
637
 * @param $item
638
 *   array with the following key/value pairs:
639
 *     'tid' => the term id (if 0 then adding the vocab as an item)
640
 *     'name' => the term's name
641
 *     'description' => term description, used as to build the title attribute
642
 *     'weight' => term weight
643
 *       (This will be overriden by the order created from taxonomy_get_tree which respects the correct wight)
644
 *     'vid' => the vocabulary's id
645
 *     'ptid' => the term's parent's term id
646
 *     'menu_name' => the menu that the link item will be inserted into
647
 *     'mlid' => if this is filled in then the mlid will be updated
648
 */
649
function _taxonomy_menu_save($item) {
650
  if (empty($item)) return;
651

    
652
  $insert = TRUE;
653

    
654
  $flatten_menu = variable_get(_taxonomy_menu_build_variable('flat', $item['vid']));
655
  // Child items should appear around the parent/root, so set their weight
656
  // equal to the root term's weight.
657
  if ($flatten_menu) {
658
    $item['weight'] = $item['root_term_weight'];
659
  }
660

    
661
  // create the path.
662
  $path = taxonomy_menu_create_path($item['vid'], $item['tid']);
663
  // Get the parent mlid: this is either:
664
  // - the parent tid's mlid
665
  // - the vocab menu item's mlid
666
  // - the menu parent setting for this vocab
667
  $plid = _taxonomy_menu_get_mlid($item['ptid'], $item['vid']);
668
  if (!$plid || $flatten_menu) {
669
    $plid = variable_get(_taxonomy_menu_build_variable('vocab_parent', $item['vid']), NULL);
670
  }
671

    
672
  // Make sure the path has less then 256 characters.
673
  if (drupal_strlen($path) > 256) {
674
    preg_match('/(.{256}.*?)\b/', $path, $matches);
675
    $path = rtrim($matches[1]);
676
  }
677

    
678
  $link = array(
679
    'link_title' => $item['name'],
680
    'menu_name' => $item['menu_name'],
681
    'plid' => $plid,
682
    'weight' => $item['weight'],
683
    'module' => 'taxonomy_menu',
684
    'expanded' => variable_get(_taxonomy_menu_build_variable('expanded', $item['vid']), TRUE),
685
    'link_path' => $path,
686
  );
687

    
688
  // Be sure to load the original menu link to preserve non-standard properties.
689
  if (isset($item['mlid']) && !empty($item['mlid']) && $original_link = menu_link_load($item['mlid'])) {
690
    $link = array_merge($original_link, $link);
691
  }
692
  else {
693
    $link['options'] = array(
694
      'attributes' => array(
695
        'title' => trim($item['description']) ? $item['description'] : $item['name'],
696
      ),
697
    );
698
  }
699

    
700
  // Add setup the query paramater in the URL correctly.
701
  if (strpos($path, '?') !== FALSE) {
702
    $split = explode('?', $path);
703
    if (strpos($split[1], '?') !== FALSE) {
704
      // the query split didn't work, too many question marks
705
      // error?
706
    }
707
    else {
708
      parse_str($split[1], $link['options']['query']);
709
      $link['link_path'] = $split[0];
710
    }
711
  }
712

    
713
  // If passed a mlid then add it.
714
  if (isset($item['mlid']) && $item['mlid']) {
715
    $link['mlid'] = $item['mlid'];
716
    $insert = FALSE;
717
    $menu_link = menu_link_load($item['mlid']);
718
    $is_hidden = $menu_link['hidden'];
719
  }
720
  else {
721
    $is_hidden = 0;
722
  }
723

    
724
  // @todo i18nmenu needs to be cleaned up to allow translation from other menu modules.
725
  if (module_exists('i18n_menu')) {
726
    $link['options']['alter'] = TRUE;
727
    $link['language'] = $item['language'];
728
    $link['customized'] = 1;
729
  }
730

    
731
  // Set the has_children property.
732
  // If tid=0 then adding a vocab item and had children.
733
  // If the term has any children then set it to true.
734
  if ($item['tid'] == 0) {
735
    $link['has_children'] = 1;
736
  }
737
  else {
738
    $children = taxonomy_get_children($item['tid']);
739
    if (!empty($children)) {
740
      $link['has_children'] = 1;
741
    }
742
  }
743

    
744
  // If remove is true then set hidden to 1.
745
  $link['hidden'] = (isset($item['remove']) && $item['remove']) ? 1 : $is_hidden;
746

    
747
  // Save the menu item.
748
  if ($mlid = menu_link_save($link)) {
749
    // if inserting a new menu item then insert a record into the table.
750
    if ($insert) {
751
      _taxonomy_menu_insert_menu_item($mlid, $item['tid'], $item['vid']);
752
    }
753
    return $mlid;
754
  }
755
  else {
756
    drupal_set_message(t('Could not save the menu link for the taxonomy menu.'), 'error');
757
    return FALSE;
758
  }
759
}
760

    
761
/**
762
 * Create the path to use in the menu item.
763
 *
764
 * @return array
765
 *   Path selections.
766
 */
767
function _taxonomy_menu_get_paths() {
768
  return module_invoke_all('taxonomy_menu_path');
769
}
770

    
771
/**
772
 * Creates the path for the vid/tid combination.
773
 *
774
 * @param $vid
775
 *   Vocablary ID.
776
 * @param $tid
777
 *   Taxonomy term ID.
778
 *
779
 * @return string
780
 *   Path
781
 */
782
function taxonomy_menu_create_path($vid, $tid) {
783
  // Get the path function for this vocabulary.
784
  $function = variable_get(_taxonomy_menu_build_variable('path', $vid), 'taxonomy_menu_path_default');
785
  // Run the function.
786
  return $function($vid, $tid);
787
}
788

    
789
/**
790
 * Implements hook_taxonomy_menu_path().
791
 *
792
 * @return array
793
 *   A list of the path options in the form: function_name => Display Title.
794
 *
795
 * @see _taxonomy_menu_get_paths().
796
 */
797
function taxonomy_menu_taxonomy_menu_path() {
798
  $output = array(
799
    'taxonomy_menu_path_default' => t('Default'),
800
  );
801

    
802
  return $output;
803
}
804

    
805
/**
806
 * Callback for hook_taxonomy_menu_path.
807
 */
808
function taxonomy_menu_path_default($vid, $tid) {
809
  // If tid = 0 then we are creating the vocab menu item format will be taxonomy/term/$tid+$tid+$tid...
810
  if ($tid == 0) {
811
    // Get all of the terms for the vocab.
812
    $vtids = _taxonomy_menu_get_terms($vid);
813
    $end = implode('/', $vtids);
814
    $path = "taxonomy/term/$end";
815
  }
816
  else {
817
    $path = 'taxonomy/term/' . $tid;
818
    if (variable_get(_taxonomy_menu_build_variable('display_descendants', $vid), FALSE)) {
819
      // Use 'all' at the end of the path.
820
      if (variable_get(_taxonomy_menu_build_variable('end_all', $vid), FALSE)) {
821
        $path .= '/all';
822
      }
823
      else {
824
        // We wait to run this instead of during the if above because we only
825
        // want to run it once.
826
        $terms = taxonomy_get_tree($vid, $tid);
827
        foreach ($terms as $term) {
828
          $tids[] = $term->tid;
829
        }
830
        if (isset($tids)) {
831
          $end = implode('/', $tids);
832
          $path .= '/ ' . $end;
833
        }
834
      }
835
    }
836
  }
837

    
838
  return $path;
839
}
840

    
841
/**
842
 * Implements hook_taxonomy_menu_delete().
843
 *
844
 * @param array $item
845
 *   Taxonomy menu item array, containing the following key/value pairs:
846
 *     'vid': Vocabulary ID.
847
 *     'tid': Taxonomy term ID.
848
 *     'mlid': Menu link ID.
849
 */
850
function taxonomy_menu_taxonomy_menu_delete(&$item) {
851
  menu_link_delete($item['mlid']);
852
  _taxonomy_menu_delete_item($item['vid'], $item['tid']);
853
  unset($item['mlid']);
854
}
855

    
856
/**
857
 * Creates the initial $item array.
858
 *
859
 * @param $args
860
 *   array with the following key/value pairs:
861
 *     'term': Taxonomy term object, if updating a term.
862
 *     'menu_name': menu that the item is set to apply to.
863
 *     'vid': Vocabuary id, if editing vocab item.
864
 *     'mlid': Menu link id.
865
 *
866
 * @param $node
867
 *   The node object.
868
 */
869
function _taxonomy_menu_create_item($args = array(), $node) {
870
  // If tid = 0, then we are creating a vocab item.
871
  if (isset($args['tid']) && isset($args['vid']) && $args['tid'] == 0 && variable_get(_taxonomy_menu_build_variable('voc_item', $args['vid']), 0)) {
872
    $vocab = taxonomy_vocabulary_load($args['vid']);
873
    $item = array(
874
      'tid' => 0,
875
      'name' => $vocab->name,
876
      'description' => variable_get(_taxonomy_menu_build_variable('voc_item_description', $args['vid']), 0) ? $vocab->description : '',
877
      'weight' => $vocab->weight,
878
      'vid' => $args['vid'],
879
      'ptid' => 0,
880
      'root_term_weight' => $vocab->weight,
881
      'menu_name' => $args['menu_name'],
882
      'language' => $vocab->language,
883
    );
884
  }
885
  else {
886
    // If tid <> 0 then we are creating a term item.
887
    $term = $args['term'];
888

    
889
    // Sometimes $term->parents is not set so we find it.
890
    if (empty($term->parents)) {
891
      $term->parents = _taxonomy_menu_get_parents($term->tid);
892
      if (empty($term->parents)) {
893
        // Even without parents, create one with $ptid = 0.
894
        $term->parents = array(0 => '0');
895
      }
896
    }
897

    
898
    // Find the weight of the root taxonomy term; we'll need it in case we want
899
    // a flat taxonomy menu.
900
    if (is_object($term)) {
901
      $term_parents = taxonomy_get_parents_all($term->tid);
902
      $root_term_weight = ($term_parents) ? $term_parents[count($term_parents) - 1]->weight : 0;
903
    }
904
    else {
905
      $root_term_weight = 0;
906
    }
907

    
908
    foreach ($term->parents as $parent) {
909
      $ptid = $parent;
910
      // Turn the term into the correct $item array form.
911
      $item = array(
912
        'term' => $term,
913
        'tid' => $term->tid,
914
        'name' => $term->name,
915
        'description' => variable_get(_taxonomy_menu_build_variable('term_item_description', $term->vid), 0) ? $term->description : '',
916
        'weight' => !empty($term->weight) ? $term->weight : 0,
917
        'vid' => $term->vid,
918
        'ptid' => $ptid,
919
        'root_term_weight' => $root_term_weight,
920
        'menu_name' => $args['menu_name'],
921
        'language' => isset($term->language) ? $term->language : ($node ? $node->language : $GLOBALS['language']->language),
922
      );
923
      if (isset($args['mlid'])) {
924
        $item['mlid'] = $args['mlid'];
925
      }
926
      // Mutiple parents are not supported yet. Without the break, the item is
927
      // inserted multiple under one parent, instead of once under each parent.
928
      break;
929
    }
930
  }
931

    
932
  return $item;
933
}
934

    
935
/**
936
 * Helper function: See if any of the children have any nodes.
937
 *
938
 * @param $tid
939
 *   Taxonomy term ID.
940
 * @param $vid
941
 *   Vocabulary ID.
942
 *
943
 * @return boolean
944
 */
945
function _taxonomy_menu_children_has_nodes($tid, $vid, $return = FALSE) {
946
  $children = taxonomy_get_children($tid, $vid);
947
  foreach ($children as $tid => $term) {
948
    if (_taxonomy_menu_term_count($tid) > 0) {
949
      $return = TRUE;
950
    }
951
    else {
952
      $return = _taxonomy_menu_children_has_nodes($tid, $vid, $return);
953
    }
954
  }
955
  return $return;
956
}
957

    
958
/**
959
 * Helper function: Inserts and updates menu along with taxonomy changes.
960
 *
961
 * @param array $item
962
 *   Taxonomy menu item.
963
 *
964
 * @return array
965
 *   Taxonomy menu item.
966
 */
967
function _taxonomy_menu_item($item) {
968
  if (empty($item)) return;
969

    
970
  // If tid is 0 then do not change any settings.
971
  if ($item['tid'] > 0) {
972
    // Get the number of node attached to this term.
973
    $num = _taxonomy_menu_term_count($item['tid']);
974

    
975
    // If hide menu is selected and the term count is 0 and the term has no
976
    // children then do not create the menu item.
977
    if ($num == 0 &&
978
      variable_get(_taxonomy_menu_build_variable('hide_empty_terms', $item['vid']), FALSE) &&
979
      !_taxonomy_menu_children_has_nodes($item['tid'], $item['vid'])) {
980
        $item['remove'] = TRUE;
981
        return $item;
982
    }
983

    
984
    // If display number is selected and $num > 0 then change the title.
985
    if (variable_get(_taxonomy_menu_build_variable('display_num', $item['vid']), FALSE)) {
986
      // If number > 0 and display include children num, then count all of the children.
987
      if (variable_get(_taxonomy_menu_build_variable('display_num_incl_children', $item['vid']), TRUE)) {
988
        $num = taxonomy_menu_term_count_nodes($item['tid'], $item['vid']);
989
      }
990
      $item['name'] .= " ($num)";
991
    }
992
  }
993
  elseif ($item['tid'] == 0) {
994
    // If custom name is provided, use that name.
995
    $custom_name = variable_get(_taxonomy_menu_build_variable('voc_name', $item['vid']), '');
996
    if (!empty($custom_name)) {
997
      $item['name'] = $custom_name;
998
    }
999
  }
1000

    
1001
  return $item;
1002
}
1003

    
1004
/**
1005
 * Calculates the number of nodes linked to the term and all children.
1006
 *
1007
 * @param int $tid
1008
 *   Taxonomy term ID.
1009
 * @param int $vid
1010
 *   Vocabulary ID.
1011
 *
1012
 * @return int
1013
 *   Count for how many nodes are in that taxonomy category.
1014
 */
1015
function taxonomy_menu_term_count_nodes($tid, $vid, $count = 0) {
1016
  $count += _taxonomy_menu_term_count($tid);
1017
  $children = taxonomy_get_children($tid, $vid);
1018
  foreach ($children as $tid => $term) {
1019
    $count = taxonomy_menu_term_count_nodes($term->tid, $term->vid, $count);
1020
  }
1021
  return $count;
1022
}
1023

    
1024
/**
1025
 * Implements hook_taxonomy_menu_insert().
1026
 *
1027
 * @param array $item
1028
 *   Taxonomy menu item array with the following key/value pairs:
1029
 *     'tid': The term id (if 0 then updating the vocab as an item).
1030
 *     'name': New menu name.
1031
 *     'description': New menu description, used for the title attribute.
1032
 *     'weight': New menu weight.
1033
 *     'vid': The new vocabulary's id.
1034
 *     'ptid': The new parent tid.
1035
 *     'remove': If this is set to TRUE then the $item is not added as a menu.
1036
 *
1037
 * @return array $item
1038
 *   Taxonomy menu item.
1039
 */
1040
function taxonomy_menu_taxonomy_menu_insert(&$item) {
1041
  $item = _taxonomy_menu_item($item);
1042
}
1043

    
1044
/**
1045
 * Implements hook_taxonomy_menu_update().
1046
 *
1047
 * @param array $item
1048
 *   Taxonomy menu item array with the following key/value pairs:
1049
 *     'tid': The term id (if 0 then updating the vocab as an item).
1050
 *     'name': New menu name.
1051
 *     'description': New menu description, used for the title attribute.
1052
 *     'weight': New menu weight.
1053
 *     'vid': The new vocabulary's id.
1054
 *     'ptid': The new parent tid.
1055
 *     'remove': If this is set to TRUE then the $item is not added as a menu.
1056
 */
1057
function taxonomy_menu_taxonomy_menu_update(&$item) {
1058
  $item = _taxonomy_menu_item($item);
1059
}
1060

    
1061
/**
1062
 *Creates a form array of taxonomy menu options.
1063
 * Invokes hook_taxonomy_menu_options().
1064
 *
1065
 * @param $vid
1066
 *   Vocabulary ID.
1067
 *
1068
 * @return array
1069
 *   Form array.
1070
 */
1071
function _taxonomy_menu_create_options($vid) {
1072
  $options = module_invoke_all('taxonomy_menu_options');
1073

    
1074
  // Cycle through field.
1075
  foreach ($options as $field_name => $field_elements) {
1076
    // Cycle through each value of the field.
1077
    $variable_name = _taxonomy_menu_build_variable($field_name, $vid);
1078

    
1079
    // If the variable is set then use that, if the default key is set then use that,
1080
    // otherwise use FALSE.
1081
    $options[$field_name]['#default_value'] =
1082
      variable_get($variable_name,
1083
      !empty($options[$field_name]['default']) ? $options[$field_name]['default'] : FALSE);
1084

    
1085
    // Set the type to checkbox if it is empty.
1086
    if (empty($options[$field_name]['#type'])) {
1087
      $options[$field_name]['#type'] = 'checkbox';
1088
    }
1089

    
1090
    // Set the options.
1091
    $options['#type'] = 'container';
1092

    
1093
    // Remove the default value from the array so we don't pass it to the form.
1094
    unset($options[$field_name]['default']);
1095
  }
1096

    
1097
  return $options;
1098
}
1099

    
1100
/**
1101
 * Builds a variable from the supplied name and machine name of the vocabulary.
1102
 *
1103
 * @param string $name
1104
 *   Name to be added to the returned variable.
1105
 * @param $vid
1106
 *  VID of the vocabulary from which the machine name will be taken.
1107
 *
1108
 * @return bool|string
1109
 */
1110
function _taxonomy_menu_build_variable($name, $vid) {
1111
  $vocabulary = taxonomy_vocabulary_load($vid);
1112
  if ($vocabulary) {
1113
    return 'taxonomy_menu_' . $name . '_' . $vocabulary->machine_name;
1114
  }
1115
  else {
1116
    return FALSE;
1117
  }
1118
}
1119

    
1120
/**
1121
 * Implements hook_taxonomy_menu_options().
1122
 */
1123
function taxonomy_menu_taxonomy_menu_options() {
1124
  $options['sync'] = array(
1125
    '#title' => t('Synchronise changes to this vocabulary'),
1126
    '#description' => t('Every time a term is added/deleted/modified, the corresponding menu link will be altered too.'),
1127
    'default' => TRUE,
1128
  );
1129

    
1130
  $options['max_depth'] = array(
1131
   '#type' => 'select',
1132
   '#title' => t('Max depth'),
1133
   '#description' => t('Limit how many levels of the taxonomy tree to process. Useful if you have a very large tree of taxonomy terms, and only want to provide a menu for the first several levels.'),
1134
   '#options' => array(0 => t('All'), 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9),
1135
   'default' => 0,
1136
  );
1137

    
1138
  $options['display_num'] = array(
1139
    '#title' => t('Display the number of items in each taxonomy term.'),
1140
    'default' => FALSE,
1141
  );
1142

    
1143
  $options['display_num_incl_children'] = array(
1144
    '#title' => t('Include items belonging to child terms in number counts'),
1145
    '#description' => t('Items belonging to the child terms will be counted when performing item count calculations.'),
1146
    '#states' => array(
1147
      'visible' => array(
1148
        ':input[name="taxonomy_menu[options][display_num]"]' => array(
1149
          'checked' => TRUE,
1150
        ),
1151
      ),
1152
    ),
1153
    'default' => TRUE,
1154
  );
1155

    
1156
  $options['hide_empty_terms'] = array(
1157
    '#title' => t('Do not add a menu link for taxonomy terms with no items.'),
1158
    'default' => FALSE,
1159
  );
1160

    
1161
  $options['voc_item'] = array(
1162
    '#title' => t('Include the vocabulary name as the top level menu item of the taxonomy menu.'),
1163
    'default' => FALSE,
1164
    '#disabled' => TRUE,
1165
  );
1166

    
1167
  $options['voc_item_description'] = array(
1168
    '#title' => t('Add the vocabulary description to the vocabulary menu item.'),
1169
    'default' => FALSE,
1170
    '#access' => FALSE,
1171
  );
1172

    
1173
  $options['term_item_description'] = array(
1174
    '#title' => t('Add the taxonomy term description to the term menu item.'),
1175
    'default' => FALSE,
1176
  );
1177

    
1178
  $options['expanded'] = array(
1179
    '#title' => t('Automatically show all menu items as expanded.'),
1180
    'default' => TRUE,
1181
  );
1182

    
1183
  $options['flat'] = array(
1184
    '#title' => t('Add all menu items to the same level rather than retaining term hierarchy.'),
1185
    'default' => FALSE,
1186
  );
1187

    
1188
  $options['voc_name'] = array(
1189
    '#type' => 'textfield',
1190
    '#title' => t('Custom name for vocabulary item'),
1191
    '#description' => t('Changes the name of the vocabulary item (if enabled above). Leave blank to use the name of the vocabulary.'),
1192
    'default' => '',
1193
    '#disabled' => TRUE,
1194
  );
1195

    
1196
  $options['display_descendants'] = array(
1197
    '#title' => t('Display descendants: change the path to taxonomy/term/tid+tid+tid for all terms thave have child terms.'),
1198
    'default' => FALSE,
1199
  );
1200

    
1201
  $options['end_all'] = array(
1202
    '#title' => t("Use 'all' at the end of URL"),
1203
    'default' => FALSE,
1204
    '#description' => t('This changes tid+tid+tid to "All" in term when <em>Display descendants</em> has been selected.<br />Only used if <em>Menu path type</em> is "Default path".<br />Works with default taxonomy page.'),
1205
    '#disabled' => TRUE,
1206
  );
1207

    
1208
  return $options;
1209
}
1210

    
1211
/**
1212
 * Implements hook_translated_menu_link_alter().
1213
 *
1214
 * Translate menu links on the fly by using term translations.
1215
 */
1216
function taxonomy_menu_translated_menu_link_alter(&$item, $map) {
1217
  if (module_exists('i18n_taxonomy')) {
1218
    // In case of localized terms, use term translation for menu title.
1219
    if ($item['module'] == 'taxonomy_menu') {
1220
      $t = _taxonomy_menu_get_item($item['mlid']);
1221
      // Only translate when term exist (may occur with stray menu item).
1222
      if ($t) {
1223
        // Only translate when translation mode is set to localize.
1224
        if (i18n_taxonomy_vocabulary_mode($t->vid, I18N_MODE_LOCALIZE)) {
1225
          // This is a term.
1226
          if ($t->tid > 0) {
1227
            $term = taxonomy_term_load($t->tid);
1228
            $display_num = '';
1229

    
1230
            $menu_num_inc_children = variable_get(_taxonomy_menu_build_variable('display_num_incl_children', $term->vid), TRUE);
1231
            $menu_display_descendants = variable_get(_taxonomy_menu_build_variable('display_descendants', $t->vid), FALSE);
1232
            if ($menu_num_inc_children || $menu_display_descendants) {
1233
              $num = taxonomy_menu_term_count_nodes($t->tid, $t->vid);
1234
            }
1235
            else {
1236
              $num = _taxonomy_menu_term_count($t->tid);
1237
            }
1238

    
1239
            // If hide menu is selected and the term count is 0 and the term
1240
            // has no children then do not create the menu item.
1241
            if ($num == 0 && variable_get(_taxonomy_menu_build_variable('hide_empty_terms', $t->vid), FALSE) && !_taxonomy_menu_children_has_nodes($t->tid, $t->vid)) {
1242
              $display_num = '';
1243
            }
1244
            // If display number is selected and $num > 0 then change the title.
1245
            elseif (variable_get(_taxonomy_menu_build_variable('display_num', $t->vid), FALSE)) {
1246
              $display_num = " ($num)";
1247
            }
1248

    
1249
            if ($item['title'] != ($term->name . $display_num)) {
1250
              // Should not happen.
1251
              watchdog('error', 'Menu and taxonomy name mismatch: @title != @name', array('@title' => $item['title'], '@name' => $term->name . $display_num));
1252
            }
1253

    
1254
            $term = i18n_taxonomy_localize_terms($term);
1255
            $item['title'] = $item['link_title'] = $term->name . $display_num;
1256
            if (variable_get(_taxonomy_menu_build_variable('term_item_description', $t->vid), FALSE)) {
1257
              $item['options']['attributes']['title'] = $term->description;
1258
            }
1259
          }
1260
          // Is a vocabulary.
1261
          else {
1262
            $vocab = taxonomy_vocabulary_load($t->vid);
1263
            $item['title'] = i18n_string('taxonomy:vocabulary:' . $vocab->vid . ':name', $vocab->name);
1264
          }
1265
        }
1266
      }
1267
      // No term, add a watchdog entry to help.
1268
      else {
1269
        watchdog('taxonomy_menu', 'Error with menu entry "%me" in menu "%mt"', array('%me' => $item['title'], '%mt' => $item['menu_name']));
1270
      }
1271
    }
1272
  }
1273
}
1274

    
1275
/**
1276
 * Gets term depth from a tid.
1277
 *
1278
 * @param $tid
1279
 *   Taxonomy term ID.
1280
 * @param $max_depth
1281
 *   Maximum depth.
1282
 *
1283
 * @return bool
1284
 *   Whether or not the term is too deep to include.
1285
 */
1286
function _taxonomy_menu_term_too_deep($tid, $max_depth) {
1287
  if ($max_depth) {
1288
    $depth = 0;
1289
    while ($parent = db_select('taxonomy_term_hierarchy', 't')
1290
      ->condition('tid', $tid, '=')
1291
      ->fields('t')
1292
      ->execute()
1293
      ->fetchAssoc()) {
1294
      $depth++;
1295
      $tid = $parent['parent'];
1296
      if ($depth > $max_depth) {
1297
        return TRUE;
1298
      }
1299
    }
1300
  }
1301
  return FALSE;
1302
}