| 1 |
<?php
|
| 2 |
// $Id: taxonomy_sifter.module,v 1.3.4.5 2008/11/15 17:37:26 tbarregren Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* Taxonomy Sifter - provides a block for selecting a term to filter nodes.
|
| 7 |
*
|
| 8 |
* Authors:
|
| 9 |
* Thomas Barregren <http://drupal.org/user/16678>.
|
| 10 |
* Nancy Wichmann <http://drupal.org/user/101412>.
|
| 11 |
*
|
| 12 |
* Sponsors:
|
| 13 |
* SSPA Sweden <http://www.sspa.se/>
|
| 14 |
* imBridge <http://www.imbridge.com/>
|
| 15 |
*/
|
| 16 |
|
| 17 |
/**
|
| 18 |
* Implementation of hook_perm().
|
| 19 |
*/
|
| 20 |
function taxonomy_sifter_perm() {
|
| 21 |
return array('administer taxonomy sifter', 'view sifter block');
|
| 22 |
}
|
| 23 |
|
| 24 |
/**
|
| 25 |
* Implementation of hook_menu().
|
| 26 |
*/
|
| 27 |
function _taxonomy_sifter_menu() {
|
| 28 |
$items = array();
|
| 29 |
$items['taxonomy/term'] = array(
|
| 30 |
'type' => MENU_CALLBACK,
|
| 31 |
'page callback' => 'taxonomy_sifter_taxonomy_term_filter',
|
| 32 |
'access arguments' => array('access content'),
|
| 33 |
);
|
| 34 |
return $items;
|
| 35 |
}
|
| 36 |
|
| 37 |
function taxonomy_sifter_menu_alter(&$items) {
|
| 38 |
$items['taxonomy/term/%']['page callback'] = 'taxonomy_sifter_taxonomy_term_filter';
|
| 39 |
unset($items['taxonomy/term/%']['file']);
|
| 40 |
}
|
| 41 |
|
| 42 |
/**
|
| 43 |
* Implementation of hook_block().
|
| 44 |
*/
|
| 45 |
function taxonomy_sifter_block($op = 'list', $delta = 0, $edit = array()) {
|
| 46 |
$function = "_taxonomy_sifter_block_$op";
|
| 47 |
if (function_exists($function)) {
|
| 48 |
return $function($delta, $edit);
|
| 49 |
}
|
| 50 |
else { drupal_set_message("$function does not exist."); }
|
| 51 |
}
|
| 52 |
|
| 53 |
/**
|
| 54 |
* Implementation of hook_help().
|
| 55 |
*/
|
| 56 |
function taxonomy_sifter_help($path, $args) {
|
| 57 |
switch ($path) {
|
| 58 |
case 'admin/modules#description':
|
| 59 |
return t('Provides a block with terms which <em>any</em> or <em>all</em> selected must apply to a node for it to be listed when viewing a taxonomy term page, e.g. <code>taxonomy/term/...</code>');
|
| 60 |
|
| 61 |
case 'admin/help#taxonomy_sifter':
|
| 62 |
return t('<p><a href="http://drupal.org/project/taxonomy_sifter">Taxonomy Sifter</a> provides a block where the user can select terms that will automatically be combined with the terms in every request of the form <code>taxonomy/term/...</code> for the duration of their session. The selected terms are combined with the same operator already used in the request. If no operator is used, that is a single term is given, the sifter uses the operator given in the module\'s settings. The vocabularies of the terms presented in the sifter block is also configurable. For further documentation, see the <a href="http://drupal.org/node/22273">handbook</a>.</p>');
|
| 63 |
}
|
| 64 |
}
|
| 65 |
|
| 66 |
/**
|
| 67 |
* BLOCK API
|
| 68 |
*/
|
| 69 |
|
| 70 |
/**
|
| 71 |
* Blocks are listed.
|
| 72 |
*/
|
| 73 |
function _taxonomy_sifter_block_list() {
|
| 74 |
$blocks[0]['info'] = t('Taxonomy Sifter');
|
| 75 |
return $blocks;
|
| 76 |
}
|
| 77 |
|
| 78 |
/**
|
| 79 |
* Blocks are configured.
|
| 80 |
*/
|
| 81 |
function _taxonomy_sifter_block_configure($delta, $edit) {
|
| 82 |
drupal_add_css(drupal_get_path('module', 'taxonomy_sifter') .'/taxonomy_sifter.css');
|
| 83 |
$form = array('#attributes' => array('class' => 'taxonomy-sifter'));
|
| 84 |
// Check that the user has permission to use the taxonomy sifter.
|
| 85 |
if (!user_access('administer taxonomy sifter')) {
|
| 86 |
$form['taxonomy_sifter'] = array(
|
| 87 |
'#type' => 'markup',
|
| 88 |
'#value' => '<p>'. t('You do not have permission to use the taxonomy sifter.') .'</p>',
|
| 89 |
);
|
| 90 |
return $form;
|
| 91 |
}
|
| 92 |
|
| 93 |
// Get all available vocabularies.
|
| 94 |
$vocabularies = _taxonomy_sifter_db_get_vocabularies();
|
| 95 |
|
| 96 |
// Show checkboxes with roles that can be delegated if any.
|
| 97 |
if ($vocabularies) {
|
| 98 |
$form['taxonomy_sifter'] = array(
|
| 99 |
'#type' => 'fieldset',
|
| 100 |
'#title' => t('Taxonomy Sifter Settings'),
|
| 101 |
'#collapsible' => TRUE,
|
| 102 |
'#collapsed' => FALSE,
|
| 103 |
);
|
| 104 |
|
| 105 |
$form['taxonomy_sifter']['taxonomy_sifter_vocabularies'] = array(
|
| 106 |
'#type' => 'checkboxes',
|
| 107 |
'#title' => t('Vocabularies'),
|
| 108 |
'#options' => $vocabularies,
|
| 109 |
'#default_value' => _taxonomy_sifter_variable_vocabularies(),
|
| 110 |
'#description' => t('Select vocabularies that should be available in the Taxonomy Sifter block.'),
|
| 111 |
'#prefix' => '<div class="taxonomy-sifter-checkboxes">',
|
| 112 |
'#suffix' => '</div>',
|
| 113 |
);
|
| 114 |
|
| 115 |
$form['taxonomy_sifter']['taxonomy_sifter_operator'] = array(
|
| 116 |
'#type' => 'radios',
|
| 117 |
'#title' => t('Default operator'),
|
| 118 |
'#options' => array(t('or (any term)'), t('and (all terms)')),
|
| 119 |
'#default_value' => _taxonomy_sifter_variable_operator(),
|
| 120 |
'#description' => t('Select the default term filter. When a taxonomy term page or feed is requested, the given terms are combined with those selected in the Taxonomy Sifter block. If more than one term is given in the request, the combination is done with the operator used in the request. If only one term is given, the operator selected above is used.'),
|
| 121 |
'#prefix' => '<div class="taxonomy-sifter-radios">',
|
| 122 |
'#suffix' => '</div>',
|
| 123 |
);
|
| 124 |
|
| 125 |
$display_opts = array(
|
| 126 |
'select' => t('Select list'),
|
| 127 |
'checkboxes' => t('Check boxes'),
|
| 128 |
'buttons' => t('Buttons'),
|
| 129 |
);
|
| 130 |
$form['taxonomy_sifter']['taxonomy_sifter_select_type'] = array(
|
| 131 |
'#type' => 'radios',
|
| 132 |
'#title' => t('Display choices as'),
|
| 133 |
'#options' => $display_opts,
|
| 134 |
'#default_value' => variable_get('taxonomy_sifter_select_type', 'select'),
|
| 135 |
'#description' => t('This determines how the possible choices will be shown.'),
|
| 136 |
'#prefix' => '<div class="taxonomy-sifter-radios">',
|
| 137 |
'#suffix' => '</div>',
|
| 138 |
);
|
| 139 |
}
|
| 140 |
else {
|
| 141 |
$form['taxonomy_sifter'] = array(
|
| 142 |
'#type' => 'markup',
|
| 143 |
'#value' => '<p>'. t('No vocabulary is available.') .'</p>',
|
| 144 |
);
|
| 145 |
}
|
| 146 |
|
| 147 |
return $form;
|
| 148 |
}
|
| 149 |
|
| 150 |
/**
|
| 151 |
* Save block setings.
|
| 152 |
*/
|
| 153 |
function _taxonomy_sifter_block_save($delta, $edit) {
|
| 154 |
_taxonomy_sifter_variable_vocabularies($edit['taxonomy_sifter_vocabularies']);
|
| 155 |
_taxonomy_sifter_variable_operator($edit['taxonomy_sifter_operator']);
|
| 156 |
variable_set('taxonomy_sifter_select_type', $edit['taxonomy_sifter_select_type']);
|
| 157 |
}
|
| 158 |
|
| 159 |
/**
|
| 160 |
* Block is viewed.
|
| 161 |
*/
|
| 162 |
function _taxonomy_sifter_block_view($vid) {
|
| 163 |
if (user_access('view sifter block') && arg(0) == 'taxonomy' && arg(1) == 'term') {
|
| 164 |
drupal_add_css(drupal_get_path('module', 'taxonomy_sifter') .'/taxonomy_sifter.css');
|
| 165 |
$vocabularies = _taxonomy_sifter_db_get_vocabularies();
|
| 166 |
$block = array(
|
| 167 |
'content' => drupal_get_form('_taxonomy_sifter_block_form', $vid),
|
| 168 |
);
|
| 169 |
return $block;
|
| 170 |
}
|
| 171 |
}
|
| 172 |
|
| 173 |
/**
|
| 174 |
* BLOCK CONTENT AND FORM PROCESSING
|
| 175 |
*/
|
| 176 |
|
| 177 |
/**
|
| 178 |
* Returns the themed content of the taxonomy sifter block of $vid.
|
| 179 |
*/
|
| 180 |
function _taxonomy_sifter_block_form($form, $vid) {
|
| 181 |
$form = array();
|
| 182 |
|
| 183 |
// Submit and reset buttons
|
| 184 |
$form['buttons']['#weight'] = 99;
|
| 185 |
$form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Sift'));
|
| 186 |
$form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset'));
|
| 187 |
|
| 188 |
// Get the names of all vocabularies.
|
| 189 |
$vocabularies = _taxonomy_sifter_db_get_vocabularies();
|
| 190 |
|
| 191 |
// Get the available vocabularies.
|
| 192 |
$vids = _taxonomy_sifter_variable_vocabularies();
|
| 193 |
$vids = array_filter($vids);
|
| 194 |
|
| 195 |
$curr_selection = _taxonomy_sifter_session_get_terms();
|
| 196 |
$curr_selection = $curr_selection[0];
|
| 197 |
|
| 198 |
drupal_set_message(print_r($x, true));
|
| 199 |
$select_type = variable_get('taxonomy_sifter_select_type', 'select');
|
| 200 |
$current = taxonomy_get_term(arg(2));
|
| 201 |
$curr_tid = $current->tid;
|
| 202 |
$oper = variable_get('taxonomy_sifter_operator', 0);
|
| 203 |
|
| 204 |
// For each vocabulary, add a select element of its terms.
|
| 205 |
foreach ($vids as $vid) {
|
| 206 |
// Build a list of terms to be presented in the select element.
|
| 207 |
$options = array();
|
| 208 |
$tree = taxonomy_get_tree($vid);
|
| 209 |
foreach ($tree as $term) {
|
| 210 |
if ($oper == 0) {
|
| 211 |
$sql = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {term_node} tn ON n.vid = tn.vid WHERE tn.tid IN (%d,%d) AND n.status = 1';
|
| 212 |
}
|
| 213 |
else {
|
| 214 |
$sql = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {term_node} tn1 ON n.vid = tn1.vid INNER JOIN {term_node} tn2 ON n.vid = tn2.vid WHERE tn1.tid = %d AND tn2.tid = %d AND n.status = 1';
|
| 215 |
}
|
| 216 |
$count = db_result(db_query($sql, $curr_tid, $term->tid));
|
| 217 |
if ($count > 0) {
|
| 218 |
$options[$term->tid] = str_repeat($term->depth, '-') . $term->name;
|
| 219 |
}
|
| 220 |
}
|
| 221 |
|
| 222 |
// Build and return the select element.
|
| 223 |
switch ($select_type) {
|
| 224 |
case 'checkboxes':
|
| 225 |
case 'select':
|
| 226 |
$form["taxonomy_sifter_terms_$vid"] = array(
|
| 227 |
'#title' => t('Sift by @vid', array('@vid' => $vocabularies[$vid])),
|
| 228 |
'#type' => $select_type,
|
| 229 |
'#multiple' => TRUE,
|
| 230 |
'#options' => $options,
|
| 231 |
'#default_value' => _taxonomy_sifter_session_get_terms($vid),
|
| 232 |
);
|
| 233 |
break;
|
| 234 |
|
| 235 |
case 'buttons':
|
| 236 |
foreach ($options as $tid => $name) {
|
| 237 |
$class = 'taxonomy-sifter-term-button';
|
| 238 |
if ($curr_selection == $tid) {
|
| 239 |
$class .= ' active';
|
| 240 |
}
|
| 241 |
$form[$name] = array(
|
| 242 |
'#type' => 'submit',
|
| 243 |
'#value' => check_plain($name),
|
| 244 |
'#attributes' => array('class' => $class),
|
| 245 |
);
|
| 246 |
}
|
| 247 |
unset($form['buttons']['submit']);
|
| 248 |
}
|
| 249 |
}
|
| 250 |
|
| 251 |
return $form;
|
| 252 |
}
|
| 253 |
|
| 254 |
/**
|
| 255 |
* Process the submited form.
|
| 256 |
*/
|
| 257 |
function _taxonomy_sifter_block_form_submit($form, &$form_state) {
|
| 258 |
// @TODO: Change to dedicated functions from form.
|
| 259 |
$op = isset($form_state['values']['op']) ? $form_state['values']['op'] : '';
|
| 260 |
switch ($op) {
|
| 261 |
case t('Sift'):
|
| 262 |
// Clear away extra stuff in values.
|
| 263 |
foreach ($form_state['values'] as $name => $value) {
|
| 264 |
if (drupal_substr($name, 0, 22) != 'taxonomy_sifter_terms_') {
|
| 265 |
unset($form_state['values'][$name]);
|
| 266 |
}
|
| 267 |
}
|
| 268 |
_taxonomy_sifter_session_set_terms($form_state['values']);
|
| 269 |
break;
|
| 270 |
|
| 271 |
case t('Reset'):
|
| 272 |
_taxonomy_sifter_session_set_terms(array());
|
| 273 |
break;
|
| 274 |
|
| 275 |
default:
|
| 276 |
// $op is term name on select type = button.
|
| 277 |
// But the value may have leading '-' due to term hierarchy.
|
| 278 |
$op = trim($op, '- ');
|
| 279 |
$term = taxonomy_get_term_by_name($op);
|
| 280 |
$_SESSION['taxonomy_sifter_terms']['taxonomy_sifter_terms_'.$term[0]->vid] = array($term[0]->tid => $term[0]->tid);
|
| 281 |
}
|
| 282 |
}
|
| 283 |
|
| 284 |
/**
|
| 285 |
* FILTERING BY TAXONOMY
|
| 286 |
*/
|
| 287 |
|
| 288 |
/**
|
| 289 |
* Intercept the 'taxonomy/term' callback function to complement the terms' id
|
| 290 |
* in the URL with those of the terms selcted in the block.
|
| 291 |
*/
|
| 292 |
function taxonomy_sifter_taxonomy_term_filter($terms, $depth = 0, $feed = 'page') {
|
| 293 |
$terms = _taxonomy_sifter_rewrite_filter($terms);
|
| 294 |
module_load_include('inc', 'taxonomy', 'taxonomy.pages');
|
| 295 |
return taxonomy_term_page($terms, $depth, $feed);
|
| 296 |
}
|
| 297 |
|
| 298 |
/**
|
| 299 |
* Rewrite the taxonomy filter.
|
| 300 |
*/
|
| 301 |
function _taxonomy_sifter_rewrite_filter($filter) {
|
| 302 |
$original = $filter;
|
| 303 |
// Get the terms selected in the block.
|
| 304 |
$terms = _taxonomy_sifter_session_get_terms();
|
| 305 |
|
| 306 |
// If terms are selected, add them to the filter.
|
| 307 |
if ($terms) {
|
| 308 |
// Extract the terms already in the filter.
|
| 309 |
// Note 1: Only one kind of taxonomy operators + and , can be used in the
|
| 310 |
// URL. Therefore we must use the same operator as already in the URL. If
|
| 311 |
// no such operator is avaiable, we use the configured default operator.
|
| 312 |
// Note 2: a plus sign in the URL is converted to space.
|
| 313 |
$op_lut = array(' ', ',');
|
| 314 |
$op_def = _taxonomy_sifter_variable_operator();
|
| 315 |
$op = $op_lut[$op_def];
|
| 316 |
$filter = explode($op, $filter);
|
| 317 |
if (count($filter) == 1) {
|
| 318 |
// The default operator wasn't used in the filter.
|
| 319 |
// Swap operator and try again.
|
| 320 |
$op = $op_lut[($op_def + 1) % 2];
|
| 321 |
$filter = explode($op, $filter[0]);
|
| 322 |
if (count($filter) == 1) {
|
| 323 |
// The other operator wasn't used either.
|
| 324 |
// Swap back to the default operator.
|
| 325 |
$op = $op_lut[$op_def];
|
| 326 |
}
|
| 327 |
}
|
| 328 |
|
| 329 |
// Add the terms selected in the block to the terms already in the filter.
|
| 330 |
$filter = array_merge($filter, $terms);
|
| 331 |
$filter = array_flip(array_flip($filter)); // array_unique() is overkill
|
| 332 |
|
| 333 |
// Build the filter string
|
| 334 |
$filter = implode($op, $filter);
|
| 335 |
}
|
| 336 |
|
| 337 |
return $filter;
|
| 338 |
}
|
| 339 |
|
| 340 |
/**
|
| 341 |
* DATABASE
|
| 342 |
*/
|
| 343 |
|
| 344 |
/**
|
| 345 |
* Get available vocabularies.
|
| 346 |
*/
|
| 347 |
function _taxonomy_sifter_db_get_vocabularies() {
|
| 348 |
static $vocabularies;
|
| 349 |
if (!isset($vocabularies)) {
|
| 350 |
$vocabularies = array();
|
| 351 |
$result = db_query('SELECT vid, name FROM {vocabulary} ORDER BY weight, name');
|
| 352 |
while ($vocabulary = db_fetch_object($result)) {
|
| 353 |
$vocabularies[$vocabulary->vid] = $vocabulary->name;
|
| 354 |
}
|
| 355 |
}
|
| 356 |
return $vocabularies;
|
| 357 |
}
|
| 358 |
|
| 359 |
/**
|
| 360 |
* PERSISTENT VARIABLES
|
| 361 |
*/
|
| 362 |
|
| 363 |
/**
|
| 364 |
* Sets and gets selected vocabularies.
|
| 365 |
*/
|
| 366 |
function _taxonomy_sifter_variable_vocabularies($vocabularies = NULL) {
|
| 367 |
return _taxonomy_sifter_variable('taxonomy_sifter_vocabularies', $vocabularies, array());
|
| 368 |
}
|
| 369 |
|
| 370 |
/**
|
| 371 |
* Sets and gets selected operator.
|
| 372 |
*/
|
| 373 |
function _taxonomy_sifter_variable_operator($operator = NULL) {
|
| 374 |
return _taxonomy_sifter_variable('taxonomy_sifter_operator', $operator, 0);
|
| 375 |
}
|
| 376 |
|
| 377 |
/**
|
| 378 |
* Sets and gets the named persisted variable.
|
| 379 |
*/
|
| 380 |
function _taxonomy_sifter_variable($name, $value = NULL, $default = NULL) {
|
| 381 |
if (isset($value)) {
|
| 382 |
variable_set($name, $value);
|
| 383 |
}
|
| 384 |
return variable_get($name, $default);
|
| 385 |
}
|
| 386 |
|
| 387 |
/**
|
| 388 |
* SESSION VARIABLES
|
| 389 |
*/
|
| 390 |
|
| 391 |
/**
|
| 392 |
* Returns the selected terms.
|
| 393 |
*/
|
| 394 |
function _taxonomy_sifter_session_get_terms($vid = NULL) {
|
| 395 |
if (is_null($vid)) {
|
| 396 |
$terms = array();
|
| 397 |
if (isset($_SESSION['taxonomy_sifter_terms'])) {
|
| 398 |
$terms = $_SESSION['taxonomy_sifter_terms'];
|
| 399 |
}
|
| 400 |
if ($terms) {
|
| 401 |
$terms = call_user_func_array('array_merge', $terms); // Flattens the array.
|
| 402 |
}
|
| 403 |
}
|
| 404 |
else {
|
| 405 |
if (!isset($_SESSION['taxonomy_sifter_terms']["taxonomy_sifter_terms_$vid"])) {
|
| 406 |
$_SESSION['taxonomy_sifter_terms']["taxonomy_sifter_terms_$vid"] = array();
|
| 407 |
}
|
| 408 |
return $_SESSION['taxonomy_sifter_terms']["taxonomy_sifter_terms_$vid"];
|
| 409 |
}
|
| 410 |
return $terms;
|
| 411 |
}
|
| 412 |
|
| 413 |
/**
|
| 414 |
* Set the selected terms.
|
| 415 |
*/
|
| 416 |
function _taxonomy_sifter_session_set_terms($terms = array()) {
|
| 417 |
$_SESSION['taxonomy_sifter_terms'] = $terms;
|
| 418 |
}
|