/[drupal]/contributions/modules/sitemenu/sitemenu.module
ViewVC logotype

Contents of /contributions/modules/sitemenu/sitemenu.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.39 - (show annotations) (download) (as text)
Tue May 13 13:27:28 2008 UTC (18 months, 1 week ago) by kbahey
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--1
Changes since 1.38: +65 -26 lines
File MIME type: text/x-php
Drupal 6.x version of the module. Works fine.
Can use more refactoring of theme functions (break more of them into tpl.php functions).
1 <?php
2
3 //$Id: sitemenu.module,v 1.23.2.18 2008/04/03 16:12:45 kbahey Exp $
4
5 // Copyright 2005 Khalid Baheyeldin http://2bits.com
6
7 // W3C compliant patch by Méléis 2005/09/07 http://www.meleis.yi.org/
8
9 define('SITEMENU_VOCAB_TYPE_NONE', 0);
10 define('SITEMENU_VOCAB_TYPE_IMAGE', 1);
11 define('SITEMENU_VOCAB_TYPE_FORUM', 2);
12 define('SITEMENU_CACHING', 'sitemenu_caching');
13 define('SITEMENU_OVERVIEW_TITLE', 'sitemenu_overview_title');
14 define('SITEMENU_DESCRIPTION', 'sitemenu_description');
15 define('SITEMENU_OVERVIEW_VOCAB', 'sitemenu_overview_vocab');
16 define('SITEMENU_BLOCK_TITLE', 'sitemenu_block_title');
17 define('SITEMENU_NODE_COUNT', 'sitemenu_node_count');
18 define('SITEMENU_AUTHOR_AND_COMMENTS', 'sitemenu_author_and_comments');
19 define('SITEMENU_MAX_ROWS', 'sitemenu_max_rows');
20 define('SITEMENU_FOOTER', 'sitemenu_footer');
21 define('SITEMENU_SHOW_VOCAB_TITLES', 'sitemenu_show_vocab_titles');
22
23 function sitemenu_help($section) {
24 switch ($section) {
25 case 'admin/help#sitemenu':
26 $output = t("This module provides a site map based on the hierarchy of the site's taxonomy. The site map page shows all vocabularies, terms, and recent nodes within each term. It also provides a block that can be used in the side bar as a navigation menu.");
27 break;
28 }
29
30 return $output;
31 }
32
33 function sitemenu_menu() {
34 $items = array();
35
36 $items['sitemenu'] = array(
37 'title' => variable_get('SITEMENU_OVERVIEW_TITLE', t('Site map')),
38 'access callback' => 'user_access',
39 'access arguments' => array('use sitemenu'),
40 'page callback' => 'theme',
41 'page arguments' => array('sitemenu_page'),
42 'type' => MENU_SUGGESTED_ITEM,
43 );
44
45 $items['admin/settings/sitemenu'] = array(
46 'title' => t('Site menu'),
47 'description' => t('Settings for the sitemenu module.'),
48 'access callback' => 'user_access',
49 'access arguments' => array('administer site configuration'),
50 'page callback' => 'drupal_get_form',
51 'page arguments' => array('sitemenu_settings'),
52 'type' => MENU_NORMAL_ITEM,
53 );
54
55 return $items;
56 }
57
58 function sitemenu_perm() {
59 return array ('use sitemenu', 'administer sitemenu');
60 }
61
62 function sitemenu_theme() {
63 return array(
64 'sitemenu_page' => array(
65 ),
66
67 'sitemenu_box' => array(
68 'arguments' => array(
69 'title' => NULL,
70 'content' => NULL,
71 ),
72 'template' => 'sitemenu-box',
73 ),
74
75 'sitemenu_box_page' => array(
76 'template' => 'sitemenu-box-page',
77 'arguments' => array(
78 'title' => NULL,
79 'content' => NULL,
80 ),
81 ),
82
83 'sitemenu_render_outline' => array(
84 'arguments' => array(
85 'tree' => NULL,
86 'vocab_type' => NULL,
87 ),
88 ),
89 );
90 }
91
92 function sitemenu_settings() {
93
94 cache_clear_all('sitemenu', 'cache', TRUE);
95
96 $vocabularies = taxonomy_get_vocabularies();
97 $select[0] = '<'. t("none") .'>';
98 foreach ($vocabularies as $vocabulary) {
99 $select[$vocabulary->vid] = $vocabulary->name;
100 }
101
102 $form[SITEMENU_DESCRIPTION] = array(
103 '#type' => 'textarea',
104 '#title' => t('Description'),
105 '#default_value' => variable_get(SITEMENU_DESCRIPTION, t('This is the site map page.')),
106 '#cols' => 70,
107 '#rows' => 7,
108 '#description' => t('This text will be displayed at the top of the site menu page'),
109 );
110
111 $form[SITEMENU_OVERVIEW_VOCAB] = array(
112 '#type' => 'select',
113 '#title' => t('Omitted vocabularies'),
114 '#default_value' => variable_get(SITEMENU_OVERVIEW_VOCAB, array()),
115 '#options' => $select,
116 '#multiple' => TRUE,
117 '#description' => t('Select vocabularies which should be <b>omitted</b> from listings.'),
118 );
119
120 $form[SITEMENU_OVERVIEW_TITLE] = array(
121 '#type' => 'textfield',
122 '#title' => t('Navigation link text'),
123 '#required' => TRUE,
124 '#default_value' => variable_get(SITEMENU_OVERVIEW_TITLE, t('site map')),
125 '#size' => 35,
126 '#maxsize' => 255,
127 '#description' => t('The text in the navigation link which points to the site menu page.')
128 );
129
130 $form[SITEMENU_BLOCK_TITLE] = array(
131 '#type' => 'textfield',
132 '#title' => t('Block title text'),
133 '#required' => TRUE,
134 '#default_value' => variable_get(SITEMENU_BLOCK_TITLE, t('Menu')),
135 '#size' => 35,
136 '#maxsize' => 255,
137 '#description' => t('If configured as a block, this text shows as the block title.'),
138 );
139
140 $form[SITEMENU_NODE_COUNT] = array(
141 '#type' => 'checkbox',
142 '#title' => t('Show number of nodes for each term'),
143 '#default_value' => variable_get(SITEMENU_NODE_COUNT, 1),
144 );
145
146 $form[SITEMENU_CACHING] = array(
147 '#type' => 'checkbox',
148 '#title' => t('Cache the taxonomy tree for performance.'),
149 '#default_value' => variable_get(SITEMENU_CACHING, 1),
150 '#description' => t('This reduces the load of generating the site menu block for every page, as well as the site map page. It may be suitable only for sites with one language. In some cases, using the i18n module is incompatible with this caching option. In this case, uncheck this box.'),
151 );
152
153 $form[SITEMENU_AUTHOR_AND_COMMENTS] = array(
154 '#type' => 'checkbox',
155 '#title' => t('Show Author and number of Comments (in mousover)'),
156 '#default_value' => variable_get(SITEMENU_AUTHOR_AND_COMMENTS, 1),
157 );
158
159 $form[SITEMENU_SHOW_VOCAB_TITLES] = array(
160 '#type' => 'checkbox',
161 '#title' => t('Show vocabulary titles'),
162 '#default_value' => variable_get(SITEMENU_SHOW_VOCAB_TITLES, 1),
163 );
164
165 $form[SITEMENU_MAX_ROWS] = array(
166 '#type' => 'textfield',
167 '#title' => t('Number of nodes to show'),
168 '#required' => TRUE,
169 '#default_value' => variable_get(SITEMENU_MAX_ROWS, 0),
170 '#size' => 10,
171 '#maxsize' => 10,
172 '#description' => t('Number of nodes to show per taxonomy term. Set to 0 if you do not want nodes to listed.'),
173 );
174
175 $form[SITEMENU_FOOTER] = array(
176 '#type' => 'textarea',
177 '#title' => t('Closing description'),
178 '#default_value' => variable_get(SITEMENU_FOOTER, null),
179 '#cols' => 70,
180 '#rows' => 7,
181 '#description' => t('This text will be displayed at the bottom of the site menu page'),
182 );
183
184 return system_settings_form($form);
185 }
186
187 function _sitemenu_contents() {
188 $boxes = _sitemenu_overview('block');
189 return _sitemenu_print_boxes($boxes, 'block');
190 }
191
192 /**
193 * Check whether the vocabulary is used by a known core
194 * module, image or forum.
195 *
196 * @param int $vid
197 * @return boolean
198 */
199 function _sitemenu_check_vid($vid) {
200
201 $vocab_type = SITEMENU_VOCAB_TYPE_NONE;
202
203 if ($vid == variable_get('image_gallery_nav_vocabulary', '')) {
204 $vocab_type = SITEMENU_VOCAB_TYPE_IMAGE;
205 }
206 elseif ($vid == variable_get('forum_nav_vocabulary', '')) {
207 $vocab_type = SITEMENU_VOCAB_TYPE_FORUM;
208 }
209
210 return $vocab_type;
211 }
212
213 /**
214 * Get only requested vocabularies
215 *
216 * @param string $type Node type name
217 * @return array
218 */
219 function _sitemenu_get_vocabularies() {
220 $vocabularies = taxonomy_get_vocabularies();
221 $omits = variable_get(SITEMENU_OVERVIEW_VOCAB, array()); //omit undesired vocabularies from listing
222 foreach ($omits as $omit) {
223 unset($vocabularies[$omit]);
224 }
225 return $vocabularies;
226 }
227
228 function _sitemenu_inject_nodes($tree, $mode = 'page') {
229 $tree_node = $tree;
230 if ( $mode == 'page' ) {
231 $max_rows = variable_get(SITEMENU_MAX_ROWS, 0);
232 $get_author_and_comments = variable_get(SITEMENU_AUTHOR_AND_COMMENTS, 1);
233
234 // iterate over the tree backwards, so I don't trip on the new items
235 for ($i=count($tree)-1; $i>=0 ; $i--) {
236 $term = $tree[$i];
237 $sql = "SELECT n.nid, n.title, n.type ";
238 if ($get_author_and_comments) {
239 $sql .= ", u.uid, u.name ";
240 }
241 $sql .= "FROM {term_node} r LEFT JOIN {node} n ON r.nid = n.nid ";
242 if ($get_author_and_comments) {
243 $sql .= "LEFT JOIN {users} u ON n.uid = u.uid ";
244 }
245 $sql .= "WHERE n.status = '1' AND r.tid = %d ORDER BY n.changed ASC";
246 $result = db_query_range($sql, $term->tid, 0, $max_rows);
247 while ($node = db_fetch_object($result)) {
248 if ($get_author_and_comments) {
249 $detail = t('Author: ') . $node->name;
250 if (module_exists('comment')) {
251 $detail .= t(", comments: ") . comment_num_all($node->nid);
252 }
253 $link = l($node->title, "node/$node->nid", array ('title' => $detail));
254 }
255 else {
256 $link = l($node->title, "node/$node->nid");
257 }
258 $term_node = (object)(array ('nid' => $node->nid, 'depth' => $term->depth+1, 'link' => $link));
259 $part1 = array_slice($tree_node, 0, $i+1);
260 $part2 = array_slice($tree_node, $i+1, count($tree_node));
261 $part1[] = $term_node;
262 $tree_node = array_merge($part1, $part2);
263 }
264 }
265 }
266
267 return $tree_node;
268 }
269
270 /**
271 * accepts an optional param for restricting nodes to a particular type
272 * @param string $type Node type name. Default to invalid node type '(integer) 0'
273 * @param string $mode Only 'page' mode can have node counts optionally displayed
274 * @return array Array of outline boxes, possibly empty, but never NULL
275 */
276 function _sitemenu_overview($mode = 'page') {
277 $n = 0;
278 $vocabularies = _sitemenu_get_vocabularies();
279 $use_cache = variable_get(SITEMENU_CACHING, 1);
280 foreach ($vocabularies as $vocabulary) {
281 $tree_nodes = NULL;
282 if ($use_cache) {
283 $cache_id = 'sitemenu:' . $vocabulary->vid . '_' . $mode;
284 if ($cached = cache_get($cache_id)) {
285 $tree_nodes = $cached->data;
286 }
287 }
288
289 if (!$tree_nodes) {
290 $tree = taxonomy_get_tree($vocabulary->vid);
291 $get_node_count = variable_get(SITEMENU_NODE_COUNT, 1);
292 if ($get_node_count && $mode == 'page') {
293 // append the node count to each term name
294 for ($m=0; $m<count($tree); $m++) {
295 if ($count = taxonomy_term_count_nodes($tree[$m]->tid)) {
296 $tree[$m]->count = $count;
297 }
298 }
299 }
300 $tree_nodes = _sitemenu_inject_nodes($tree, $mode);
301 if ($use_cache) {
302 cache_set($cache_id, $tree_nodes, 'cache', CACHE_TEMPORARY);
303 }
304 }
305
306 $vocab_type = _sitemenu_check_vid($vocabulary->vid);
307
308 $boxes[$n]['content'] = theme('sitemenu_render_outline', $tree_nodes, $vocab_type);
309 $boxes[$n]['subject'] = $vocabulary->name;
310 $n++;
311 }
312 return $boxes ? $boxes : array();
313 }
314
315 /**
316 * Build the themed set of outline boxes
317 *
318 * @param array $boxes Each row has 'subject' and 'content' subrows
319 * @param string $mode If $mode == 'page', add pre- and post- content from settings
320 * @return string themed HTML
321 */
322 function _sitemenu_print_boxes($boxes, $mode = 'page') {
323 if ($mode == 'page') {
324 $output .= variable_get(SITEMENU_DESCRIPTION, '');
325 }
326 foreach ($boxes as $box) {
327 $subject = variable_get(SITEMENU_SHOW_VOCAB_TITLES, 1) ? $box['subject'] : '';
328 if ($mode == 'page') {
329 $output .= theme('sitemenu_box_page', $subject, $box['content']);
330 }
331 else {
332 $output .= theme('sitemenu_box', $subject, $box['content']);
333 }
334 }
335 if ($mode == 'page') {
336 $output .= variable_get(SITEMENU_FOOTER, '');
337 }
338 return $output;
339 }
340
341 /**
342 * Drupal Hooks implementation
343 */
344
345
346 /**
347 * hook_block
348 */
349 function sitemenu_block($op = 'list', $delta = 0) {
350 $title = variable_get(SITEMENU_BLOCK_TITLE, t('Menu'));
351
352 switch ($op) {
353 case 'list':
354 $block[0]['info'] = $title;
355 break;
356
357 case 'view':
358 switch ($delta) {
359 case 0:
360 $block['subject'] = $title;
361 $block['content'] = _sitemenu_contents();
362 break;
363 }
364 break;
365
366 default:
367 break;
368 }
369 return $block;
370 }
371
372 /**
373 * Themeable elements
374 */
375
376 /**
377 * Theme the box containing the outline for a given vocabulary
378 *
379 * @param string $subtitle
380 * @param string $content
381 * @return string Themed HTML
382 * @see theme_sitemenu_render_outline for the generation of $content
383 * @see _sitemenu_overview() which actually uses this function
384 */
385 function theme_sitemenu_box($title, $content) {
386 $output = '<h3>'. $title .'</h3>';
387 $output .= $content;
388 return $output;
389 }
390
391 function theme_sitemenu_box_page($title, $content) {
392 $output = '<h2 class="title">'. $title .'</h2>';
393 $output .= '<div>'. $content .'</div>';
394 return $output;
395 }
396
397 /**
398 * Theme the main sitemenu page
399 *
400 * @return string HTML
401 */
402 function theme_sitemenu_page() {
403 if (user_access("use sitemenu")) {
404 $title = variable_get(SITEMENU_OVERVIEW_TITLE, t('site map'));
405 $boxes = _sitemenu_overview();
406 $output = _sitemenu_print_boxes($boxes, 'page');
407 return $output;
408 }
409 }
410
411 /**
412 * Theme a vocabulary outline
413 *
414 * @param array $tree Vocabulary tree
415 *
416 * @param string $vocab_type Node type for the vocabulary
417 *
418 * @return string Themed HTML
419 */
420 function theme_sitemenu_render_outline($tree, $vocab_type) {
421 if (empty($tree)) {
422 return '';
423 }
424
425 global $ul;
426
427 $old_depth = -1;
428 $output = "";
429
430 for ($m = 0; $m < count($tree); $m++) {
431 $term = $tree[$m];
432
433 if ($term->depth > $old_depth) {
434 $output .= "<ul class=\"menu\">\n";
435 $ul++;
436 }
437 if ($term->depth < $old_depth) {
438 $delta = $old_depth - $term->depth;
439 $output .= str_repeat("</ul>\n", $delta);
440 $output .= '</li>'."\n";
441 }
442
443 $old_depth = $term->depth;
444
445 switch($vocab_type) {
446 case SITEMENU_VOCAB_TYPE_IMAGE:
447 $path = 'image/tid/';
448 break;
449 case SITEMENU_VOCAB_TYPE_FORUM:
450 $path = 'forum/';
451 break;
452 default:
453 $path = 'taxonomy/term/';
454 break;
455 }
456
457 $count = ($term->count) ? ' (' . $term->count . ')' : '';
458 if (isset($term->description)) {
459 // use the description as a title attribute for terms
460 $link = l($term->name . $count, $path . $term->tid, array ("title" => $term->description));
461 }
462 else {
463 if (isset($term->link)) {
464 // This is a node
465 $link = $term->link . $count;
466 }
467 else {
468 $link = l($term->name . $count, $path . $term->tid );
469 }
470 }
471
472 // if children exist, output with proper class and id attributes, else, output item with
473 // specified link or default link
474 if ($term->depth < $tree[$m+1]->depth) {
475 $output .= "<li class=\"expanded\">". $link ."\n";
476 }
477 else {
478 $output .= "<li class=\"leaf\">". $link ."</li>\n";
479 }
480 unset($description);
481 }
482 if ($term->depth >= 1) { $output .= '</ul></li>'."\n"; }
483 if ($term->depth == 0) { $output .= '</ul>'."\n"; }
484 $output .= str_repeat("</ul>\n", $term->depth);
485 return $output;
486 }
487
488 function sitemenu_taxonomy($op, $type, $object) {
489 // Expire the sitemenu cache when a taxonomy is added/changed/deleted
490 $use_cache = variable_get(SITEMENU_CACHING, 1);
491 if ($use_cache) {
492 cache_clear_all('sitemenu', 'cache', TRUE);
493 }
494 }
495
496 function sitemenu_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
497 // Expire the sitemenu cache when a node is inserted/deleted/updated
498 switch($op) {
499 case 'delete':
500 case 'insert':
501 case 'update':
502 $use_cache = variable_get(SITEMENU_CACHING, 1);
503 if ($use_cache) {
504 cache_clear_all('sitemenu:', 'cache', TRUE);
505 }
506 break;
507 }
508 }

  ViewVC Help
Powered by ViewVC 1.1.2