hs_taxonomy_views.module in Hierarchical Select 5.3
Same filename and directory in other branches
Implementation of the Hierarchical Select API for the Taxonomy module's Views exposed filters.
File
modules/hs_taxonomy_views.moduleView source
<?php
/**
* @file
* Implementation of the Hierarchical Select API for the Taxonomy module's
* Views exposed filters.
*/
//----------------------------------------------------------------------------
// Core hooks.
/**
* Implementation of hook_menu().
*/
function hs_taxonomy_views_menu($may_cache) {
$items = array();
if (!$may_cache && arg(0) == 'admin' && arg(1) == 'build' && arg(2) == 'views' && is_string(arg(3)) && arg(4) == 'hs_config' && is_numeric(arg(5))) {
$view_name = arg(3);
$vid = arg(5);
// Vocabulary ID, not View ID!
$items[] = array(
'path' => "admin/build/views/{$view_name}/hs_config/{$vid}",
'title' => t('Hierarchical Select configuration for !view', array(
'!view' => $view_name,
)),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'hs_taxonomy_views_config_form',
$view_name,
$vid,
),
'access' => user_access('administer views'),
'type' => MENU_NORMAL_ITEM,
);
}
return $items;
}
/**
* Implementation of hook_form_alter().
*/
function hs_taxonomy_views_form_alter($form_id, &$form) {
// Change the exposed filters of Views. Only affects hierarchical vocabulary
// filters.
if (in_array($form_id, array(
'views_filters',
'views_filterblock',
))) {
$hs_exposed_filters_found = 0;
// Find the ids and vocabulary ids of the exposed filters.
foreach ($form['view']['#value']->exposed_filter as $id => $filter) {
if (preg_match("/term_node_(\\d+)\\.tid/", $filter['field'], $matches)) {
$vid = $matches[1];
// Only apply Hierarchical Select if it's enabled for this vocabulary.
if (variable_get("taxonomy_hierarchical_select_{$vid}", 0)) {
$hs_exposed_filters_found++;
$vocabulary = taxonomy_get_vocabulary($vid);
$view = $form['view']['#value'];
// Make it use a hierarchical select.
require_once drupal_get_path('module', 'hierarchical_select') . '/includes/common.inc';
unset($form["filter{$id}"]['#options']);
unset($form["filter{$id}"]['#theme']);
unset($form["filter{$id}"]['#size']);
$form["filter{$id}"]['#type'] = 'hierarchical_select';
$defaults_override = array(
'module' => 'hs_taxonomy_views',
'params' => array(
'optional' => (bool) $view->exposed_filter[$id]['optional'],
'vid' => $vid,
'exclude_tid' => NULL,
'root_term' => NULL,
),
// When the **ALL** option is selected, nothing else should be.
'exclusive_lineages' => array(
'**ALL**',
),
// This is a GET form, so also render the flat select.
'render_flat_select' => 1,
);
hierarchical_select_common_config_apply($form["filter{$id}"], "taxonomy-views-{$view->name}-{$vid}", $defaults_override);
// Inherit #required from the exposed filter settings.
$form["filter{$id}"]['#required'] = !(bool) $view->exposed_filter[$id]['optional'];
// Put the altered exposed filters in a separate table row.
hierarchical_select_common_views_exposed_filters_reposition();
}
}
}
if ($hs_exposed_filters_found > 0) {
// Views will remove the form_id in views_filters_process(), but we need
// it for Hierarchical Select to work, so put it back.
$form['copy_of_form_id'] = $form['form_id'] + array(
'#parents' => array(
'form_id',
),
);
}
}
// Alter the edit view form: add a link to the Hierarchical Select
// configuration when appropriate and to mark which settings are now managed
// by the Hierarchical Select configuration.
if ($form_id == 'views_edit_view') {
foreach ($form['exposed_filter'] as $filter_id => $filter) {
if (is_numeric($filter_id)) {
$id = $form['exposed_filter'][$filter_id]['id']['#default_value'];
if (preg_match("/term_node_(\\d+)\\.tid/", $id, $matches)) {
$vid = $matches[1];
if (variable_get("taxonomy_hierarchical_select_{$vid}", 0)) {
$view = $form['#parameters'][1];
$link = l(t('Configure Hierarchical Select'), "admin/build/views/{$view->name}/hs_config/{$vid}");
$form['exposed_filter'][$filter_id]['name']['#value'] .= '<br />' . $link;
// Alter the form to support the current Hierarchical Select
// config.
require_once drupal_get_path('module', 'hierarchical_select') . '/includes/common.inc';
$config_id = "taxonomy-views-{$view->name}-{$vid}";
$config = hierarchical_select_common_config_get($config_id);
$text = t('This setting is now managed by the<br />Hierarchical Select configuration!');
// Exposed filter's "Force single" setting.
$form['exposed_filter'][$filter_id]['single']['#description'] = $text;
// Additional settings when save_lineage is enabled.
if ($config['save_lineage']) {
// Filter's "Operator" setting.
$form['filter'][$filter_id]['operator']['#description'] = $text;
// Exposed filter's "Lock Operator" setting.
$form['exposed_filter'][$filter_id]['operator']['#description'] = $text;
}
}
}
}
}
}
}
/**
* Implementation of hook_requirements().
*/
function hs_taxonomy_views_requirements($phase) {
$requirements = array();
if ($phase == 'runtime') {
$pattern = <<<EOT
function _views_build_filters_form(\$view) {
// When the form is retrieved through an AJAX callback, the cache hasn't
// been loaded yet. The cache is necesssary for _views_get_filters().
views_load_cache();
EOT;
$views_with_patch_257004 = preg_match('#' . preg_quote($pattern) . '#m', file_get_contents(drupal_get_path('module', 'views') . '/views.module'));
if ($views_with_patch_257004) {
$value = t('The Views module is new enough.');
$description = '';
$severity = REQUIREMENT_OK;
}
else {
$value = t('The Views module is outdated.');
$description = t("The version of Views that you have installed is either\n older than May 11, 2008, or doesn't have the obligatory patch applied.\n Please apply the <a href=\"!patch_url\">patch</a> or update to a newer\n version of the Views module!", array(
'!patch_url' => 'http://drupal.org/files/issues/hs_compatibility.patch',
));
$severity = REQUIREMENT_ERROR;
}
$requirements['hs_taxonomy_views'] = array(
'title' => t('Hierarchical Select Views Taxonomy'),
'value' => $value,
'description' => $description,
'severity' => $severity,
);
}
return $requirements;
}
//----------------------------------------------------------------------------
// Forms API callbacks.
/**
* Form definition; configuration form for Hierarchical Select as the widget
* for a Taxonomy exposed filter.
*
* @param $view_name
* Name of a view. Provides necessary context.
* @param $vid
* A vocabulary id. Provides necessary context.
*/
function hs_taxonomy_views_config_form($view_name, $vid) {
require_once drupal_get_path('module', 'hierarchical_select') . '/includes/common.inc';
// Find the exposed filter, we need this to set the default value of
// $config['dropbox']['status'].
$view = views_get_view($view_name);
foreach ($view->exposed_filter as $filter) {
if ($filter['id'] == "term_node_{$vid}.tid") {
$exposed_filter = $filter;
break;
}
}
// Add the Hierarchical Select config form.
$module = 'hs_taxonomy_views';
$params = array(
'optional' => (bool) $view->exposed_filter[$id]['optional'],
'vid' => $vid,
'exclude_tid' => NULL,
'root_term' => NULL,
);
$config_id = "taxonomy-views-{$view_name}-{$vid}";
$vocabulary = taxonomy_get_vocabulary($vid);
$defaults = array(
// Enable the save_lineage setting by default if the multiple parents
// vocabulary option is enabled.
'save_lineage' => (int) ($vocabulary->hierarchy == 2),
'dropbox' => array(
'status' => !$exposed_filter['single'],
),
'editability' => array(
'max_levels' => _hs_taxonomy_hierarchical_select_get_depth($vid),
),
);
$strings = array(
'hierarchy' => t('vocabulary'),
'hierarchies' => t('vocabularies'),
'item' => t('term'),
'items' => t('terms'),
'item_type' => t('term type'),
'entity' => t('node'),
'entities' => t('nodes'),
);
$max_hierarchy_depth = _hs_taxonomy_hierarchical_select_get_depth($vid);
$preview_is_required = !(bool) $exposed_filter['optional'];
$form['hierarchical_select_config'] = hierarchical_select_common_config_form($module, $params, $config_id, $defaults, $strings, $max_hierarchy_depth, $preview_is_required);
$form['hierarchical_select_config']['save_lineage']['#description'] .= '<br />' . t('When you enable the %save_lineage setting, you will have to resave the
"Edit view" form as well!', array(
'%save_lineage' => $form['hierarchical_select_config']['save_lineage']['#options'][1],
));
$form['link'] = array(
'#value' => l('Back to the view configuration', "admin/build/views/{$view_name}/edit"),
'#prefix' => '<div class="hierarchical-select-config-back-link">',
'#suffix' => '</div>',
'#weight' => -5,
);
$form['save'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
// Add the the submit handler for the Hierarchical Select config form.
$parents = array(
'hierarchical_select_config',
);
$form['#submit']['hierarchical_select_common_config_form_submit'] = array(
$parents,
);
$form['#submit']['hs_taxonomy_views_common_config_form_submit'] = array(
$view_name,
$vid,
);
return $form;
}
/**
* Additional submit callback to redirect the user to the "Edit view" form.
*
* @param $form_id
* @param $form_values
* @param $view_name
* Name of a view. Provides necessary context.
* @param $vid
* A vocabulary id. Provides necessary context.
*/
function hs_taxonomy_views_common_config_form_submit($form_id, $form_values, $view_name, $vid) {
$view_id = db_result(db_query("SELECT vid FROM {view_view} WHERE name = '%s'", $view_name));
$field = 'term_node_' . $vid . '.tid';
$filter = db_fetch_object(db_query("SELECT operator FROM {view_filter} WHERE vid = %d AND field = '%s'", $view_id, $field));
$exposed_filter = db_fetch_object(db_query("SELECT operator, single FROM {view_exposed_filter} WHERE vid = %d AND field = '%s'", $view_id, $field));
// Overrides when save_lineage is enabled.
if ($form_values['hierarchical_select_config']['save_lineage']) {
// "Operator" must always be 'AND'.
$filter->operator = 'AND';
// The exposed filter must be locked to 'AND'.
$exposed_filter->operator = 1;
// "Force single" must be disabled.
$exposed_filter->single = 0;
}
else {
// "Force single" must be enabled.
$exposed_filter->single = 1;
}
// Overrides when the dropbox is enabled.
if ($form_values['hierarchical_select_config']['dropbox']['status']) {
// "Force single" must be disabled.
$exposed_filter->single = 0;
}
if ($view_id === FALSE) {
drupal_set_message(t("Could not update the view because it doesn't live in the database."), 'error');
}
else {
db_query("UPDATE {view_filter} SET operator = '%s' WHERE vid = %d AND field = '%s'", $filter->operator, $view_id, $field);
db_query("UPDATE {view_exposed_filter} SET operator = %d, single = %d WHERE vid = %d AND field = '%s'", $exposed_filter->operator, $exposed_filter->single, $view_id, $field);
cache_clear_all('views_urls', 'cache_views');
drupal_set_message(t("Updated the View's exposed filter according to the settings you made."));
}
}
//----------------------------------------------------------------------------
// Hierarchical Select hooks.
/**
* Implementation of hook_hierarchical_select_params().
*/
function hs_taxonomy_views_hierarchical_select_params() {
return array(
'optional',
) + hs_taxonomy_hierarchical_select_params();
}
/**
* Implementation of hook_hierarchical_select_root_level().
*/
function hs_taxonomy_views_hierarchical_select_root_level($params) {
$root_level = $params['optional'] ? array(
'**ALL**' => '<' . t('all') . '>',
) : array();
$root_level += hs_taxonomy_hierarchical_select_root_level($params);
return $root_level;
}
/**
* Implementation of hook_hierarchical_select_children().
*/
function hs_taxonomy_views_hierarchical_select_children($parent, $params) {
return $parent == '**ALL**' ? array() : hs_taxonomy_hierarchical_select_children($parent, $params);
}
/**
* Implementation of hook_hierarchical_select_lineage().
*/
function hs_taxonomy_views_hierarchical_select_lineage($item, $params) {
return $item == '**ALL**' ? array(
$item,
) : hs_taxonomy_hierarchical_select_lineage($item, $params);
}
/**
* Implementation of hook_hierarchical_select_valid_item().
*/
function hs_taxonomy_views_hierarchical_select_valid_item($item, $params) {
return $item == '**ALL**' || hs_taxonomy_hierarchical_select_valid_item($item, $params);
}
/**
* Implementation of hook_hierarchical_select_item_get_label().
*/
function hs_taxonomy_views_hierarchical_select_item_get_label($item, $params) {
return $item == '**ALL**' ? '<' . t('all') . '>' : hs_taxonomy_hierarchical_select_item_get_label($item, $params);
}
/**
* Implementation of hook_hierarchical_select_create_item().
*/
// No implementation. This doesn't make sense for exposed filters: if you were
// able to create new items in the hierarchy, how could you then possibly find
// anything for that item?
/**
* Implementation of hook_hierarchical_select_entity_count().
*/
function hs_taxonomy_views_hierarchical_select_entity_count($item, $params) {
if ($item == '**ALL**') {
return db_result(db_query('SELECT COUNT(DISTINCT(t.nid)) FROM {term_node} t INNER JOIN {node} n ON t.nid = n.nid WHERE n.status = 1'));
}
else {
return hs_taxonomy_hierarchical_select_entity_count($item, $params);
}
}
/**
* Implementation of hook_hierarchical_select_implementation_info().
*/
function hs_taxonomy_views_hierarchical_select_implementation_info() {
return array(
'hierarchy type' => t('Taxonomy'),
'entity type' => t('Node'),
);
}
/**
* Implementation of hook_hierarchical_select_config_info().
*/
function hs_taxonomy_views_hierarchical_select_config_info() {
static $config_info;
if (!isset($config_info)) {
$config_info = array();
views_load_cache();
$result = db_query("SELECT vid, name FROM {view_view} ORDER BY name");
while ($view = db_fetch_object($result)) {
$view = views_get_view($view->name);
foreach ($view->exposed_filter as $filter_id => $filter) {
$vid = _hs_taxonomy_views_parse_vocabulary_id_from_id($filter['id']);
if ($vid) {
$vocabulary = taxonomy_get_vocabulary($vid);
$config_id = "taxonomy-views-{$view->name}-{$vid}";
$config_info[$config_id] = array(
'config_id' => $config_id,
'hierarchy type' => t('Taxonomy'),
'hierarchy' => t($vocabulary->name),
'entity type' => t('Node'),
'entity' => '',
'context type' => t('Views exposed filter'),
'context' => t($view->name),
'edit link' => "admin/build/views/{$view->name}/hs_config/{$vid}",
);
}
}
}
}
return $config_info;
}
/**
* Given an id of the form "term_node_1.tid", with 1 the vid, get the vid.
*
* @return
* When no valid id was given, FALSE, otherwise the vid.
*/
function _hs_taxonomy_views_parse_vocabulary_id_from_id($id) {
$vid = FALSE;
if (preg_match("/term_node_(\\d+)\\.tid/", $id, $matches)) {
$vid = $matches[1];
}
return $vid;
}
Functions
Name | Description |
---|---|
hs_taxonomy_views_common_config_form_submit | Additional submit callback to redirect the user to the "Edit view" form. |
hs_taxonomy_views_config_form | Form definition; configuration form for Hierarchical Select as the widget for a Taxonomy exposed filter. |
hs_taxonomy_views_form_alter | Implementation of hook_form_alter(). |
hs_taxonomy_views_hierarchical_select_children | Implementation of hook_hierarchical_select_children(). |
hs_taxonomy_views_hierarchical_select_config_info | Implementation of hook_hierarchical_select_config_info(). |
hs_taxonomy_views_hierarchical_select_entity_count | Implementation of hook_hierarchical_select_entity_count(). |
hs_taxonomy_views_hierarchical_select_implementation_info | Implementation of hook_hierarchical_select_implementation_info(). |
hs_taxonomy_views_hierarchical_select_item_get_label | Implementation of hook_hierarchical_select_item_get_label(). |
hs_taxonomy_views_hierarchical_select_lineage | Implementation of hook_hierarchical_select_lineage(). |
hs_taxonomy_views_hierarchical_select_params | Implementation of hook_hierarchical_select_params(). |
hs_taxonomy_views_hierarchical_select_root_level | Implementation of hook_hierarchical_select_root_level(). |
hs_taxonomy_views_hierarchical_select_valid_item | Implementation of hook_hierarchical_select_valid_item(). |
hs_taxonomy_views_menu | Implementation of hook_menu(). |
hs_taxonomy_views_requirements | Implementation of hook_requirements(). |
_hs_taxonomy_views_parse_vocabulary_id_from_id | Given an id of the form "term_node_1.tid", with 1 the vid, get the vid. |