diff --git a/UPGRADE.txt b/UPGRADE.txt index f3473ee..53643c5 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -1,4 +1,7 @@ +<<<<<<< HEAD # Upgrading (from Drupal 6 to 7) +======= +>>>>>>> aa51d12a286aa871808e3994c025e896d747a2b5  1. **BE WARE THAT NOT ALL FUNCTIONALITY HAS BEEN PORTED!**  diff --git a/hierarchical_select.js b/hierarchical_select.js index 059fcc8..3034f87 100644 --- a/hierarchical_select.js +++ b/hierarchical_select.js @@ -450,9 +450,22 @@ Drupal.HierarchicalSelect.triggerEvents = function(hsid, updateType, settings) { Drupal.HierarchicalSelect.update = function(hsid, updateType, settings) { var post = $('form:has(#hierarchical-select-' + hsid +'-wrapper)', Drupal.HierarchicalSelect.context).formToArray();  + if(Drupal.settings.exposed_form_info) { + $.each(Drupal.settings.exposed_form_info, function (key, val) { + var keyExists = false; + $.each(post, function (keyPost, valPost) { + if(valPost.name == val) { + keyExists = true; + } + }); + if(keyExists == false) { + post.push({'name' : key, 'value' : val}); + } + }); + } + // Pass the hierarchical_select id via POST. post.push({ name : 'hsid', value : hsid }); -  // If a cache system is installed, let the server know if it's running // properly. If it is running properly, the server will send back additional // information to maintain a lazily-loaded cache. diff --git a/hierarchical_select.module b/hierarchical_select.module index 731267d..146a5c4 100644 --- a/hierarchical_select.module +++ b/hierarchical_select.module @@ -333,6 +333,10 @@ function hierarchical_select_ajax($form, $form_state) { 'output' => $output,  // 'cache' => $cache, ); + $commands[] = array( + 'command' => 'viewUpdate', + 'output' => $output, + ); $new_settings = _hs_new_setting_ajax(FALSE); foreach ($new_settings as $new_setting) { $commands[] = array( @@ -376,6 +380,7 @@ function _hs_process_shortcut_special_items($config) { function _hs_process_attach_css_js($element, $hsid, &$form_state, $complete_form) { // Set up Javascript and add settings specifically for the current // hierarchical select. + $element['#attached']['library'][] = array('system', 'ui'); $element['#attached']['library'][] = array('system', 'drupal.ajax'); $element['#attached']['library'][] = array('system', 'jquery.form'); $element['#attached']['library'][] = array('system', 'effects.core');  @@ -402,7 +407,7 @@ function _hs_process_attach_css_js($element, $hsid, &$form_state, $complete_form 'HierarchicalSelect' => array( 'settings' => array( "hs-$hsid" => array( - 'animationDelay' => ($config['animation_delay'] == 0) ? (int) variable_get('hierarchical_select_animation_delay', 400) : $config['animation_delay'], + 'animationDelay' => ($config['animation_delay'] == 0) ? (int) variable_get('hierarchical_select_animation_delay', 0) : $config['animation_delay'], 'cacheId' => $config['module'] . '_' . md5(serialize($config['params'])), 'renderFlatSelect' => (isset($config['render_flat_select'])) ? (int) $config['render_flat_select'] : 0, 'createNewItems' => (isset($config['editability']['status'])) ? (int) $config['editability']['status'] : 0, @@ -690,9 +695,6 @@ function _hs_process_render_nojs($element, $config) { * Hierarchical select form element type #process callback. */ function form_hierarchical_select_process($element, &$form_state, $complete_form) {  - // dpm('#process'); - // dpm($form_state); - // // Calculations. //  @@ -920,7 +922,6 @@ function _hierarchical_select_process_get_hs_selection($element) { $hs_selection = ($hs_selection != -1) ? array(end($hs_selection)) : array(); } } - return $hs_selection; }  @@ -1094,6 +1095,16 @@ function _hierarchical_select_process_calculate_selections(&$element, $hsid, $fo // - $op == t('Cancel') (used when creating a new item or a new level) // - any other submit button, e.g. the "Preview" button $hs_selection = _hierarchical_select_process_get_hs_selection($element); + // hack to get hs_views running + if(array_key_exists($element['#name'], $form_state['values'])) { + $values = $form_state['values'][$element['#name']]; + if( is_array($values) ) { + $hs_selection[] = $form_state['values'][$element['#name']]['hierarchical_select']['selects']; + } else { + $hs_selection[] = check_plain($form_state['values'][$element['#name']]); + } + } + if ($dropbox) { $db_selection = _hierarchical_select_process_get_db_selection($element, $hsid, $form_state); } @@ -1780,7 +1791,7 @@ function _hierarchical_select_hierarchy_generate($config, $selection, $required,  // Level label: set an empty level label if they've been disabled. $hierarchy->lineage[$depth] = 'label_' . $depth; - $label = ($config['level_labels']['status']) ? t($config['level_labels']['labels'][$depth]) : ''; + $label = ($config['level_labels']['status'] && array_key_exists($depth, $config['level_labels']['labels'])) ? t($config['level_labels']['labels'][$depth]) : ''; $hierarchy->levels[$depth] = array('label_' . $depth => $label) + $hierarchy->levels[$depth] + $children;  $hierarchy->levels[$depth] = _hierarchical_select_apply_entity_settings($hierarchy->levels[$depth], $config); diff --git a/includes/views.js b/includes/views.js index d5b5e3e..31ca72f 100644 --- a/includes/views.js +++ b/includes/views.js @@ -11,19 +11,43 @@ * of course only work when JavaScript is enabled! */  - -if (Drupal.jsEnabled) { - $(document).ready(function(){ - $('.view-filters form').submit(function() { - // Remove the Hierarchical Select form build id and the form id, to - // prevent them from ending up in the GET URL. - $('#edit-hs-form-build-id').remove(); - - // Prepare the hierarchical select form elements that are used as - // exposed filters for a GET submit. +(function($){ + Drupal.behaviors.HierarchicalSelectTaxonomyViews = { + attach: function ( context, settings ) { + $('.view-filters form').bind('submit', function() { $('.view-filters form') .find('.hierarchical-select-wrapper') .trigger('prepare-GET-submit'); }); - }); } + }; + Drupal.behaviors.HierarchicalSelectTaxonomyViews.getViewData = function (form, options, target) { + + var currLink = "views/ajax?"; + var url = Drupal.settings.basePath + currLink + "view_name=" + options.view_name + "&view_display_id=" + options.view_display_id + "&js=1&" + $(form).serialize(); + $.ajax({ + url: url, + type: "GET", + success: function(response) { + $(target).replaceWith(response[1].data); + }, + error: function() { + var message = Drupal.t("An error occurred at @path.", {"@path": ajax_path}); + alert(message); + }, + dataType: "json" + }); + }; + Drupal.behaviors.HierarchicalSelectTaxonomyViews.refreshView = function () { + + + var target = ".view-id-testing_term"; + var form = $("#views-exposed-form-testing-term-page-1"); + Drupal.behaviors.HierarchicalSelectTaxonomyViews.getViewData(form, { + js : 0, + view_name : "testing", + view_display_id : "page_1" + }, target); + }; + +})(jQuery); diff --git a/modules/hs_taxonomy.module b/modules/hs_taxonomy.module index 2fc3fb4..6b83c2d 100644 --- a/modules/hs_taxonomy.module +++ b/modules/hs_taxonomy.module @@ -566,7 +566,7 @@ function hs_taxonomy_hierarchical_select_params() { * Implementation of hook_hierarchical_select_root_level(). */ function hs_taxonomy_hierarchical_select_root_level($params) { - // TODO: support multiple parents, i.e. support "save lineage". + // TODO: support multiple parents, i.e. support "save lineage".# $vocabulary = taxonomy_vocabulary_load($params['vid']); $terms = _hs_taxonomy_hierarchical_select_get_tree($params['vid'], 0, -1, 1);  @@ -624,7 +624,6 @@ function hs_taxonomy_hierarchical_select_children($parent, $params) { } } } - return _hs_taxonomy_hierarchical_select_terms_to_options($terms); }  @@ -708,7 +707,7 @@ function hs_taxonomy_hierarchical_select_item_get_label($item, $params) { }  // Use the translated term when available! - if (module_exists('i18ntaxonomy') && i18ntaxonomy_vocabulary($term->vid) == I18N_TAXONOMY_LOCALIZE) { + if ( $term->tid !== 0 && module_exists('i18n_taxonomy') && i18n_taxonomy_vocabulary_mode($term->vid) == I18N_MODE_TRANSLATE) { $labels[$item] = i18n_taxonomy_term_name($term); } else { @@ -998,6 +997,9 @@ function theme_hs_taxonomy_formatter_lineage($variables) { function _hs_taxonomy_hierarchical_select_get_tree($vid, $parent = 0, $depth = -1, $max_depth = NULL, $reset = FALSE) { static $children, $parents, $terms;  + if(!isset($vid) && empty($vid)) { + throw new Exception('vid should not be empty'); + } if ($reset) { $children = $parents = $terms = array(); } @@ -1008,9 +1010,22 @@ function _hs_taxonomy_hierarchical_select_get_tree($vid, $parent = 0, $depth = - // and its children, too. if (!isset($children[$vid])) { $children[$vid] = array(); - // TODO Please convert this statement to the D7 database API syntax. - $result = db_query('SELECT t.tid, t.*, parent FROM {taxonomy_term_data} t INNER JOIN {taxonomy_term_hierarchy} h ON t.tid = h.tid WHERE t.vid = :vid ORDER BY weight, name', array(':vid' => $vid)); + $query = db_select('taxonomy_term_data','ttd'); + $query->join('taxonomy_term_hierarchy', 'tth', 'ttd.tid = tth.tid'); + $query->fields('ttd') + ->fields('tth') + ->condition('ttd.vid', $vid); + global $language; + $vocabulary = taxonomy_vocabulary_load($vid); + if(module_exists('i18n_taxonomy') && !empty($language->language) && $vocabulary->i18n_mode === I18N_MODE_TRANSLATE ) { + $query->condition('ttd.language', $language->language); + } + $query->orderBy('weight', 'ASC') + ->orderBy('name', 'ASC'); + $result = $query + ->execute() + ->fetchAllAssoc('tid'); foreach ($result as $term) { $children[$vid][$term->parent][] = $term->tid; $parents[$vid][$term->tid][] = $term->parent; @@ -1096,6 +1111,9 @@ function _hs_taxonomy_hierarchical_select_terms_to_options($terms) { */ function _hs_taxonomy_hierarchical_select_get_depth($vid) { $depth = -99999; + if(!isset($vid) && empty($vid)) { + throw new Exception('vid should not be empty'); + } $tree = _hs_taxonomy_hierarchical_select_get_tree($vid); foreach ($tree as $term) { if ($term->depth > $depth) { diff --git a/modules/hs_taxonomy_views.info b/modules/hs_taxonomy_views.info index a17c657..22846b7 100644 --- a/modules/hs_taxonomy_views.info +++ b/modules/hs_taxonomy_views.info @@ -4,6 +4,6 @@ dependencies[] = hierarchical_select dependencies[] = hs_taxonomy  dependencies[] = views package = Form Elements -core = 6.x +core = 7.x  files[] = hs_taxonomy_views_handler_filter_term_node_tid.inc diff --git a/modules/hs_taxonomy_views.module b/modules/hs_taxonomy_views.module index 84e6680..0b51ca3 100644 --- a/modules/hs_taxonomy_views.module +++ b/modules/hs_taxonomy_views.module @@ -44,7 +44,7 @@ function hs_taxonomy_views_menu() { /** * Implementation of hook_form_alter(). */ -function hs_taxonomy_views_form_alter(&$form, $form_state, $form_id) { +function hs_taxonomy_views_form_alter(&$form, &$form_state, $form_id) { // if ($form_id == 'views_ui_edit_view_form') { // Add JS and CSS required for Hierarchical Select to work. @@ -82,6 +82,49 @@ function hs_taxonomy_views_form_alter(&$form, $form_state, $form_id) { $form['options']['expose']['operator']['#description'] = $description; } } + + if( $form_id == 'views_exposed_form' ) { + // Since the exposed form is a GET form, we don't want it to send a wide + // variety of information. + $form['form_build_id']['#access'] = FALSE; + $form['form_token']['#access'] = FALSE; + $form['form_id']['#access'] = FALSE; + + // In order for Ajax to work, we need the form build info. Here we check if + // #ajax has been added to any form elements, and if so, pass this info as + // settings via Javascript, which get attached to the submitted form on Ajax + // form submissions. + foreach (element_children($form) as $key) { + if (array_key_exists('#ajax', $form[$key])) { + $form['#attached']['js'][] = array( + 'type' => 'setting', + 'data' => array( + 'exposed_form_info' => array( + 'form_id' => $form['#form_id'], + 'form_build_id' => $form['#build_id'], + // 'form_token' => $form['#token'], + ), + ), + ); + $form['#attached']['js'][] = array( + 'type' => 'inline', + 'weight' => 100, + 'data' => '(function ($) { + Drupal.behaviors.ViewsExposedFormAjax = { + attach: function(context, settings) { + for (ajax_object in Drupal.ajax) { + if (Drupal.ajax[ajax_object].options) { + jQuery.extend(Drupal.ajax[ajax_object].options.data, Drupal.settings.exposed_form_info); + } + } + } + }; + })(jQuery);', + ); + break; + } + } + } }  //---------------------------------------------------------------------------- @@ -160,32 +203,14 @@ function hs_taxonomy_views_json($view_name, $display_id) { /** * Implementation of hook_views_api(). */ -function hs_taxonomy_views_api() { +function hs_taxonomy_views_views_api() { return array( - 'api' => 2, + 'api' => 3, 'path' => drupal_get_path('module', 'hierarchical_select') . '/modules', ); }  /** - * Implementation of hook_views_handlers(). - */ -function hs_taxonomy_views_handlers() { - return array( - 'handlers' => array( - // Provide a subclass of the term filter handler, to make it possible to - // use Hierarchical Select in Views. - 'hs_taxonomy_views_handler_filter_term_node_tid' => array( - 'parent' => 'views_handler_filter_term_node_tid', - ), - 'hs_taxonomy_views_handler_filter_term_node_tid_depth' => array( - 'parent' => 'hs_taxonomy_views_handler_filter_term_node_tid', - ), - ) - ); -} - -/** * Implementation of hook_views_data_alter(). */ function hs_taxonomy_views_views_data_alter(&$data) { @@ -214,6 +239,9 @@ function hs_taxonomy_views_views_data_alter(&$data) { ), );  +// $data['taxonomy_term_data']['tid']['filter']['handler'] = 'hs_taxonomy_views_handler_filter_term_node_tid'; + // $data['taxonomy_term_data']['tid']['filter']['handler'] = 'foobar_handler'; + // Node view type, tid field. $data['taxonomy_term_node']['tid'] = array( 'title' => t('Term ID'), @@ -278,6 +306,7 @@ function hs_taxonomy_views_config_form($form, $form_state, $view, $display_id, $ require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'hierarchical_select') . '/includes/common.inc';  $filter = _hs_taxonomy_views_get_filter($view, $display_id, $filter_id); + $vocabulary = taxonomy_vocabulary_machine_name_load($filter['vocabulary']);  // Build the config ID. $config_id = "taxonomy-views-$view->name-$display_id-$filter_id"; @@ -285,19 +314,18 @@ function hs_taxonomy_views_config_form($form, $form_state, $view, $display_id, $ // Add the Hierarchical Select config form. $module = 'hs_taxonomy_views'; $params = array( - 'optional' => (bool) $filter['expose']['optional'], + 'optional' => !((bool) $filter['expose']['required']), 'filter_id' => $filter_id, - 'vid' => $filter['vid'], + 'vid' => $vocabulary->vid, 'exclude_tid' => NULL, 'root_term' => NULL, ); - $vocabulary = taxonomy_vocabulary_load($params['vid']); $defaults = array( // Enable the save_lineage setting by default if the multiple parents // vocabulary option is enabled. 'save_lineage' => (int) ($vocabulary->hierarchy == 2), 'editability' => array( - 'max_levels' => _hs_taxonomy_hierarchical_select_get_depth($filter['vid']), + 'max_levels' => _hs_taxonomy_hierarchical_select_get_depth($vocabulary->vid), ), // Use our custom callback. 'path' => "hs_taxonomy_views_json/$view->name/$display_id", @@ -317,11 +345,11 @@ function hs_taxonomy_views_config_form($form, $form_state, $view, $display_id, $ 'entities' => t('nodes'), ); $max_hierarchy_depth = _hs_taxonomy_hierarchical_select_get_depth($vocabulary->vid); - $preview_is_required = !(bool) $filter['expose']['optional']; + $preview_is_required = (bool) $filter['expose']['required']; $form['hierarchical_select_config'] = hierarchical_select_common_config_form($module, $params, $config_id, $defaults, $strings, $max_hierarchy_depth, $preview_is_required);  $form['link'] = array( - '#markup' => l("Back to the View's display configuration", "admin/structure/views/edit/$view->name", array('fragment' => 'views-tab-' . $display_id)), + '#markup' => l("Back to the View's display configuration", "admin/structure/views/view/$view->name/edit", array('fragment' => 'views-tab-' . $display_id)), '#prefix' => '', '#weight' => -5, @@ -398,7 +426,7 @@ function hs_taxonomy_views_hierarchical_select_params() { */ function hs_taxonomy_views_hierarchical_select_root_level($params) { $any_label = variable_get('views_exposed_filter_any_label', 'old_any') === 'old_any' ? '<' . t('Any') . '>' : '- ' . t('Any') . ' -'; - $root_level = ($params['optional']) ? array(HS_TAXONOMY_VIEWS_ANY_OPTION => $any_label) : array(); + $root_level = (!$params['required']) ? array(HS_TAXONOMY_VIEWS_ANY_OPTION => $any_label) : array(); $root_level += hs_taxonomy_hierarchical_select_root_level($params); return $root_level; } @@ -444,7 +472,7 @@ function hs_taxonomy_views_hierarchical_select_item_get_label($item, $params) { function hs_taxonomy_views_hierarchical_select_entity_count($item, $params) { static $count;  - $current_view = views_get_current_view(); +/* $current_view = views_get_current_view();  if (!isset($count[$current_view->name][$item])) { $temp_view = $current_view->clone_view(); @@ -467,6 +495,7 @@ function hs_taxonomy_views_hierarchical_select_entity_count($item, $params) { if ($item != HS_TAXONOMY_VIEWS_ANY_OPTION) { // Get an array with all tids: the tid of the currently selected term and // all child terms. +// print_r($item); $term = taxonomy_term_load($item); $tree = _hs_taxonomy_hierarchical_select_get_tree($term->vid, $term->tid); $tids = array($term->tid => $term->tid); @@ -475,7 +504,7 @@ function hs_taxonomy_views_hierarchical_select_entity_count($item, $params) { }  $id = 'tid_' . implode('-', $tids); - $temp_view->display[$display_id]->handler->override_option('filters', array( +/* $temp_view->display[$display_id]->handler->override_option('filters', array( $id => array( 'operator' => 'or', 'value' => $tids, @@ -503,59 +532,61 @@ function hs_taxonomy_views_hierarchical_select_entity_count($item, $params) { else { // Disable the default value, otherwise the option will actually // filter by the default value. - $filter_id = $params['filter_id']; - $temp_view->display[$display_id]->display_options['filters'][$filter_id]['value'] = array(); - $temp_view->display[$display_id]->handler->options['filters'][$filter_id]['value'] = array(); - $temp_view->display['default']->display_options['filters'][$filter_id]['value'] = array(); - $temp_view->display['default']->handler->options['filters'][$filter_id]['value'] = array(); - } - + // $filter_id = $params['filter_id']; + // $temp_view->display[$display_id]->display_options['filters'][$filter_id]['value'] = array(); + // $temp_view->display[$display_id]->handler->options['filters'][$filter_id]['value'] = array(); + // $temp_view->display['default']->display_options['filters'][$filter_id]['value'] = array(); + // $temp_view->display['default']->handler->options['filters'][$filter_id]['value'] = array(); + // } + +//print_r($display_id); // Build the queries and collect the arguments. - $temp_view->build($display_id); + // $temp_view->build($display_id);  // We only need the count query. We don't care about the actual fields or // order of the View. - $count_query = !empty($temp_view->build_info['count_query']) ? $temp_view->build_info['count_query'] : $temp_view->query->count_query; - $args = !empty($temp_view->build_info['query_args']) ? $temp_view->build_info['query_args'] : $temp_view->query->query_args; + // $count_query = !empty($temp_view->build_info['count_query']) ? $temp_view->build_info['count_query'] : $temp_view->query->count_query; + // $args = !empty($temp_view->build_info['query_args']) ? $temp_view->build_info['query_args'] : $temp_view->query->query_args;  // Regenerate the query after we set the distinct flag for the nid field. // This unfortunately doesn't work, because Views doesn't create an // optimized count query when any of the fields have the distinct flag set. //$temp_view->query->fields['nid']['distinct'] = TRUE; - //$count_query = $temp_view->query->query(TRUE); + $count_query = $temp_view->query->query(TRUE);  // Due to the above: sneak DISTINCT() in through a string replace ... - $count_query = str_replace("SELECT node.nid AS nid", "SELECT DISTINCT(node.nid) AS nid", $count_query); + // $count_query = str_replace("SELECT node.nid AS nid", "SELECT DISTINCT(node.nid) AS nid", $count_query);  // Filter by node type if such a filter is configured in the view. - if (isset($current_view->filter['type'])) { - $node_types = $current_view->filter['type']->value; - if (isset($node_types)) { - $values = ''; - foreach ($node_types as $key => $value) { - if (empty($values)) { - $values = '\'' . $value . '\''; - } - else { - $values .= ', \'' . $value . '\''; - } - } - - // Use the same sneaky string replace trick once more. - $count_query = str_replace("WHERE", 'WHERE node.type IN (' . $values . ') AND', $count_query); - } - } + // if (isset($current_view->filter['type'])) { + // $node_types = $current_view->filter['type']->value; + // if (isset($node_types)) { + // $values = ''; + // foreach ($node_types as $key => $value) { + // if (empty($values)) { + // $values = '\'' . $value . '\''; + // } + // else { + // $values .= ', \'' . $value . '\''; + // } + // } + + // // Use the same sneaky string replace trick once more. + // $count_query = str_replace("WHERE", 'WHERE node.type IN (' . $values . ') AND', $count_query); + // } + // }  // Apply the same query transformations as view::execute() does. - $count_query = db_rewrite_sql($count_query, $temp_view->base_table, $temp_view->base_field, array('view' => &$temp_view)); - $count_query = 'SELECT COUNT(*) FROM (' . $count_query . ') count_alias'; + // $count_query = db_rewrite_sql($count_query, $temp_view->base_table, $temp_view->base_field, array('view' => &$temp_view)); + // $count_query = 'SELECT COUNT(*) FROM (' . $count_query . ') count_alias';  // Execute the count query. // TODO Please convert this statement to the D7 database API syntax. - $count[$current_view->name][$item] = db_query($count_query, $args)->fetchField(); + // $count[$current_view->name][$item] = db_query($count_query, $args)->fetchField(); } - - return $count[$current_view->name][$item]; +} */ + return 1; + // return $count[$current_view->name][$item]; }  /** diff --git a/modules/hs_taxonomy_views_handler_filter_term_node_tid.inc b/modules/hs_taxonomy_views_handler_filter_term_node_tid.inc index 1f1a4c6..ddd1047 100644 --- a/modules/hs_taxonomy_views_handler_filter_term_node_tid.inc +++ b/modules/hs_taxonomy_views_handler_filter_term_node_tid.inc @@ -8,9 +8,27 @@  class hs_taxonomy_views_handler_filter_term_node_tid extends views_handler_filter_term_node_tid {  - function init(&$view, $options) { + function init(&$view, &$options) { parent::init($view, $options); - + // @TODO Support non exposed filters + $vocabulary = taxonomy_vocabulary_machine_name_load($this->options['vocabulary']); + if( array_key_exists($options['expose']['identifier'], $_GET) ) { + $parent_term = $_GET[$options['expose']['identifier']]; + $term = taxonomy_term_load($parent_term); + $tids = array(); + if(!$parent_term) { + $tree = taxonomy_get_tree($vocabulary->vid); + } else { + $tree = _hs_taxonomy_hierarchical_select_get_tree($vocabulary->vid, $term->tid); + $tids = array($term->tid => $term->tid); + } + foreach ($tree as $descendant) { + $tids[$descendant->tid] = $descendant->tid; + } + $this->value[] = $tids; + } else { + $this->value = array(); + } // The following code should logically be wrapped in a // $this->select_type_is_hierarchical_select() // check. However, if we'd do this, you wouldn't be able to dynamically @@ -23,17 +41,37 @@ class hs_taxonomy_views_handler_filter_term_node_tid extends views_handler_filte // code below in such a check.  // Add JS and CSS required for Hierarchical Select to work. - _hierarchical_select_setup_js(); + // @TODO uncomment +// _hierarchical_select_setup_js();  // Ensure that Drupal.HierarchicalSelect.prepareGETSubmit() gets called. require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'hierarchical_select') . '/includes/common.inc'; - hierarchical_select_common_add_views_js(); + // @TODO uncomment +// hierarchical_select_common_add_views_js(); }  function value_form(&$form, &$form_state) { // Support limiting of vocabulary by the vocabulary's module name (this is // possible when a vocabulary is exported/defined as a feature, see // http://drupal.org/node/789556) or by the vocabulary's vid. +// if( array_key_exists($this->options['relationship'], $form_state['input']) ) { +// $parent_term = $form_state['input'][$this->options['relationship']]; +// $term = taxonomy_term_load($parent_term); +// $vocabulary = taxonomy_vocabulary_machine_name_load($this->options['vocabulary']); +// $tids = array(); +// if(!$parent_term) { +// $tree = taxonomy_get_tree($vocabulary->vid); +// } else { +// $tree = _hs_taxonomy_hierarchical_select_get_tree($vocabulary->vid, $term->tid); +// $tids = array($term->tid => $term->tid); +// } +// foreach ($tree as $descendant) { +// $tids[$descendant->tid] = $descendant->tid; +// } +// $this->value[] = $tids; +// } else { +// $this->value = array(); +// } if (isset($this->options['limit_by']) && $this->options['limit_by'] == 'module') { foreach (taxonomy_get_vocabularies() as $vid => $vocab) { if ($vocab->module == $this->options['module']) { @@ -43,29 +81,27 @@ class hs_taxonomy_views_handler_filter_term_node_tid extends views_handler_filte } } else { - $vocabulary = taxonomy_vocabulary_load($this->options['vid']); + $vocabulary = taxonomy_vocabulary_machine_name_load($this->options['vocabulary']); }  $view_name = $this->view->name; $filter_id = $this->options['id']; $display_id = _hs_taxonomy_views_get_display_id_for_filter($this->view, $filter_id); - $optional = $this->options['expose']['optional']; + $required = $this->options['expose']['required'];  $config_id = "taxonomy-views-$view_name-$display_id-$filter_id";  - // When not exposed: settings form. - if (empty($form_state['exposed'])) { - // When the 'Selection type' is 'Hierarchical Select', user our own - // value_form, otherwise use the parent's class form. - if ($this->options['type'] == 'textfield' || $this->options['type'] == 'select') { + // When the 'Selection Type' isn't 'Hierachical Select' use + // parent's form. + if (!$this->select_type_is_hierarchical_select()) { parent::value_form($form, $form_state); - } - else { + } else { + if ( ! $this->is_exposed() ) { $config = hierarchical_select_common_config_get($config_id); $form['value'] = array( '#type' => 'hierarchical_select', '#title' => t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->name)), - '#default_value' => !empty($this->value) ? $this->value : array(), + '#default_value' => $this->value, '#config' => array( 'module' => 'hs_taxonomy', 'params' => array( @@ -95,27 +131,23 @@ class hs_taxonomy_views_handler_filter_term_node_tid extends views_handler_filte ), ); } - } // When exposed: filter form. else { - // When the 'Selection type' is 'Hierarchical Select', user our own - // value_form, otherwise use the parent's class form. - if (!$this->select_type_is_hierarchical_select()) { - parent::value_form($form, $form_state); - } - else { + drupal_add_js(drupal_get_path('module', 'hierarchical_select').'/includes/views.js'); $default_value = (isset($this->value) && !empty($this->value)) ? $this->value : array();  // Basic settings for the form item. $form['value']['#type'] = 'hierarchical_select'; $form['value']['#default_value'] = $default_value; - $form['value']['#required'] = !((bool) $optional); + $form['value']['#required'] = ((bool) $required); + + $form['value']['#ajax'] = NULL;  // Apply the Hierarchical Select configuration to the form item. $defaults_override = array( 'module' => 'hs_taxonomy_views', 'params' => array( - 'optional' => (bool) $optional, + 'required' => !((bool) $required), 'filter_id' => $filter_id, 'vid' => $vocabulary->vid, 'exclude_tid' => NULL, @@ -150,15 +182,11 @@ class hs_taxonomy_views_handler_filter_term_node_tid extends views_handler_filte function extra_options_form(&$form, &$form_state) { parent::extra_options_form($form, $form_state);  - $form['type'] = array( - '#type' => 'radios', - '#title' => t('Selection type'), - '#options' => array( - 'select' => t('Dropdown'), - 'textfield' => t('Autocomplete'), - 'hierarchical_select' => t('Hierarchical Select'), - ), - '#default_value' => $this->options['type'], + $form['type']['#options'] = array_merge( + $form['type']['#options'], + array( + 'hierarchical_select' => t('Hierarchical Select') + ) );  $filter_id = $form_state['id']; @@ -168,7 +196,7 @@ class hs_taxonomy_views_handler_filter_term_node_tid extends views_handler_filte '#markup' => l(t('Configure Hierarchical Select'), _hs_taxonomy_views_config_path($this->view->name, $display_id, $filter_id)), '#suffix' => '', // Doesn't work because #process is not called for #type = markup form items. - '#process' => array('views_process_dependency'), + '#process' => array('ctools_dependent_process'), '#dependency' => array('radio:options[type]' => array('hierarchical_select')), // Set #input = TRUE so that #process will be called. '#input' => TRUE, @@ -234,7 +262,7 @@ class hs_taxonomy_views_handler_filter_term_node_tid extends views_handler_filte }  function admin_summary() { - $this->value = (array) $this->value; + $this->value = NULL; return parent::admin_summary(); }  diff --git a/modules/hs_taxonomy_views_handler_filter_term_node_tid_depth.inc b/modules/hs_taxonomy_views_handler_filter_term_node_tid_depth.inc new file mode 100644 index 0000000..0bafd13 --- /dev/null +++ b/modules/hs_taxonomy_views_handler_filter_term_node_tid_depth.inc @@ -0,0 +1,90 @@ + t('Is one of'), + ); + } + + function option_definition() { + $options = parent::option_definition(); + + $options['depth'] = array('default' => 0); + + return $options; + } + + function extra_options_form(&$form, &$form_state) { + parent::extra_options_form($form, $form_state); + + $form['depth'] = array( + '#type' => 'weight', + '#title' => t('Depth'), + '#default_value' => $this->options['depth'], + '#description' => t('The depth will match nodes tagged with terms in the hierarchy. For example, if you have the term "fruit" and a child term "apple", with a depth of 1 (or higher) then filtering for the term "fruit" will get nodes that are tagged with "apple" as well as "fruit". If negative, the reverse is true; searching for "apple" will also pick up nodes tagged with "fruit" if depth is -1 (or lower).'), + ); + } + + function query() { + // If no filter values are present, then do nothing. + if (count($this->value) == 0) { + return; + } + else if (count($this->value) == 1) { + $placeholder = " = %d"; + } + else { + $placeholder = " IN (" . implode(', ', array_fill(0, sizeof($this->value), '%d')) . ")"; + } + + // The normal use of ensure_my_table() here breaks Views. + // So instead we trick the filter into using the alias of the base table. + // See http://drupal.org/node/271833 + // If a relationship is set, we must use the alias it provides. + if (!empty($this->relationship)) { + $this->table_alias = $this->relationship; + } + // If no relationship, then use the alias of the base table. + else if (isset($this->query->table_queue[$this->query->base_table]['alias'])) { + $this->table_alias = $this->query->table_queue[$this->query->base_table]['alias']; + } + // This should never happen, but if it does, we fail quietly. + else { + return; + } + + // Now build the subqueries. + $subquery = "\n SELECT tn.vid FROM {term_node} tn\n"; + $where = " WHERE tn.tid $placeholder\n"; + $args = $this->value; + $last = "tn"; + + if ($this->options['depth'] > 0) { + $subquery .= " LEFT JOIN {term_hierarchy} th ON th.tid = tn.tid\n"; + $last = "th"; + foreach (range(1, abs($this->options['depth'])) as $count) { + $subquery .= " LEFT JOIN {term_hierarchy} th$count ON $last.parent = th$count.tid\n"; + $where .= " OR th$count.tid $placeholder\n"; + $args = array_merge($args, $this->value); + $last = "th$count"; + } + } + else if ($this->options['depth'] < 0) { + foreach (range(1, abs($this->options['depth'])) as $count) { + $subquery .= " LEFT JOIN {term_hierarchy} th$count ON $last.tid = th$count.parent\n"; + $where .= " OR th$count.tid $placeholder\n"; + $args = array_merge($args, $this->value); + $last = "th$count"; + } + } + + $this->query->add_where(0, "$this->table_alias.$this->real_field IN ($subquery$where )", $args); + } +}