Parent Directory
|
Revision Log
|
Revision Graph
Tweak to breadcrumbs.
| 1 | <?php |
| 2 | // $Id: taxonomy_dss.module,v 1.25 2007/08/31 17:17:59 moonray Exp $ |
| 3 | |
| 4 | /* Required patch to core (can we find a module specific workaround?): |
| 5 | |
| 6 | Index: themes/engines/phptemplate/phptemplate.engine |
| 7 | =================================================================== |
| 8 | RCS file: /cvs/drupal/drupal/themes/engines/phptemplate/phptemplate.engine,v |
| 9 | retrieving revision 1.54 |
| 10 | diff -b -U3 -r1.54 phptemplate.engine |
| 11 | --- themes/engines/phptemplate/phptemplate.engine 30 Dec 2006 20:59:11 -0000 1.54 |
| 12 | +++ themes/engines/phptemplate/phptemplate.engine 25 Jan 2007 17:58:08 -0000 |
| 13 | @@ -266,13 +266,27 @@ |
| 14 | $taxonomy = array(); |
| 15 | } |
| 16 | |
| 17 | + // This seems like a bit of a hack, but it works |
| 18 | + if (isset($node->links['node_read_more'])) { |
| 19 | + $link = $node->links['node_read_more']; |
| 20 | + |
| 21 | + $href = isset($link['href']) ? $link['href'] : NULL; |
| 22 | + $query = isset($link['query']) ? $link['query'] : NULL; |
| 23 | + $fragment = isset($link['fragment']) ? $link['fragment'] : NULL; |
| 24 | + |
| 25 | + $node_url = url($href, $query, $fragment); |
| 26 | + } |
| 27 | + else { |
| 28 | + $node_url = url('node/'.$node->nid); |
| 29 | + } |
| 30 | + |
| 31 | $variables = array( |
| 32 | 'content' => ($teaser && $node->teaser) ? $node->teaser : $node->body, |
| 33 | 'date' => format_date($node->created), |
| 34 | 'links' => $node->links ? theme('links', $node->links, array('class' => 'links inline')) : '', |
| 35 | 'name' => theme('username', $node), |
| 36 | 'node' => $node, // we pass the actual node to allow more customization |
| 37 | - 'node_url' => url('node/'. $node->nid), |
| 38 | + 'node_url' => $node_url, |
| 39 | 'page' => $page, |
| 40 | 'taxonomy' => $taxonomy, |
| 41 | 'teaser' => $teaser, |
| 42 | |
| 43 | */ |
| 44 | |
| 45 | /** |
| 46 | * @file |
| 47 | * Taxonomy Dynamic Site Structure uses taxonomy terms to create a flexible |
| 48 | * and dynamic site structure, or outline. |
| 49 | * |
| 50 | * TODO |
| 51 | * Figure out how to let this module be loaded last if it is enabled at the |
| 52 | * same time as taxonomy; the menu callback override doesn't work otherwise. |
| 53 | * Also, find every implode that only handles commas (,) and add ability to |
| 54 | * handle plusses (+). |
| 55 | */ |
| 56 | |
| 57 | /** |
| 58 | * Implementation of hook_menu(). |
| 59 | */ |
| 60 | function taxonomy_dss_menu($may_cache) { |
| 61 | $items = array(); |
| 62 | |
| 63 | if (!$may_cache) { |
| 64 | $items[] = array( |
| 65 | 'path' => 'admin/content/taxonomy/settings', |
| 66 | 'title' => t('Settings'), |
| 67 | 'callback' => 'drupal_get_form', |
| 68 | 'callback arguments' => array('taxonomy_dss_admin_settings'), |
| 69 | 'access' => user_access('administer taxonomy'), |
| 70 | 'weight' => 10, |
| 71 | 'type' => MENU_LOCAL_TASK, |
| 72 | ); |
| 73 | |
| 74 | // Terrible hack to override taxonomy's callback function |
| 75 | // Couldn't find another way to accomplish this, though |
| 76 | $GLOBALS['_menu']['callbacks']['taxonomy/term']['callback'] = 'taxonomy_dss_term_page'; |
| 77 | |
| 78 | // Show node view and edit/add links for taxonomy pages |
| 79 | if (arg(0) == 'taxonomy' && arg(1) == 'term') { |
| 80 | $node = node_load(taxonomy_dss_get_nid(arg(2))); |
| 81 | $items[] = array( |
| 82 | 'path' => 'taxonomy/term/'. arg(2), |
| 83 | 'title' => t('View'), |
| 84 | 'callback' => 'taxonomy_dss_term_page', |
| 85 | 'callback arguments' => array(arg(2)), |
| 86 | 'access' => user_access('access content') && ($node ? node_access('view', $node) : TRUE), |
| 87 | 'type' => MENU_CALLBACK, |
| 88 | ); |
| 89 | $items[] = array( |
| 90 | 'path' => 'taxonomy/term/'. arg(2) .'/view', |
| 91 | 'title' => t('View'), |
| 92 | 'type' => MENU_DEFAULT_LOCAL_TASK, |
| 93 | 'weight' => -10, |
| 94 | ); |
| 95 | if ($node) { |
| 96 | $items[] = array( |
| 97 | 'path' => 'taxonomy/term/'. arg(2) .'/outline', |
| 98 | 'title' => t('Outline'), |
| 99 | 'callback' => 'drupal_get_form', |
| 100 | 'callback arguments' => array('book_outline', $node->nid), |
| 101 | 'access' => user_access('outline posts in books'), |
| 102 | 'type' => MENU_LOCAL_TASK, |
| 103 | 'weight' => 2 |
| 104 | ); |
| 105 | $items[] = array( |
| 106 | 'path' => 'taxonomy/term/'. arg(2) .'/edit', |
| 107 | 'title' => t('Edit'), |
| 108 | 'callback' => 'taxonomy_dss_page_edit', |
| 109 | 'callback arguments' => array(arg(2), $node), |
| 110 | 'access' => node_access('update', $node), |
| 111 | 'weight' => 1, |
| 112 | 'type' => MENU_LOCAL_TASK, |
| 113 | ); |
| 114 | $items[] = array( |
| 115 | 'path' => 'taxonomy/term/'. arg(2) .'/add', |
| 116 | 'title' => t('Edit'), |
| 117 | 'callback' => 'taxonomy_dss_not_available', |
| 118 | 'access' => node_access('update', $node), |
| 119 | 'weight' => 1, |
| 120 | 'type' => MENU_CALLBACK, |
| 121 | ); |
| 122 | $items[] = array( |
| 123 | 'path' => 'taxonomy/term/'. arg(2) .'/delete', |
| 124 | 'title' => t('Delete'), |
| 125 | 'callback' => 'drupal_get_form', |
| 126 | 'callback arguments' => array('node_delete_confirm', $node), |
| 127 | 'access' => node_access('delete', $node), |
| 128 | 'weight' => 1, |
| 129 | 'type' => MENU_CALLBACK, |
| 130 | ); |
| 131 | } |
| 132 | else { |
| 133 | $items[] = array( |
| 134 | 'path' => 'taxonomy/term/'. arg(2) .'/add', |
| 135 | 'title' => t('Edit'), |
| 136 | 'callback' => 'taxonomy_dss_page_add', |
| 137 | 'callback arguments' => array(arg(2)), |
| 138 | 'access' => node_access('create', 'term'), |
| 139 | 'weight' => 1, |
| 140 | 'type' => MENU_LOCAL_TASK, |
| 141 | ); |
| 142 | $items[] = array( |
| 143 | 'path' => 'taxonomy/term/'. arg(2) .'/edit', |
| 144 | 'title' => t('Edit'), |
| 145 | 'callback' => 'taxonomy_dss_not_available', |
| 146 | 'access' => node_access('create', 'term'), |
| 147 | 'weight' => 1, |
| 148 | 'type' => MENU_CALLBACK, |
| 149 | ); |
| 150 | } |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | return $items; |
| 155 | } |
| 156 | |
| 157 | /** |
| 158 | * Menu callback; presents the taxonomy settings page. |
| 159 | */ |
| 160 | function taxonomy_dss_admin_settings() { |
| 161 | $form['toc_options'] = array( |
| 162 | '#type' => 'fieldset', |
| 163 | '#title' => t('Default outline options'), |
| 164 | '#collapsible' => TRUE, |
| 165 | '#description' => t('These are the default setting which can be overridden for each individual taxonomy terms set.'), |
| 166 | '#weight' => -2, |
| 167 | ); |
| 168 | $form['toc_options']['taxonomy_dss_toc_hidden'] = array( |
| 169 | '#type' => 'checkbox', |
| 170 | '#title' => t('Hide outline'), |
| 171 | '#default_value' => variable_get('taxonomy_dss_toc_hidden', 0), |
| 172 | '#description' => t('Hide the table of contents for this set of terms.'), |
| 173 | ); |
| 174 | $form['toc_options']['taxonomy_dss_toc_depth'] = array( |
| 175 | '#type' => 'select', |
| 176 | '#title' => t('Depth of outline'), |
| 177 | '#default_value' => variable_get('taxonomy_dss_toc_depth', 0), |
| 178 | '#options' => array(0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 10 => 10), |
| 179 | '#description' => t('Depth of the table of contents for this set of terms. Set this to 0 to reflect an infinite depth.'), |
| 180 | ); |
| 181 | $form['toc_options']['taxonomy_dss_toc_nodecount'] = array( |
| 182 | '#type' => 'checkbox', |
| 183 | '#title' => t('Show assigned node count in outline'), |
| 184 | '#default_value' => variable_get('taxonomy_dss_toc_nodecount', 1), |
| 185 | '#description' => t('Toggles display of the number of assigned nodes available, for each item listed in the table of contents.'), |
| 186 | ); |
| 187 | |
| 188 | $form['node_options'] = array( |
| 189 | '#type' => 'fieldset', |
| 190 | '#title' => t('Default node listing options'), |
| 191 | '#collapsible' => TRUE, |
| 192 | '#collapsed' => FALSE, |
| 193 | '#weight' => -1, |
| 194 | ); |
| 195 | $form['node_options']['taxonomy_dss_lst_hidden'] = array( |
| 196 | '#type' => 'checkbox', |
| 197 | '#title' => t('Hide node listing'), |
| 198 | '#default_value' => variable_get('taxonomy_dss_lst_hidden', 0), |
| 199 | '#description' => t('Hide the listed nodes in this set of terms.'), |
| 200 | ); |
| 201 | $form['node_options']['taxonomy_dss_lst_teasers_hidden'] = array( |
| 202 | '#type' => 'checkbox', |
| 203 | '#title' => t('Hide teasers'), |
| 204 | '#default_value' => variable_get('taxonomy_dss_lst_teasers_hidden', 0), |
| 205 | '#description' => t('Hide the teaser texts for the listed nodes in this set of terms.'), |
| 206 | ); |
| 207 | |
| 208 | return system_settings_form($form); |
| 209 | } |
| 210 | |
| 211 | /** |
| 212 | * Menu callback; presents the editing form associated with this set of terms, |
| 213 | * or redirects to delete confirmation. |
| 214 | */ |
| 215 | function taxonomy_dss_page_edit($tid, $node) { |
| 216 | if ($_POST['op'] == t('Delete')) { |
| 217 | // Note: we redirect from taxonomy/term/tid/edit to taxonomy/term/tid/delete to make the tabs disappear. |
| 218 | if ($_REQUEST['destination']) { |
| 219 | $destination = drupal_get_destination(); |
| 220 | unset($_REQUEST['destination']); |
| 221 | } |
| 222 | drupal_goto('taxonomy/term/'. $tid .'/delete', $destination); |
| 223 | } |
| 224 | |
| 225 | $terms = taxonomy_dss_terms_parse_string($tid); |
| 226 | |
| 227 | // Set page title |
| 228 | $title = check_plain(end($terms['names'])); |
| 229 | drupal_set_title($title); |
| 230 | |
| 231 | // Set breadcrumb |
| 232 | $breadcrumb = taxonomy_dss_generate_breadcrumb($terms['tids'], $terms['names']); |
| 233 | taxonomy_dss_set_breadcrumb($breadcrumb); |
| 234 | |
| 235 | // Render editing form |
| 236 | return drupal_get_form($node->type .'_node_form', $node); |
| 237 | } |
| 238 | |
| 239 | /** |
| 240 | * Menu callback; presents the add node form and associated a node with this |
| 241 | * set of terms. |
| 242 | */ |
| 243 | function taxonomy_dss_page_add($tid) { |
| 244 | $type = 'term'; |
| 245 | |
| 246 | $terms = taxonomy_dss_terms_parse_string($tid); |
| 247 | |
| 248 | // Set page title |
| 249 | $title = check_plain(end($terms['names'])); |
| 250 | drupal_set_title($title); |
| 251 | |
| 252 | // Set breadcrumb |
| 253 | $breadcrumb = taxonomy_dss_generate_breadcrumb($terms['tids'], $terms['names']); |
| 254 | taxonomy_dss_set_breadcrumb($breadcrumb); |
| 255 | |
| 256 | // Initialize settings: |
| 257 | $node = array('uid' => $GLOBALS['user']->uid, 'name' => $GLOBALS['user']->name, 'type' => $type); |
| 258 | |
| 259 | return drupal_get_form($type .'_node_form', $node); |
| 260 | } |
| 261 | |
| 262 | /** |
| 263 | * Implementation of hook_link_alter(). |
| 264 | * |
| 265 | * Adds query part to links in order to keep track of dynamic taxonomy based |
| 266 | * site structure. |
| 267 | */ |
| 268 | function taxonomy_dss_link_alter(&$node, &$links) { |
| 269 | $process = FALSE; |
| 270 | |
| 271 | if (arg(0) == 'taxonomy' && arg(1) == 'term' && isset($node->taxonomy)) { |
| 272 | $tids = taxonomy_dss_filter_tids($node->taxonomy, arg(2), TRUE); |
| 273 | $process = TRUE; |
| 274 | } |
| 275 | elseif (arg(0) == 'node' && isset($_GET['taxonomy'])) { |
| 276 | $tids = taxonomy_dss_filter_tids($node->taxonomy, $_GET['taxonomy'], TRUE); |
| 277 | $process = TRUE; |
| 278 | } |
| 279 | elseif (arg(0) == 'comment') { |
| 280 | } |
| 281 | |
| 282 | if ($process) { |
| 283 | $query = (count($tids) ? 'taxonomy='. implode(',', $tids) : ''); |
| 284 | |
| 285 | foreach ($links as $module => $link) { |
| 286 | switch ($module) { |
| 287 | case 'comment_comments': |
| 288 | case 'comment_add': |
| 289 | case 'node_read_more': |
| 290 | if ($query) { |
| 291 | $links[$module]['query'] = (isset($link['query']) ? $link['query'] . '&' : '') . $query; |
| 292 | } |
| 293 | break; |
| 294 | } |
| 295 | } |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | /** |
| 300 | * Implementation of hook_comment(). |
| 301 | * |
| 302 | * Redirects the page back to the proper taxonomy term set after adding |
| 303 | * a comment to a node. |
| 304 | */ |
| 305 | function taxonomy_dss_comment(&$comment, $op) { |
| 306 | switch ($op) { |
| 307 | case 'form': |
| 308 | if (isset($_GET['taxonomy']) && !isset($comment['#attributes']['destination'])) { |
| 309 | $form['destination'] = array( |
| 310 | '#type' => 'hidden', |
| 311 | '#value' => 'node/'. $comment['nid']['#value'] .'?taxonomy='. $_GET['taxonomy'], |
| 312 | ); |
| 313 | } |
| 314 | elseif (isset($comment['#attributes']['destination'])) { |
| 315 | $form['destination'] = array( |
| 316 | '#type' => 'hidden', |
| 317 | '#value' => $comment['#attributes']['destination'], |
| 318 | ); |
| 319 | } |
| 320 | return $form; |
| 321 | break; |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | /** |
| 326 | * Implementation of hook_form_alter(). |
| 327 | */ |
| 328 | function taxonomy_dss_form_alter($form_id, &$form) { |
| 329 | switch ($form_id) { |
| 330 | case 'taxonomy_form_vocabulary': |
| 331 | $form['taxonomy_dss_hidden'] = array( |
| 332 | '#type' => 'checkboxes', |
| 333 | '#title' => t('Breadcrumb'), |
| 334 | '#default_value' => (taxonomy_dss_vocabulary_is_hidden($form['vid']['#value']) ? 1 : 0), |
| 335 | '#options' => array('1' => t('Don\'t show in breadcrumb trail')), |
| 336 | '#description' => t('The breadcrumb trail is built using terms from all vocabularies associated with the current node. The vocabulary\'s weight determines the order in which the vocabulary appears in the breadcrumb trail. If hidden, this vocabulary will not be used to build the breadcrumb trail. It is recommended to hide free tagging vocabularies.'), |
| 337 | '#weight' => 1, |
| 338 | ); |
| 339 | break; |
| 340 | |
| 341 | case 'term_node_form': |
| 342 | if (arg(0) == 'node' && arg(1) == 'add') { |
| 343 | $form = array(); |
| 344 | $form[] = array( |
| 345 | '#value' => t('Term pages can only be created from a taxonomy term page.'), |
| 346 | ); |
| 347 | } |
| 348 | elseif (arg(0) == 'taxonomy' && arg(1) == 'term' && (arg(3) == 'add' || arg(3) == 'edit')) { |
| 349 | // Add options for display of outline tree |
| 350 | |
| 351 | $termset = taxonomy_dss_load(arg(2)); |
| 352 | |
| 353 | $form['toc_options'] = array( |
| 354 | '#type' => 'fieldset', |
| 355 | '#title' => t('Outline options'), |
| 356 | '#collapsible' => TRUE, |
| 357 | '#collapsed' => FALSE, |
| 358 | '#weight' => -2, |
| 359 | ); |
| 360 | $form['toc_options']['hidden'] = array( |
| 361 | '#type' => 'checkbox', |
| 362 | '#title' => t('Hide term'), |
| 363 | '#default_value' => isset($node->hidden) ? $node->hidden : $termset->hidden, |
| 364 | '#description' => t('Don\'t display this item in the table of contents.'), |
| 365 | ); |
| 366 | $form['toc_options']['toc_hidden'] = array( |
| 367 | '#type' => 'checkbox', |
| 368 | '#title' => t('Hide outline'), |
| 369 | '#default_value' => isset($node->toc_hidden) ? $node->toc_hidden : $termset->toc_hidden, |
| 370 | '#description' => t('Hide the table of contents for this set of terms.'), |
| 371 | ); |
| 372 | $form['toc_options']['toc_depth'] = array( |
| 373 | '#type' => 'select', |
| 374 | '#title' => t('Depth of outline'), |
| 375 | '#default_value' => isset($node->toc_depth) ? $node->toc_depth : $termset->toc_depth, |
| 376 | '#options' => array(0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 10 => 10), |
| 377 | '#description' => t('Depth of the table of contents for this set of terms. Set this to 0 to reflect an infinite depth.'), |
| 378 | ); |
| 379 | $form['toc_options']['toc_nodecount'] = array( |
| 380 | '#type' => 'checkbox', |
| 381 | '#title' => t('Show assigned node count in outline'), |
| 382 | '#default_value' => isset($node->toc_nodecount) ? $node->toc_nodecount : $termset->toc_nodecount, |
| 383 | '#description' => t('Toggles display of the number of assigned nodes available for each item listed in the table of contents.'), |
| 384 | ); |
| 385 | |
| 386 | $form['node_options'] = array( |
| 387 | '#type' => 'fieldset', |
| 388 | '#title' => t('Node listing options'), |
| 389 | '#collapsible' => TRUE, |
| 390 | '#collapsed' => FALSE, |
| 391 | '#weight' => -1, |
| 392 | ); |
| 393 | $form['node_options']['lst_hidden'] = array( |
| 394 | '#type' => 'checkbox', |
| 395 | '#title' => t('Hide node listing'), |
| 396 | '#default_value' => isset($node->lst_hidden) ? $node->lst_hidden : $termset->lst_hidden, |
| 397 | '#description' => t('Hide the listed nodes in this set of terms.'), |
| 398 | ); |
| 399 | $form['node_options']['lst_teasers_hidden'] = array( |
| 400 | '#type' => 'checkbox', |
| 401 | '#title' => t('Hide teasers'), |
| 402 | '#default_value' => isset($node->lst_teasers_hidden) ? $node->lst_teasers_hidden : $termset->lst_teasers_hidden, |
| 403 | '#description' => t('Hide the teaser texts for the listed nodes in this set of terms.'), |
| 404 | ); |
| 405 | |
| 406 | // Required to make this form unique to this set of terms. If omitted, |
| 407 | // drupal's form handler often thinks it's a duplicate submit for a |
| 408 | // previous 'add node' request. |
| 409 | $form['term_tid'] = array( |
| 410 | '#type' => 'hidden', |
| 411 | '#value' => arg(2), |
| 412 | ); |
| 413 | } |
| 414 | else { |
| 415 | print "EDIT THIS PAGE!<br />\nAdd a taxonomy select dropdown menu.<br />\nOr, we can somehow disable access to this particular page from this particular spot?"; |
| 416 | } |
| 417 | break; |
| 418 | |
| 419 | case 'node_admin_nodes': |
| 420 | // Override edit destination for 'term' nodes on 'Content management' page |
| 421 | if (is_array($form['name'])) { |
| 422 | $keys = array_keys($form['name']); |
| 423 | foreach ($keys as $key) { |
| 424 | if ($form['name'][$key]['#value'] == 'Term') { |
| 425 | $form['operations'][$key]['#value'] = l(t('edit'), 'taxonomy/term/'. taxonomy_dss_get_tids($key) .'/edit', array(), drupal_get_destination()); |
| 426 | } |
| 427 | } |
| 428 | } |
| 429 | break; |
| 430 | } |
| 431 | } |
| 432 | |
| 433 | /** |
| 434 | * Implementation of hook_taxonomy(). |
| 435 | */ |
| 436 | function taxonomy_dss_taxonomy($op, $type, $object = NULL) { |
| 437 | if ($type == 'vocabulary') { |
| 438 | switch ($op) { |
| 439 | case 'delete': |
| 440 | db_query("DELETE FROM {taxonomy_dss_vocabulary} WHERE vid = %d", $object['vid']); |
| 441 | break; |
| 442 | case 'insert': |
| 443 | db_query("INSERT INTO {taxonomy_dss_vocabulary} (vid, hidden) VALUES (%d, %d)", $object['vid'], $object['taxonomy_dss_hidden']['1']); |
| 444 | break; |
| 445 | case 'update': |
| 446 | db_query("UPDATE {taxonomy_dss_vocabulary} SET hidden = %d WHERE vid = %d", $object['taxonomy_dss_hidden']['1'], $object['vid']); |
| 447 | break; |
| 448 | } |
| 449 | } |
| 450 | elseif ($type == 'term') { |
| 451 | switch ($op) { |
| 452 | case 'delete': |
| 453 | db_query("DELETE FROM {taxonomy_dss_term} WHERE tid = '%s'", $object['tid']); |
| 454 | // Actually, we need to delete every single page that this term appears in... ouch! |
| 455 | break; |
| 456 | } |
| 457 | } |
| 458 | } |
| 459 | |
| 460 | /** |
| 461 | * Implementation of hook_nodeapi(). |
| 462 | */ |
| 463 | function taxonomy_dss_nodeapi(&$node, $op, $teaser, $page) { |
| 464 | $clean_url = (bool)variable_get('clean_url', '0'); |
| 465 | $delimiter = ($clean_url == FALSE || strstr('?', $node->breadcrumb[$i]['path']) ? '&' : '?'); |
| 466 | |
| 467 | switch ($op) { |
| 468 | case 'insert': |
| 469 | if (arg(0) == 'taxonomy' && arg(1) == 'term' && arg(3) == 'add') { |
| 470 | // arg(2) needs to be cleaned, or we might have a security hole! |
| 471 | |
| 472 | // Allow other modules to alter the data |
| 473 | $termset = taxonomy_dss_node_to_termset(arg(2), $node); |
| 474 | taxonomy_dss_invoke($termset, 'submit', $node); |
| 475 | $termset->serialized_data = serialize($termset->serial_data); |
| 476 | |
| 477 | // Insert termset into database |
| 478 | db_query("INSERT INTO {taxonomy_dss_term} (tid, nid, hidden, toc_hidden, toc_depth, toc_nodecount, lst_hidden, lst_teasers_hidden, serialized_data) VALUES ('%s', %d, %d, %d, %d, %d, %d, %d, '%s')", $termset->tids, $termset->nid, $termset->hidden, $termset->toc_hidden, $termset->toc_depth, $termset->toc_nodecount, $termset->lst_hidden, $termset->lst_teasers_hidden, $termset->serialized_data); |
| 479 | |
| 480 | // Allow other modules to alter the data |
| 481 | taxonomy_dss_invoke($termset, 'insert', $node); |
| 482 | } |
| 483 | break; |
| 484 | |
| 485 | case 'update': |
| 486 | if (arg(0) == 'taxonomy' && arg(1) == 'term' && arg(3) == 'edit') { |
| 487 | |
| 488 | // Allow other modules to alter the data |
| 489 | $termset = taxonomy_dss_node_to_termset(arg(2), $node); |
| 490 | taxonomy_dss_invoke($termset, 'submit', $node); |
| 491 | $termset->serialized_data = serialize($termset->serial_data); |
| 492 | |
| 493 | // Update termset in database |
| 494 | db_query("UPDATE {taxonomy_dss_term} SET hidden = %d, toc_hidden = %d, toc_depth = %d, toc_nodecount = %d, lst_hidden = %d, lst_teasers_hidden = %d, serialized_data = '%s' WHERE tid = '%s'", $termset->hidden, $termset->toc_hidden, $termset->toc_depth, $termset->toc_nodecount, $termset->lst_hidden, $termset->lst_teasers_hidden, $termset->serialized_data, $termset->tids); |
| 495 | |
| 496 | // Allow other modules to alter the data |
| 497 | taxonomy_dss_invoke($termset, 'update', $node); |
| 498 | } |
| 499 | break; |
| 500 | |
| 501 | case 'delete': |
| 502 | db_query("DELETE FROM {taxonomy_dss_term} WHERE nid = %d", $node->nid); |
| 503 | |
| 504 | // Allow other modules to alter the data |
| 505 | taxonomy_dss_invoke($termset, 'delete'); |
| 506 | break; |
| 507 | |
| 508 | case 'submit': |
| 509 | // If it's a term node, add a title |
| 510 | if (isset($node->nid)) { |
| 511 | // Updating existing node |
| 512 | if ($node->type == 'term' && $tids = taxonomy_dss_get_tids($node->nid)) { |
| 513 | $node->title = taxonomy_dss_get_title($tids); |
| 514 | } |
| 515 | } |
| 516 | elseif (arg(0) == 'taxonomy' && arg(1) == 'term' && arg(3) == 'add') { |
| 517 | // Creating new node |
| 518 | $node->title = taxonomy_dss_get_title(arg(2)); |
| 519 | } |
| 520 | |
| 521 | break; |
| 522 | |
| 523 | case 'view': |
| 524 | if ($page) { |
| 525 | // Page view |
| 526 | |
| 527 | // If this node is associated with a taxonomy term, jump! |
| 528 | if (arg(0) != 'taxonomy' && arg(1) != 'term' && $tid = taxonomy_dss_get_tids($node->nid)) { |
| 529 | drupal_goto('taxonomy/term/'.$tid); |
| 530 | } |
| 531 | |
| 532 | // Fix book module links |
| 533 | $taxonomy = $_GET['taxonomy'] ? 'taxonomy='.$_GET['taxonomy'] : ''; |
| 534 | if (module_exists('book') && isset($node->content['book_navigation']) && $taxonomy) { |
| 535 | // Hack the themed output from the book module's navigation |
| 536 | $node->content['book_navigation'] = preg_replace('/(node\/\d+)/', '${1}'. $delimiter.$taxonomy, $node->content['book_navigation']); |
| 537 | } |
| 538 | |
| 539 | // Taxonomy terms seem to already be sorted by vocabulary weight. |
| 540 | $tids = taxonomy_dss_filter_tids($node->taxonomy, $_GET['taxonomy']); |
| 541 | $names = array(); |
| 542 | foreach ($tids as $tid) { |
| 543 | $names[] = $node->taxonomy[$tid]->name; |
| 544 | } |
| 545 | |
| 546 | $breadcrumb = taxonomy_dss_generate_breadcrumb($tids, $names); |
| 547 | |
| 548 | // Integrate with book module |
| 549 | if (module_exists('book') && isset($node->breadcrumb)) { |
| 550 | $breadcrumb = array_merge($breadcrumb, $node->breadcrumb); |
| 551 | } |
| 552 | else { |
| 553 | $breadcrumb[] = array('path' => 'node/'. $node->nid, 'title' => $node->title); |
| 554 | } |
| 555 | |
| 556 | menu_set_location($breadcrumb); |
| 557 | taxonomy_dss_set_breadcrumb($breadcrumb); |
| 558 | } |
| 559 | break; |
| 560 | case 'alter': |
| 561 | if ($page) { |
| 562 | // Page view |
| 563 | |
| 564 | $taxonomy = $_GET['taxonomy'] ? 'taxonomy='.$_GET['taxonomy'] : ''; |
| 565 | |
| 566 | if (module_exists('book') && isset($node->breadcrumb) && $taxonomy) { |
| 567 | // Hack the breadcrumb to include the query |
| 568 | $breadcrumb = drupal_get_breadcrumb(); |
| 569 | $offset = count($breadcrumb) - count($node->breadcrumb) + 1; |
| 570 | for ($i = $offset; $i < count($breadcrumb); $i++) { |
| 571 | $breadcrumb[$i] = str_replace($node->breadcrumb[$i - $offset]['path'], $node->breadcrumb[$i - $offset]['path'] . $delimiter . $taxonomy, $breadcrumb[$i]); |
| 572 | } |
| 573 | drupal_set_breadcrumb($breadcrumb); |
| 574 | } |
| 575 | } |
| 576 | break; |
| 577 | } |
| 578 | } |
| 579 | |
| 580 | /** |
| 581 | * Is vocabulary hidden? |
| 582 | */ |
| 583 | function taxonomy_dss_vocabulary_is_hidden($vid) { |
| 584 | static $vocabularies = array(); |
| 585 | |
| 586 | if (!isset($vocabularies[$vid])) { |
| 587 | $result = db_query("SELECT hidden FROM {taxonomy_dss_vocabulary} WHERE vid = %d", $vid); |
| 588 | $row = db_fetch_array($result); |
| 589 | if ($row && $row['hidden'] == 1) { |
| 590 | $vocabularies[$vid] = TRUE; |
| 591 | } |
| 592 | else { |
| 593 | $vocabularies[$vid] = FALSE; |
| 594 | } |
| 595 | } |
| 596 | |
| 597 | return $vocabularies[$vid]; |
| 598 | } |
| 599 | |
| 600 | function taxonomy_dss_not_available() { |
| 601 | return t('n/a'); |
| 602 | } |
| 603 | |
| 604 | function taxonomy_dss_get_termset_data($tids) { |
| 605 | static $data = array(); |
| 606 | |
| 607 | if (!isset($data[$tids])) { |
| 608 | $result = db_query("SELECT nid, hidden, toc_hidden, toc_depth, toc_nodecount, lst_hidden, lst_teasers_hidden, serialized_data FROM {taxonomy_dss_term} WHERE tid = '%s'", $tids); |
| 609 | if ($row = db_fetch_object($result)) { |
| 610 | $row->serial_data = unserialize($row->serialized_data); |
| 611 | $data[$tids] = $row; |
| 612 | } |
| 613 | else { |
| 614 | $data[$tids] = new StdClass; |
| 615 | $data[$tids]->tids = $tids; |
| 616 | $data[$tids]->nid = 0; |
| 617 | $data[$tids]->hidden = 0; |
| 618 | $data[$tids]->toc_hidden = variable_get('taxonomy_dss_toc_hidden', 0); |
| 619 | $data[$tids]->toc_depth = variable_get('taxonomy_dss_toc_depth', 0); |
| 620 | $data[$tids]->toc_nodecount = variable_get('taxonomy_dss_toc_nodecount', 1); |
| 621 | $data[$tids]->lst_hidden = variable_get('taxonomy_dss_lst_hidden', 0); |
| 622 | $data[$tids]->lst_teasers_hidden = variable_get('taxonomy_dss_lst_teasers_hidden', 0); |
| 623 | $data[$tids]->serial_data = unserialize(''); |
| 624 | } |
| 625 | } |
| 626 | |
| 627 | return drupal_clone($data[$tids]); |
| 628 | } |
| 629 | |
| 630 | function taxonomy_dss_term_is_hidden($tids) { |
| 631 | $termset = taxonomy_dss_load($tids); |
| 632 | return $termset->hidden; |
| 633 | } |
| 634 | |
| 635 | function taxonomy_dss_get_nid($tids) { |
| 636 | $termset = taxonomy_dss_load($tids); |
| 637 | return $termset->nid; |
| 638 | } |
| 639 | |
| 640 | function taxonomy_dss_get_tids($nid) { |
| 641 | $tids = 0; |
| 642 | |
| 643 | $result = db_query("SELECT tid FROM {taxonomy_dss_term} WHERE nid = %d", $nid); |
| 644 | if ($row = db_fetch_array($result)) { |
| 645 | $tids = $row['tid']; |
| 646 | } |
| 647 | return $tids; |
| 648 | } |
| 649 | |
| 650 | function taxonomy_dss_get_current_tids() { |
| 651 | $tids = array(); |
| 652 | switch (arg(0)) { |
| 653 | case 'node': |
| 654 | if (is_numeric(arg(1))) { |
| 655 | $node = node_load(arg(1)); |
| 656 | if (!$node) { |
| 657 | break; |
| 658 | } |
| 659 | $tids = taxonomy_dss_filter_tids($node->taxonomy, isset($_GET['taxonomy']) ? $_GET['taxonomy'] : ''); |
| 660 | } |
| 661 | break; |
| 662 | case 'taxonomy': |
| 663 | if (arg(1) == 'term') { |
| 664 | $tids = explode(',', arg(2)); |
| 665 | } |
| 666 | break; |
| 667 | case 'faq': |
| 668 | if (module_exists('faq') && module_exists('path_redirect')) { |
| 669 | $result = db_query("SELECT path FROM {path_redirect} WHERE redirect = '%s'", 'faq'); |
| 670 | while ($row = db_fetch_array($result)) { |
| 671 | if (substr($row['path'], 0, 14) == 'taxonomy/term/') { |
| 672 | $names = array(); |
| 673 | $tids = explode(',', substr($row['path'], 14)); |
| 674 | } |
| 675 | } |
| 676 | } |
| 677 | break; |
| 678 | } |
| 679 | |
| 680 | return $tids; |
| 681 | } |
| 682 | |
| 683 | /** |
| 684 | * Extends taxonomy_terms_parse_string. |
| 685 | * Parses a comma or plus separated string of term IDs. |
| 686 | * |
| 687 | * @param $str_tids |
| 688 | * A string of term IDs, separated by plus or comma. |
| 689 | * comma (,) means AND. |
| 690 | * plus (+) means OR. |
| 691 | * @param $expand_parents |
| 692 | * (optional) Expands tids that have parents when TRUE. Defaults to FALSE. |
| 693 | * |
| 694 | * @return an associative array with an operator key (either 'and' or 'or'), |
| 695 | * a tids key containing an array of the term ids, and a names key |
| 696 | * containing the term names/titles. |
| 697 | */ |
| 698 | function taxonomy_dss_terms_parse_string($str_tids, $expand_parents = FALSE) { |
| 699 | static $termsets = array( |
| 700 | 'default' => array(), |
| 701 | 'expanded' => array(), |
| 702 | ); |
| 703 | |
| 704 | if ($expand_parents === FALSE) { |
| 705 | if (isset($termsets['default'][$str_tids])) { |
| 706 | return $termsets['default'][$str_tids]; |
| 707 | } |
| 708 | } |
| 709 | else { |
| 710 | if (isset($termsets['expanded'][$str_tids])) { |
| 711 | return $termsets['expanded'][$str_tids]; |
| 712 | } |
| 713 | } |
| 714 | |
| 715 | // Parse string |
| 716 | $terms = taxonomy_terms_parse_string($str_tids); |
| 717 | if ($terms['operator'] != 'and' && $terms['operator'] != 'or') { |
| 718 | drupal_not_found(); |
| 719 | } |
| 720 | |
| 721 | // Expand to include parents |
| 722 | if ($expand_parents) { |
| 723 | $tids = array(); |
| 724 | |
| 725 | foreach ($terms['tids'] as $tid) { |
| 726 | if ($parents = taxonomy_get_parents_all($tid)) { |
| 727 | while (count($parents)) { |
| 728 | $parent = array_pop($parents); |
| 729 | $tids[] = $parent->tid; |
| 730 | } |
| 731 | } |
| 732 | $tids[] = $tid; |
| 733 | } |
| 734 | |
| 735 | $terms['tids'] = $tids; |
| 736 | } |
| 737 | |
| 738 | // Retrieve the name for each term |
| 739 | if ($terms['tids']) { |
| 740 | $tids = array(); |
| 741 | $names = array(); |
| 742 | |
| 743 | $result = db_query(db_rewrite_sql('SELECT t.tid, t.name, (%s) AS weight FROM {term_data} t WHERE t.tid IN (%s) ORDER BY weight', 't', 'tid'), _taxonomy_dss_sql_order_tids($terms['tids']), implode(',', $terms['tids'])); |
| 744 | while ($term = db_fetch_object($result)) { |
| 745 | $tids[] = $term->tid; |
| 746 | $names[] = $term->name; |
| 747 | } |
| 748 | |
| 749 | $terms['tids'] = $tids; |
| 750 | $terms['names'] = $names; |
| 751 | } |
| 752 | |
| 753 | if ($expand_parents === FALSE) { |
| 754 | $termsets['default'][$str_tids] = $terms; |
| 755 | return $termsets['default'][$str_tids]; |
| 756 | } |
| 757 | else { |
| 758 | $termsets['expanded'][$str_tids] = $terms; |
| 759 | return $termsets['expanded'][$str_tids]; |
| 760 | } |
| 761 | } |
| 762 | |
| 763 | /** |
| 764 | * Derives title from a comma or plus separated string of term IDs. |
| 765 | * |
| 766 | * @param $str_tids |
| 767 | * A string of term IDs, separated by plus or comma. |
| 768 | * comma (,) means AND. |
| 769 | * plus (+) means OR. |
| 770 | * |
| 771 | * @return the derived title string. |
| 772 | **/ |
| 773 | function taxonomy_dss_get_title($str_tids) { |
| 774 | $terms = taxonomy_dss_terms_parse_string($str_tids, TRUE); |
| 775 | $title = implode(' › ', $terms['names']); |
| 776 | |
| 777 | return $title; |
| 778 | } |
| 779 | |
| 780 | /** |
| 781 | * Given an array of taxonomy terms, this function will validate it against |
| 782 | * a set of term IDs and strip out invalid ones. By default it will also strip |
| 783 | * out hidden terms. |
| 784 | * |
| 785 | * @param $taxonomy |
| 786 | * An array of taxonomy terms to be filtered. |
| 787 | * @param $tids |
| 788 | * An array of the valid taxonomy term IDs. |
| 789 | * @param $minimal |
| 790 | * (optional) When TRUE, this function will look at the weights of each term |
| 791 | * and its vocabulary, and remove the terms that are in the right order. |
| 792 | * Defaults to FALSE. |
| 793 | * @param $strip_hidden |
| 794 | * (optional) Strips hidden vocabularies when TRUE. Defaults to TRUE. |
| 795 | * |
| 796 | * @return |
| 797 | * An array of taxonomy term IDs, with hidden and excess terms stripped out. |
| 798 | */ |
| 799 | function taxonomy_dss_filter_tids($taxonomy, $tids = array(), $minimal = FALSE, $strip_hidden = TRUE) { |
| 800 | // Strip out other terms from the same vocabulary |
| 801 | $strip_same_vocabulary = TRUE; |
| 802 | |
| 803 | $return = array(); |
| 804 | |
| 805 | if (count($taxonomy) == 0) { |
| 806 | return $return; |
| 807 | } |
| 808 | |
| 809 | if (!is_array($tids)) { |
| 810 | if ($tids) { |
| 811 | $terms = taxonomy_dss_terms_parse_string($tids); |
| 812 | $tids = $terms['tids']; |
| 813 | } |
| 814 | else { |
| 815 | $tids = array(); |
| 816 | } |
| 817 | } |
| 818 | |
| 819 | $vids = array(); |
| 820 | $keys = array_keys($taxonomy); |
| 821 | |
| 822 | // Filter out invalid and hidden tids |
| 823 | for ($i = 0; $i < count($tids); $i++) { |
| 824 | /* |
| 825 | // If the term's vocabulary is hidden, don't return it |
| 826 | if ($strip_hidden) { |
| 827 | // Is this a valid tid? |
| 828 | if (in_array($tids[$i], $keys)) { |
| 829 | $term = $taxonomy[$tids[$i]]; |
| 830 | |
| 831 | // Cache vocabulary data |
| 832 | if (!isset($vids[$term->vid])) { |
| 833 | $vids[$term->vid] = taxonomy_dss_vocabulary_is_hidden($term->vid); |
| 834 | } |
| 835 | |
| 836 | // Only return tid if it's not hidden |
| 837 | if ($vids[$term->vid] == FALSE) { |
| 838 | $return[] = $term->tid; |
| 839 | } |
| 840 | } |
| 841 | } |
| 842 | else { |
| 843 | */ |
| 844 | // Is this a valid tid? |
| 845 | if (in_array($tids[$i], $keys)) { |
| 846 | $term = $taxonomy[$tids[$i]]; |
| 847 | |
| 848 | if (!isset($vids[$term->vid])) { |
| 849 | if ($strip_hidden) { |
| 850 | $vids[$term->vid] = taxonomy_dss_vocabulary_is_hidden($term->vid); |
| 851 | } |
| 852 | else { |
| 853 | $vids[$term->vid] = FALSE; |
| 854 | } |
| 855 | } |
| 856 | $return[] = $tids[$i]; |
| 857 | } |
| 858 | /* |
| 859 | } |
| 860 | */ |
| 861 | } |
| 862 | |
| 863 | // Filter out hidden tids, and add the remaining ones |
| 864 | for ($i = 0; $i < count($keys); $i++) { |
| 865 | if (!in_array($keys[$i], $return)) { |
| 866 | $term = $taxonomy[$keys[$i]]; |
| 867 | |
| 868 | if ($strip_hidden) { |
| 869 | // Cache vocabulary data |
| 870 | if (!isset($vids[$term->vid])) { |
| 871 | $vids[$term->vid] = taxonomy_dss_vocabulary_is_hidden($term->vid); |
| 872 | if ($strip_same_vocabulary == TRUE && $vids[$term->vid] == FALSE) { |
| 873 | $return[] = $term->tid; |
| 874 | } |
| 875 | } |
| 876 | |
| 877 | // Only return tid if it's not hidden |
| 878 | if ($strip_same_vocabulary == FALSE && $vids[$term->vid] == FALSE) { |
| 879 | $return[] = $term->tid; |
| 880 | } |
| 881 | } |
| 882 | else { |
| 883 | if ($strip_same_vocabulary) { |
| 884 | if (!isset($vids[$term->vid])) { |
| 885 | $vids[$term->vid] = FALSE; |
| 886 | $return[] = $keys[$i]; |
| 887 | } |
| 888 | } |
| 889 | else { |
| 890 | $return[] = $keys[$i]; |
| 891 | } |
| 892 | } |
| 893 | } |
| 894 | } |
| 895 | |
| 896 | // Filter out redundant tids (tids that are already in order of weight) |
| 897 | if ($minimal) { |
| 898 | for ($i = count($keys) -1; $i >= 0; $i--) { |
| 899 | if ($return[$i] == $keys[$i]) { |
| 900 | array_pop($return); |
| 901 | } |
| 902 | } |
| 903 | } |
| 904 | |
| 905 | return $return; |
| 906 | } |
| 907 | |
| 908 | function taxonomy_dss_select_children($tids) { |
| 909 | if (!is_array($tids) && is_numeric($tids)) { |
| 910 | $tids = array($tids); |
| 911 | } |
| 912 | if (count($tids) > 0) { |
| 913 | $joins = ''; |
| 914 | $wheres = ''; |
| 915 | foreach ($tids as $index => $tid) { |
| 916 | $joins .= ' INNER JOIN {term_node} tn'. $index .' ON n.nid = tn'. $index .'.nid'; |
| 917 | $wheres .= ' AND tn'. $index .'.tid = '. $tid; |
| 918 | } |
| 919 | $sql = "SELECT DISTINCT(n.nid) FROM {node} n {$joins} WHERE n.status = 1 {$wheres} AND (SELECT COUNT(DISTINCT td0.vid) FROM {term_node} t LEFT JOIN {term_data} td0 ON t.tid = td0.tid WHERE t.nid = n.nid) > ". count($tids); |
| 920 | |
| 921 | $sql = "SELECT tn.nid, tn.tid, td.vid, td.name, td.description, td.weight, v.weight AS vweight FROM {term_node} tn LEFT JOIN {term_data} td ON td.tid = tn.tid LEFT JOIN {vocabulary} v ON td.vid = v.vid WHERE tn.nid IN ({$sql}) AND td.vid NOT IN (SELECT td1.vid FROM {term_data} td1 WHERE td1.tid IN (". implode(',', $tids) .")) ORDER BY v.weight DESC, td.weight DESC, td.name DESC"; |
| 922 | |
| 923 | $sql = "SELECT DISTINCT r.tid, r.vid, r.name, r.description, r.weight, GROUP_CONCAT(DISTINCT r.tid ORDER BY r.vweight, r.weight, r.name SEPARATOR ',') AS tids FROM ({$sql}) r GROUP BY r.nid ORDER BY r.vweight, r.weight, r.name"; |
| 924 | |
| 925 | $result = db_query(db_rewrite_sql($sql, 'tn', 'randomfieldname')); |
| 926 | } |
| 927 | |
| 928 | return $result; |
| 929 | } |
| 930 | |
| 931 | function taxonomy_dss_get_tree_children($tids, &$result, $depth = 0) { |
| 932 | $children = array(); |
| 933 | |
| 934 | // Get all child terms |
| 935 | $child_terms = taxonomy_get_children(end($tids)); |
| 936 | |
| 937 | // Add all children from other vocabularies |
| 938 | if (db_num_rows($result) > 0) { |
| 939 | while ($term = db_fetch_object($result)) { |
| 940 | $child_terms[] = $term; |
| 941 | } |
| 942 | } |
| 943 | |
| 944 | foreach ($child_terms as $child) { |
| 945 | // Create a new tids array |
| 946 | $mytids = $tids; |
| 947 | |
| 948 | // Fix for child terms (not child terms from other vocabularies) |
| 949 | if (!isset($child->tids)) { |
| 950 | array_pop($mytids); |
| 951 | } |
| 952 | |
| 953 | $child->nodes = array(); |
| 954 | |
| 955 | // Is child a sub of other child(ren)? |
| 956 | if (strpos($child->tids, ',') !== FALSE) { |
| 957 | $atids = explode(',', $child->tids); |
| 958 | |
| 959 | $mychildren = &$children; |
| 960 | while (count($atids) > 1) { |
| 961 | $tid = array_shift($atids); |
| 962 | array_push($mytids, $tid); |
| 963 | |
| 964 | if (!isset($mychildren[$tid])) { |
| 965 | // Fetch missing term |
| 966 | $term = taxonomy_get_term($tid); |
| 967 | |
| 968 | $term->count = _taxonomy_dss_count_nodes($mytids); |
| 969 | // $term->children = array(); |
| 970 | $term->nodes = array(); |
| 971 | $term->pids = $mytids; |
| 972 | $term->link = 'taxonomy/term/'. implode(',', $mytids); |
| 973 | $term->hidden = taxonomy_dss_term_is_hidden(implode(',', $mytids)); |
| 974 | |
| 975 | $mychildren[$tid] = $term; |
| 976 | } |
| 977 | |
| 978 | // Handle terms from the same vocabulary |
| 979 | $next_term = taxonomy_get_term($atids[0]); |
| 980 | if ($mychildren[$tid]->vid !== $next_term->vid) { |
| 981 | if (!isset($mychildren[$tid]->children)) { |
| 982 | $mychildren[$tid]->children = array(); |
| 983 | } |
| 984 | $mychildren = &$mychildren[$tid]->children; |
| 985 | } |
| 986 | else { |
| 987 | array_pop($mytids); |
| 988 | } |
| 989 | |
| 990 | } |
| 991 | |
| 992 | // Add details |
| 993 | array_push($mytids, $child->tid); |
| 994 | $child->count = _taxonomy_dss_count_nodes($mytids); |
| 995 | $child->pids = $mytids; |
| 996 | $child->link = 'taxonomy/term/'. implode(',', $mytids); |
| 997 | $child->hidden = taxonomy_dss_term_is_hidden(implode(',', $mytids)); |
| 998 | |
| 999 | // Parent node should already be created |
| 1000 | $mychildren[$child->tid] = $child; |
| 1001 | } |
| 1002 | else { |
| 1003 | // Add details |
| 1004 | array_push($mytids, $child->tid); |
| 1005 | $child->count = _taxonomy_dss_count_nodes($mytids); |
| 1006 | |
| 1007 | if (count($tids) == 1 || $child->count > 0) { |
| 1008 | $child->pids = $mytids; |
| 1009 | $child->link = 'taxonomy/term/'. implode(',', $mytids); |
| 1010 | $child->hidden = taxonomy_dss_term_is_hidden(implode(',', $mytids)); |
| 1011 | |
| 1012 | if (!isset($child->tids)) { |
| 1013 | $mychildren = taxonomy_dss_get_tree_children($mytids, taxonomy_dss_select_children($mytids), 0); |
| 1014 | if (count($mychildren)) { |
| 1015 | $child->children = $mychildren; |
| 1016 | } |
| 1017 | } |
| 1018 | |
| 1019 | // Normal child, not a sub-child |
| 1020 | $children[$child->tid] = $child; |
| 1021 | } |
| 1022 | } |
| 1023 | } |
| 1024 | |
| 1025 | // Expand terms to include parent terms |
| 1026 | _taxonomy_dss_expand_terms($children, $tids); |
| 1027 | |
| 1028 | // Strip anything that's in a deeper level than requested |
| 1029 | if ($depth > 0) { |
| 1030 | _taxonomy_dss_limit_depth($children, $depth); |
| 1031 | } |
| 1032 | |
| 1033 | // Sort terms by weight: first by vocabulary weight, then by individual term weights |
| 1034 | _taxonomy_dss_sort_tree($children); |
| 1035 | |
| 1036 | return $children; |
| 1037 | } |
| 1038 | |
| 1039 | /** |
| 1040 | * Replacement for taxonomy_select_nodes. |
| 1041 | * Finds all nodes that match selected taxonomy conditions. |
| 1042 | * |
| 1043 | * @param $tids |
| 1044 | * An array of term IDs to match. |
| 1045 | * @param $operator |
| 1046 | * How to interpret multiple IDs in the array. Can be "or" or "and". |
| 1047 | * @param $depth |
| 1048 | * How many levels deep to traverse the taxonomy tree. Can be a nonnegative |
| 1049 | * integer or "all". |
| 1050 | * @param $pager |
| 1051 | * Whether the nodes are to be used with a pager (the case on most Drupal |
| 1052 | * pages) or not (in an XML feed, for example). |
| 1053 | * @param $order |
| 1054 | * The order clause for the query that retrieve the nodes. |
| 1055 | * @return |
| 1056 | * A resource identifier pointing to the query results. |
| 1057 | */ |
| 1058 | function taxonomy_dss_select_nodes($tids = array(), $operator = 'or', $depth = 0, $pager = TRUE, $order = 'n.sticky DESC, n.created DESC', $exclusive = TRUE, $promoted = FALSE, $nodecount = 0) { |
| 1059 | if (count($tids) > 0) { |
| 1060 | // For each term ID, generate an array of descendant term IDs to the right depth. |
| 1061 | $descendant_tids = array(); |
| 1062 | if ($depth === 'all') { |
| 1063 | $depth = NULL; |
| 1064 | } |
| 1065 | foreach ($tids as $index => $tid) { |
| 1066 | $term = taxonomy_get_term($tid); |
| 1067 | $tree = taxonomy_get_tree($term->vid, $tid, -1, $depth); |
| 1068 | $descendant_tids[] = array_merge(array($tid), array_map('_taxonomy_get_tid_from_term', $tree)); |
| 1069 | } |
| 1070 | |
| 1071 | $promote_sql = $promoted ? 'AND n.promote = 1 ' : ''; |
| 1072 | |
| 1073 | if ($operator == 'or') { |
| 1074 | $str_tids = implode(',', call_user_func_array('array_merge', $descendant_tids)); |
| 1075 | $sql = 'SELECT DISTINCT(n.nid), n.sticky, n.title, n.created FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN ('. $str_tids .') '. $promote_sql .'AND n.status = 1 ORDER BY '. $order; |
| 1076 | $sql_count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid IN ('. $str_tids .') '. $promote_sql .'AND n.status = 1'; |
| 1077 | } |
| 1078 | else { |
| 1079 | $joins = ''; |
| 1080 | $wheres = ''; |
| 1081 | foreach ($descendant_tids as $index => $tids) { |
| 1082 | $joins .= ' INNER JOIN {term_node} tn'. $index .' ON n.nid = tn'. $index .'.nid'; |
| 1083 | $wheres .= ' AND tn'. $index .'.tid IN ('. implode(',', $tids) .')'; |
| 1084 | } |
| 1085 | if ($exclusive) { |
| 1086 | $sql = 'SELECT DISTINCT(n.nid), n.sticky, n.title, n.created FROM {node} n '. $joins .' WHERE n.status = 1 '. $promote_sql . $wheres .' AND (SELECT COUNT(DISTINCT td0.vid) FROM {term_node} t LEFT JOIN {term_data} td0 ON t.tid = td0.tid WHERE t.nid = n.nid) = '. count($descendant_tids) .' ORDER BY '. $order; |
| 1087 | $sql_count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n '. $joins .' AND (SELECT COUNT(*) FROM {term_node} t WHERE t.nid = n.nid) = '. count($descendant_tids) .' WHERE n.status = 1 '. $promote_sql . $wheres; |
| 1088 | } |
| 1089 | else { |
| 1090 | $sql = 'SELECT DISTINCT(n.nid), n.sticky, n.title, n.created FROM {node} n '. $joins .' WHERE n.status = 1 '. $promote_sql . $wheres .' ORDER BY '. $order; |
| 1091 | $sql_count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n '. $joins .' WHERE n.status = 1 '. $promote_sql . $wheres; |
| 1092 | } |
| 1093 | } |
| 1094 | // Once Taxonomy Acccess Control or any other acces control module gets |
| 1095 | // enabled, it tries to mess with the SQL unless you set the fieldname to |
| 1096 | // something it doesn't recognize. |
| 1097 | $sql = db_rewrite_sql($sql, 'tn', 'randomfieldname'); |
| 1098 | $sql_count = db_rewrite_sql($sql_count, 'tn', 'randomfieldname'); |
| 1099 | |
| 1100 | if ($pager) { |
| 1101 | if ($nodecount == 0) { |
| 1102 | $nodecount = variable_get('default_nodes_main', 10); |
| 1103 | } |
| 1104 | $result = pager_query($sql, $nodecount, 0, $sql_count); |
| 1105 | } |
| 1106 | else { |
| 1107 | if ($nodecount == 0) { |
| 1108 | $nodecount = variable_get('feed_default_items', 10); |
| 1109 | } |
| 1110 | $result = db_query_range($sql, 0, $nodecount); |
| 1111 | } |