diff --git a/sites/all/modules/contrib/views/views/handlers/views_handler_area_view.inc b/sites/all/modules/contrib/views/views/handlers/views_handler_area_view.inc index 45ea4999..3b72bf6b 100644 --- a/sites/all/modules/contrib/views/views/handlers/views_handler_area_view.inc +++ b/sites/all/modules/contrib/views/views/handlers/views_handler_area_view.inc @@ -51,33 +51,48 @@ class views_handler_area_view extends views_handler_area { * Render the area */ function render($empty = FALSE) { - if (!empty($this->options['view_to_insert'])) { - list($view_name, $display_id) = explode(':', $this->options['view_to_insert']); - - $view = views_get_view($view_name); - if (empty($view) || !$view->access($display_id)) { - return; - } - $view->set_display($display_id); - - // Avoid recursion - $view->parent_views += $this->view->parent_views; - $view->parent_views[] = "$view_name:$display_id"; - - // Check if the view is part of the parent views of this view - $search = "$view_name:$display_id"; - if (in_array($search, $this->view->parent_views)) { - drupal_set_message(t("Recursion detected in view @view display @display.", array('@view' => $view_name, '@display' => $display_id)), 'error'); + if ($view = $this->loadView()) { + if (!empty($this->options['inherit_arguments']) && !empty($this->view->args)) { + return $view->preview(NULL, $this->view->args); } else { - if (!empty($this->options['inherit_arguments']) && !empty($this->view->args)) { - return $view->preview($display_id, $this->view->args); - } - else { - return $view->preview($display_id); - } + return $view->preview(NULL); } } return ''; } + + /** + * Loads the used view for rendering. + * + * @return \view|NULL + * The loaded view or NULL, in case the view was not loadable / recursion + * got detected / access got denied. + */ + protected function loadView() { + if (empty($this->options['view_to_insert'])) { + return NULL; + } + list($view_name, $display_id) = explode(':', $this->options['view_to_insert']); + + $view = views_get_view($view_name); + if (empty($view) || !$view->access($display_id)) { + return NULL; + } + $view->set_display($display_id); + + // Avoid recursion. + $view->parent_views += $this->view->parent_views; + $view->parent_views[] = "$view_name:$display_id"; + + // Check if the view is part of the parent views of this view. + $search = "$view_name:$display_id"; + if (in_array($search, $this->view->parent_views)) { + drupal_set_message(t("Recursion detected in view @view display @display.", array('@view' => $view_name, '@display' => $display_id)), 'error'); + return NULL; + } + + return $view; + } + } diff --git a/sites/all/modules/contrib/views/views/handlers/views_handler_argument.inc b/sites/all/modules/contrib/views/views/handlers/views_handler_argument.inc index 5a5ec004..86c4a0df 100644 --- a/sites/all/modules/contrib/views/views/handlers/views_handler_argument.inc +++ b/sites/all/modules/contrib/views/views/handlers/views_handler_argument.inc @@ -419,7 +419,7 @@ class views_handler_argument extends views_handler { // Let the plugins do validation. $default_id = $form_state['values']['options']['default_argument_type']; $plugin = $this->get_plugin('argument default', $default_id); - if ($plugin) { + if ($plugin && isset($form['argument_default'][$default_id]) && isset($form_state['values']['options']['argument_default'][$default_id])) { $plugin->options_validate($form['argument_default'][$default_id], $form_state, $form_state['values']['options']['argument_default'][$default_id]); } @@ -1075,9 +1075,6 @@ class views_handler_argument extends views_handler { $argument = clone $this; if (!isset($arg) && $argument->has_default_argument()) { $arg = $argument->get_default_argument(); - - // remember that this argument was computed, not passed on the URL. - $this->is_default = TRUE; } // Set the argument, which will also validate that the argument can be set. if ($argument->set_argument($arg)) { diff --git a/sites/all/modules/contrib/views/views/handlers/views_handler_field.inc b/sites/all/modules/contrib/views/views/handlers/views_handler_field.inc index c04fd460..65210d9f 100644 --- a/sites/all/modules/contrib/views/views/handlers/views_handler_field.inc +++ b/sites/all/modules/contrib/views/views/handlers/views_handler_field.inc @@ -372,7 +372,7 @@ class views_handler_field extends views_handler { * Optional name of the field where the value is stored. */ function get_value($values, $field = NULL) { - $alias = isset($field) && isset($this->aliases[$field]) ? $this->aliases[$field] : $this->field_alias; + $alias = isset($field) ? $this->aliases[$field] : $this->field_alias; if (isset($values->{$alias})) { return $values->{$alias}; } diff --git a/sites/all/modules/contrib/views/views/handlers/views_handler_field_contextual_links.inc b/sites/all/modules/contrib/views/views/handlers/views_handler_field_contextual_links.inc index faeeedc2..4386e059 100644 --- a/sites/all/modules/contrib/views/views/handlers/views_handler_field_contextual_links.inc +++ b/sites/all/modules/contrib/views/views/handlers/views_handler_field_contextual_links.inc @@ -10,35 +10,7 @@ * * @ingroup views_field_handlers */ -class views_handler_field_contextual_links extends views_handler_field { - function option_definition() { - $options = parent::option_definition(); - - $options['fields'] = array('default' => array()); - $options['destination'] = array('default' => TRUE, 'bool' => TRUE); - - return $options; - } - - function options_form(&$form, &$form_state) { - $all_fields = $this->view->display_handler->get_field_labels(); - // Offer to include only those fields that follow this one. - $field_options = array_slice($all_fields, 0, array_search($this->options['id'], array_keys($all_fields))); - $form['fields'] = array( - '#type' => 'checkboxes', - '#title' => t('Fields'), - '#description' => t('Fields to be included as contextual links.'), - '#options' => $field_options, - '#default_value' => $this->options['fields'], - ); - $form['destination'] = array( - '#type' => 'checkbox', - '#title' => t('Include destination'), - '#description' => t('Include a "destination" parameter in the link to return the user to the original view upon completing the contextual action.'), - '#default_value' => $this->options['destination'], - ); - } - +class views_handler_field_contextual_links extends views_handler_field_links { function pre_render(&$values) { // Add a row plugin css class for the contextual link. $class = 'contextual-links-region'; @@ -50,35 +22,18 @@ class views_handler_field_contextual_links extends views_handler_field { } } + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + $form['fields']['#description'] = t('Fields to be included as contextual links.'); + $form['destination']['#description'] = t('Include a "destination" parameter in the link to return the user to the original view upon completing the contextual action.'); + } + /** * Render the contextual fields. */ function render($values) { - $links = array(); - foreach ($this->options['fields'] as $field) { - if (empty($this->view->style_plugin->rendered_fields[$this->view->row_index][$field])) { - continue; - } - $title = $this->view->field[$field]->last_render_text; - $path = ''; - if (!empty($this->view->field[$field]->options['alter']['path'])) { - $path = $this->view->field[$field]->options['alter']['path']; - } - if (!empty($title) && !empty($path)) { - // Make sure that tokens are replaced for this paths as well. - $tokens = $this->get_render_tokens(array()); - $path = strip_tags(decode_entities(strtr($path, $tokens))); - - $links[$field] = array( - 'href' => $path, - 'title' => $title, - ); - if (!empty($this->options['destination'])) { - $links[$field]['query'] = drupal_get_destination(); - } - } - } - + $links = $this->get_links(); if (!empty($links)) { $build = array( '#prefix' => '', '#dependency' => array('edit-options-group-rows' => array(TRUE)), '#fieldset' => 'multiple_field_settings', @@ -716,6 +728,10 @@ class views_handler_field_field extends views_handler_field { } function get_value($values, $field = NULL) { + if (!isset($values->_field_data[$this->field_alias]['entity']) || !is_object($values->_field_data[$this->field_alias]['entity'])) { + return array(); + } + // Go ahead and render and store in $this->items. $entity = clone $values->_field_data[$this->field_alias]['entity']; @@ -757,6 +773,11 @@ class views_handler_field_field extends views_handler_field { return array(); } + // If requested, randomize the order of the deltas. + if ($this->options['delta_random'] && !empty($entity->{$this->definition['field_name']})) { + shuffle($entity->{$this->definition['field_name']}[$langcode]); + } + // We are supposed to show only certain deltas. if ($this->limit_values && !empty($entity->{$this->definition['field_name']})) { $all_values = !empty($entity->{$this->definition['field_name']}[$langcode]) ? $entity->{$this->definition['field_name']}[$langcode] : array(); diff --git a/sites/all/modules/contrib/views/views/modules/locale.views.inc b/sites/all/modules/contrib/views/views/modules/locale.views.inc index 3bff7dbd..fe6d0509 100644 --- a/sites/all/modules/contrib/views/views/modules/locale.views.inc +++ b/sites/all/modules/contrib/views/views/modules/locale.views.inc @@ -218,4 +218,11 @@ function locale_views_data_alter(&$data) { 'handler' => 'views_handler_sort', ), ); + $data['node']['specific_language'] = array( + 'title' => t('Specific language'), + 'help' => t('Sort by a specific language that the content is in.'), + 'sort' => array( + 'handler' => 'views_handler_sort_node_language', + ), + ); } diff --git a/sites/all/modules/contrib/views/views/modules/locale/views_handler_field_locale_link_edit.inc b/sites/all/modules/contrib/views/views/modules/locale/views_handler_field_locale_link_edit.inc index 37893551..811bcb27 100644 --- a/sites/all/modules/contrib/views/views/modules/locale/views_handler_field_locale_link_edit.inc +++ b/sites/all/modules/contrib/views/views/modules/locale/views_handler_field_locale_link_edit.inc @@ -52,7 +52,7 @@ class views_handler_field_locale_link_edit extends views_handler_field { $text = !empty($this->options['text']) ? $this->options['text'] : t('edit'); $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = 'admin/build/translate/edit/' . $data; + $this->options['alter']['path'] = 'admin/config/regional/translate/edit/' . $data; $this->options['alter']['query'] = drupal_get_destination(); return $text; diff --git a/sites/all/modules/contrib/views/views/modules/locale/views_handler_sort_node_language.inc b/sites/all/modules/contrib/views/views/modules/locale/views_handler_sort_node_language.inc new file mode 100644 index 00000000..b4298917 --- /dev/null +++ b/sites/all/modules/contrib/views/views/modules/locale/views_handler_sort_node_language.inc @@ -0,0 +1,107 @@ +options['language'])) { + $langcode = $this->get_system_langcode($this->options['language']); + // Validate the langcode. + if (preg_match('/^[a-z0-9\-]+$/i', $langcode)) { + $this->ensure_my_table(); + // See https://stackoverflow.com/questions/14104055/ordering-by-specific-field-value-first + $formula = "{$this->table_alias}_language = '{$langcode}'"; + $this->query->add_orderby($this->table_alias, NULL, $this->options['order'], $formula); + } + } + } + + /** + * Converts a views language code into a Drupal language code. + */ + function get_system_langcode($langcode) { + global $language_content; + $default_language = language_default('language'); + $system_langcode = str_replace(array( + '***CURRENT_LANGUAGE***', + '***DEFAULT_LANGUAGE***', + ), + array( + $language_content->language, + $default_language, + ), + $langcode); + return $system_langcode; + } + + /** + * {@inheritdoc} + */ + function option_definition() { + $options = parent::option_definition(); + $options['language'] = array('default' => '***CURRENT_LANGUAGE***'); + return $options; + } + + /** + * {@inheritdoc} + */ + function admin_summary() { + $summary = parent::admin_summary(); + if ($this->options['language']) { + $language_options = $this->get_language_options(); + $summary = t('@order, @language', array( + '@order' => $summary, + '@language' => $language_options[$this->options['language']], + )); + } + return $summary; + } + + /** + * Returns languages to sort by. + * + * @return array + * All the languages. + */ + function get_language_options() { + $languages = array( + '***CURRENT_LANGUAGE***' => t("Current user's language"), + '***DEFAULT_LANGUAGE***' => t("Default site language"), + LANGUAGE_NONE => t('No language') + ); + $languages = array_merge($languages, views_language_list()); + return $languages; + } + + /** + * {@inheritdoc} + */ + function show_sort_form(&$form, &$form_state) { + parent::show_sort_form($form, $form_state); + + $form['language'] = array( + '#type' => 'radios', + '#title' => t("Specific language"), + '#description' => t("Choose which specific language to sort by. Not to be confused with the 'Language' sort handler, which sorts by language."), + '#options' => $this->get_language_options(), + '#default_value' => $this->options['language'], + ); + } + +} + diff --git a/sites/all/modules/contrib/views/views/modules/node.views.inc b/sites/all/modules/contrib/views/views/modules/node.views.inc index 71a10237..1a9c76bd 100644 --- a/sites/all/modules/contrib/views/views/modules/node.views.inc +++ b/sites/all/modules/contrib/views/views/modules/node.views.inc @@ -406,6 +406,23 @@ function node_views_data() { ), ); + $data['node']['version_count'] = array( + 'title' => t('Version Count'), + 'help' => t('The total count of versions/revisions of a certain node.'), + 'field' => array( + 'handler' => 'views_handler_field_node_version_count', + 'field' => 'nid', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_node_version_count', + 'allow empty' => FALSE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort_node_version_count', + ), + ); + // ---------------------------------------------------------------------- // Content revision table @@ -413,6 +430,7 @@ function node_views_data() { // have a group defined will go into this field by default. $data['node_revisions']['moved to'] = 'node_revision'; $data['node_revision']['table']['entity type'] = 'node'; + $data['node_revision']['table']['revision'] = TRUE; $data['node_revision']['table']['group'] = t('Content revision'); // Support the conversion of the field body $data['node_revisions']['body']['moved to'] = array('field_revision_data', 'body-revision_id'); diff --git a/sites/all/modules/contrib/views/views/modules/node/views_handler_field_node_version_count.inc b/sites/all/modules/contrib/views/views/modules/node/views_handler_field_node_version_count.inc new file mode 100644 index 00000000..73c2925d --- /dev/null +++ b/sites/all/modules/contrib/views/views/modules/node/views_handler_field_node_version_count.inc @@ -0,0 +1,21 @@ +ensure_my_table(); + // Add the field. + $params = $this->options['group_type'] != 'group' ? array('function' => $this->options['group_type']) : array(); + $this->field_alias = $this->query->add_field(NULL, '(SELECT COUNT(vid) FROM {node_revision} WHERE nid = {node}.nid)', 'node_version_count', $params); + + $this->add_additional_fields(); + } +} diff --git a/sites/all/modules/contrib/views/views/modules/node/views_handler_filter_node_uid_revision.inc b/sites/all/modules/contrib/views/views/modules/node/views_handler_filter_node_uid_revision.inc index 4d3d9a70..f8f4000c 100644 --- a/sites/all/modules/contrib/views/views/modules/node/views_handler_filter_node_uid_revision.inc +++ b/sites/all/modules/contrib/views/views/modules/node/views_handler_filter_node_uid_revision.inc @@ -18,7 +18,7 @@ class views_handler_filter_node_uid_revision extends views_handler_filter_user_n $args = array_values($this->value); - $this->query->add_where_expression($this->options['group'], "$this->table_alias.uid IN($placeholder) " . $condition . " OR + $this->query->add_where_expression($this->options['group'], "$this->table_alias.uid IN($placeholder) " . "OR ((SELECT COUNT(*) FROM {node_revision} nr WHERE nr.uid IN($placeholder) AND nr.nid = $this->table_alias.nid) > 0)", array($placeholder => $args), $args); } diff --git a/sites/all/modules/contrib/views/views/modules/node/views_handler_filter_node_version_count.inc b/sites/all/modules/contrib/views/views/modules/node/views_handler_filter_node_version_count.inc new file mode 100644 index 00000000..c39f1d9f --- /dev/null +++ b/sites/all/modules/contrib/views/views/modules/node/views_handler_filter_node_version_count.inc @@ -0,0 +1,36 @@ +operator == 'between') { + $this->query->add_where_expression($this->options['group'], '(SELECT COUNT(vid) FROM {node_revision} WHERE nid = {' . $this->table_alias . '}.nid) BETWEEN :min AND :max', array(':min' => $this->value['min'], ':max' => $this->value['max'])); + } + else { + $this->query->add_where_expression($this->options['group'], '((SELECT COUNT(vid) FROM {node_revision} WHERE nid = {' . $this->table_alias . '}.nid) <= :min OR (SELECT COUNT(vid) FROM {node_revision} WHERE nid = {' . $this->table_alias . '}.nid) >= :max)', array(':min' => $this->value['min'], ':max' => $this->value['max'])); + } + } + + function op_simple($field) { + $this->query->add_where_expression($this->options['group'], '(SELECT COUNT(vid) FROM {node_revision} WHERE nid = {' . $this->table_alias . '}.nid)' . $this->operator . ' :value', array(':value' => $this->value['value'])); + } + + function op_empty($field) { + if ($this->operator == 'empty') { + $operator = "IS NULL"; + } + else { + $operator = "IS NOT NULL"; + } + + $this->query->add_where_expression($this->options['group'], '(SELECT COUNT(vid) FROM {node_revision} WHERE nid = {' . $this->table_alias . '}.nid) ' . $this->operator); + } + + function op_regex($field) { + $this->query->add_where_expression($this->options['group'], '(SELECT COUNT(vid) FROM {node_revision} WHERE nid = {' . $this->table_alias . '}.nid) RLIKE :value', array(':value' => $this->value['value'])); + } +} diff --git a/sites/all/modules/contrib/views/views/modules/node/views_handler_sort_node_version_count.inc b/sites/all/modules/contrib/views/views/modules/node/views_handler_sort_node_version_count.inc new file mode 100644 index 00000000..a8e1cf6e --- /dev/null +++ b/sites/all/modules/contrib/views/views/modules/node/views_handler_sort_node_version_count.inc @@ -0,0 +1,19 @@ +ensure_my_table(); + + $this->query->add_orderby(NULL, '(SELECT COUNT(vid) FROM {node_revision} WHERE nid = {' . $this->table_alias . '}.nid)', $this->options['order'], 'sort_node_version_count'); + } +} diff --git a/sites/all/modules/contrib/views/views/modules/search/views_handler_argument_search.inc b/sites/all/modules/contrib/views/views/modules/search/views_handler_argument_search.inc index f0a4a448..959a25af 100644 --- a/sites/all/modules/contrib/views/views/modules/search/views_handler_argument_search.inc +++ b/sites/all/modules/contrib/views/views/modules/search/views_handler_argument_search.inc @@ -56,7 +56,7 @@ class views_handler_argument_search extends views_handler_argument { $join->construct('search_total', $search_index, 'word', 'word'); $search_total = $this->query->add_relationship('search_total', $join, $search_index); - $this->search_score = $this->query->add_field('', "SUM($search_index.score * $search_total.count)", 'score', array('aggregate' => TRUE)); + $this->search_score = $this->query->add_field('', "$search_index.score * $search_total.count", 'score', array('aggregate' => TRUE, 'function' => 'sum')); if (empty($this->query->relationships[$this->relationship])) { $base_table = $this->query->base_table; diff --git a/sites/all/modules/contrib/views/views/modules/search/views_handler_filter_search.inc b/sites/all/modules/contrib/views/views/modules/search/views_handler_filter_search.inc index 16515a76..0b93031c 100644 --- a/sites/all/modules/contrib/views/views/modules/search/views_handler_filter_search.inc +++ b/sites/all/modules/contrib/views/views/modules/search/views_handler_filter_search.inc @@ -150,7 +150,7 @@ class views_handler_filter_search extends views_handler_filter { $join->construct('search_total', $search_index, 'word', 'word'); $search_total = $this->query->add_relationship('search_total', $join, $search_index); - $this->search_score = $this->query->add_field('', "SUM($search_index.score * $search_total.count)", 'score', array('aggregate' => TRUE)); + $this->search_score = $this->query->add_field('', "$search_index.score * $search_total.count", 'score', array('aggregate' => TRUE, 'function' => 'sum')); } if (empty($this->query->relationships[$this->relationship])) { diff --git a/sites/all/modules/contrib/views/views/modules/statistics.views.inc b/sites/all/modules/contrib/views/views/modules/statistics.views.inc index d6637f3e..6d99c5e6 100644 --- a/sites/all/modules/contrib/views/views/modules/statistics.views.inc +++ b/sites/all/modules/contrib/views/views/modules/statistics.views.inc @@ -32,7 +32,7 @@ function statistics_views_data() { 'help' => t('The total number of times the node has been viewed.'), 'field' => array( - 'handler' => 'views_handler_field_numeric', + 'handler' => 'views_handler_field_statistics_numeric', 'click sortable' => TRUE, ), 'filter' => array( @@ -49,7 +49,7 @@ function statistics_views_data() { 'help' => t('The total number of times the node has been viewed today.'), 'field' => array( - 'handler' => 'views_handler_field_numeric', + 'handler' => 'views_handler_field_statistics_numeric', 'click sortable' => TRUE, ), 'filter' => array( @@ -66,7 +66,7 @@ function statistics_views_data() { 'help' => t('The most recent time the node has been viewed.'), 'field' => array( - 'handler' => 'views_handler_field_date', + 'handler' => 'views_handler_field_node_counter_timestamp', 'click sortable' => TRUE, ), 'filter' => array( diff --git a/sites/all/modules/contrib/views/views/modules/statistics/views_handler_field_node_counter_timestamp.inc b/sites/all/modules/contrib/views/views/modules/statistics/views_handler_field_node_counter_timestamp.inc new file mode 100644 index 00000000..d665519b --- /dev/null +++ b/sites/all/modules/contrib/views/views/modules/statistics/views_handler_field_node_counter_timestamp.inc @@ -0,0 +1,21 @@ + t('Display content if it has the selected taxonomy terms, or children of the selected terms. Due to additional complexity, this has fewer options than the versions without depth.'), + 'real field' => 'nid', + 'argument' => array( + 'title' => t('Has taxonomy term ID with depth (using joins)'), + 'handler' => 'views_handler_argument_term_node_tid_depth_join', + 'accept depth modifier' => TRUE, + ), + 'filter' => array( + 'title' => t('Has taxonomy terms with depth (using joins)'), + 'handler' => 'views_handler_filter_term_node_tid_depth_join', + ), + ); + $data['node']['term_node_tid_depth_modifier'] = array( 'title' => t('Has taxonomy term ID depth modifier'), 'help' => t('Allows the "depth" for Taxonomy: Term ID (with depth) to be modified via an additional contextual filter value.'), diff --git a/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_argument_term_node_tid_depth_join.inc b/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_argument_term_node_tid_depth_join.inc new file mode 100644 index 00000000..23ac62d1 --- /dev/null +++ b/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_argument_term_node_tid_depth_join.inc @@ -0,0 +1,191 @@ + 0); + $options['break_phrase'] = array('default' => FALSE, 'bool' => TRUE); + $options['set_breadcrumb'] = array('default' => FALSE, 'bool' => TRUE); + $options['use_taxonomy_term_path'] = array('default' => FALSE, 'bool' => TRUE); + + return $options; + } + + function 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).'), + ); + + $form['break_phrase'] = array( + '#type' => 'checkbox', + '#title' => t('Allow multiple values'), + '#description' => t('If selected, users can enter multiple values in the form of 1+2+3. Due to the number of JOINs it would require, AND will be treated as OR with this filter.'), + '#default_value' => !empty($this->options['break_phrase']), + ); + + $form['set_breadcrumb'] = array( + '#type' => 'checkbox', + '#title' => t("Set the breadcrumb for the term parents"), + '#description' => t('If selected, the breadcrumb trail will include all parent terms, each one linking to this view. Note that this only works if just one term was received.'), + '#default_value' => !empty($this->options['set_breadcrumb']), + ); + + $form['use_taxonomy_term_path'] = array( + '#type' => 'checkbox', + '#title' => t("Use Drupal's taxonomy term path to create breadcrumb links"), + '#description' => t('If selected, the links in the breadcrumb trail will be created using the standard drupal method instead of the custom views method. This is useful if you are using modules like taxonomy redirect to modify your taxonomy term links.'), + '#default_value' => !empty($this->options['use_taxonomy_term_path']), + '#dependency' => array('edit-options-set-breadcrumb' => array(TRUE)), + ); + parent::options_form($form, $form_state); + } + + function set_breadcrumb(&$breadcrumb) { + if (empty($this->options['set_breadcrumb']) || !is_numeric($this->argument)) { + return; + } + + return views_taxonomy_set_breadcrumb($breadcrumb, $this); + } + + /** + * Override default_actions() to remove summary actions. + */ + function default_actions($which = NULL) { + if ($which) { + if (in_array($which, array('ignore', 'not found', 'empty', 'default'))) { + return parent::default_actions($which); + } + return; + } + $actions = parent::default_actions(); + unset($actions['summary asc']); + unset($actions['summary desc']); + unset($actions['summary asc by count']); + unset($actions['summary desc by count']); + return $actions; + } + + function query($group_by = FALSE) { + $this->ensure_my_table(); + + if (!empty($this->options['break_phrase'])) { + $tids = new stdClass(); + $tids->value = $this->argument; + $tids = views_break_phrase($this->argument, $tids); + if ($tids->value == array(-1)) { + return FALSE; + } + + if (count($tids->value) > 1) { + $operator = 'IN'; + } + else { + $operator = '='; + } + + $tids = $tids->value; + } + else { + $operator = "="; + $tids = $this->argument; + } + + // The tids variable can be an integer or an array of integers. + $tids = is_array($tids) ? $tids : array($tids); + + if ($this->options['depth'] > 0) { + // When the depth is positive search the children. + foreach ($tids as $tid) { + // The term must be loaded to get vid for use in taxonomy_get_tree(). + if ($term = taxonomy_term_load($tid)) { + // For every tid argument find all the children down to the depth set + // in the options and save the tids for the condition. + $tree = taxonomy_get_tree($term->vid, $term->tid, (int) $this->options['depth']); + $tids = array_merge($tids, array_map('_taxonomy_get_tid_from_term', $tree)); + } + } + } + elseif ($this->options['depth'] < 0) { + // When the depth is negative search the parents. + foreach ($tids as $tid) { + // For every tid argument find all the parents up to the depth set + // in the options and add the tids into the array. Since there is + // no taxonomy function to get all parents with a depth limit it + // is done here building a multidimensional array. + if ($term = taxonomy_term_load($tid)) { + // A variable is needed to track the current depth level. + $n = 0; + // Initialise our depth based parents array with the leaf term. + $parents[$n--][] = $term; + while ($n >= $this->options['depth']) { + // At each depth find the parents of the current terms. + // It is important to note that it is possible for a term to have + // multiple parents so get the parents of every parent and so on. + $parents[$n] = array(); + foreach ($parents[$n + 1] as $term) { + $parents[$n] += taxonomy_get_parents($term->tid); + } + // Save all the tids for the condition. + $tids = array_merge($tids, array_map('_taxonomy_get_tid_from_term', $parents[$n])); + $n--; + } + } + } + } + + // Check the size of the array and set the operator accordingly. + if (count($tids) > 1) { + $operator = 'IN'; + } + else { + $tids = current($tids); + $operator = '='; + } + + // Join on taxonomy index table. + $join = new views_join(); + $join->table = 'taxonomy_index'; + $join->field = 'nid'; + $join->left_table = $this->table_alias; + $join->left_field = $this->real_field; + $join->type = 'INNER'; + $join->extra = array( + array( + 'field' => 'tid', + 'value' => $tids, + 'operator' => $operator, + ) + ); + $taxonomy_index_alias = $this->query->add_relationship('taxonomy_index', $join, 'node'); + + // Distinct is required to prevent duplicate rows. + $this->query->distinct = TRUE; + } + + function title() { + $term = taxonomy_term_load($this->argument); + if (!empty($term)) { + return check_plain($term->name); + } + + return t('No name'); + } +} diff --git a/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_filter_term_node_tid.inc b/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_filter_term_node_tid.inc index 8938ca9f..ca2b3449 100644 --- a/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_filter_term_node_tid.inc +++ b/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_filter_term_node_tid.inc @@ -206,6 +206,9 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on if (empty($form_state['exposed'])) { // Retain the helper option $this->helper->options_form($form, $form_state); + + // Show help text if not exposed to end users. + $form['value']['#description'] = t('Leave blank for all. Otherwise, the first selected term will be the default instead of "Any".'); } } @@ -228,12 +231,25 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on return TRUE; } + // We need to know the operator, which is normally set in + // views_handler_filter::accept_exposed_input(), before we actually call + // the parent version of ourselves. + if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']) && isset($input[$this->options['expose']['operator_id']])) { + $this->operator = $input[$this->options['expose']['operator_id']]; + } + // If view is an attachment and is inheriting exposed filters, then assume // exposed input has already been validated if (!empty($this->view->is_attachment) && $this->view->display_handler->uses_exposed()) { $this->validated_exposed_input = (array) $this->view->exposed_raw_input[$this->options['expose']['identifier']]; } + // If we're checking for EMPTY or NOT, we don't need any input, and we can + // say that our input conditions are met by just having the right operator. + if ($this->operator == 'empty' || $this->operator == 'not empty') { + return TRUE; + } + // If it's non-required and there's no value don't bother filtering. if (!$this->options['expose']['required'] && empty($this->validated_exposed_input)) { return FALSE; diff --git a/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_filter_term_node_tid_depth_join.inc b/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_filter_term_node_tid_depth_join.inc new file mode 100644 index 00000000..8139b8d0 --- /dev/null +++ b/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_filter_term_node_tid_depth_join.inc @@ -0,0 +1,142 @@ + 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; + } + elseif (count($this->value) == 1) { + // Somethis $this->value is an array with a single element so convert it. + if (is_array($this->value)) { + $this->value = current($this->value); + } + $operator = '='; + } + else { + $operator = 'IN';# " 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. + elseif (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; + } + + // The tids variable can be an integer or an array of integers. + $tids = is_array($this->value) ? $this->value : array($this->value); + + if ($this->options['depth'] > 0) { + // When the depth is positive search the children. + foreach ($tids as $tid) { + // The term must be loaded to get vid for use in taxonomy_get_tree(). + if ($term = taxonomy_term_load($tid)) { + // For every tid argument find all the children down to the depth set + // in the options and save the tids for the condition. + $tree = taxonomy_get_tree($term->vid, $term->tid, (int) $this->options['depth']); + $tids = array_merge($tids, array_map('_taxonomy_get_tid_from_term', $tree)); + } + } + } + elseif ($this->options['depth'] < 0) { + // When the depth is negative search the parents. + foreach ($tids as $tid) { + // For every tid argument find all the parents up to the depth set + // in the options and add the tids into the array. Since there is + // no taxonomy function to get all parents with a depth limit it + // is done here building a multidimensional array. + if ($term = taxonomy_term_load($tid)) { + // A variable is needed to track the current depth level. + $n = 0; + // Initialise our depth based parents array with the leaf term. + $parents[$n--][] = $term; + while ($n >= $this->options['depth']) { + // At each depth find the parents of the current terms. + // It is important to note that it is possible for a term to have + // multiple parents so get the parents of every parent and so on. + $parents[$n] = array(); + foreach ($parents[$n + 1] as $term) { + $parents[$n] += taxonomy_get_parents($term->tid); + } + // Save all the tids for the condition. + $tids = array_merge($tids, array_map('_taxonomy_get_tid_from_term', $parents[$n])); + $n--; + } + } + } + } + + // Check the size of the array and set the operator accordingly. + if (count($tids) > 1) { + $operator = 'IN'; + } + else { + $tids = current($tids); + $operator = '='; + } + + // Join on taxonomy index table. + $join = new views_join(); + $join->table = 'taxonomy_index'; + $join->field = 'nid'; + $join->left_table = $this->table_alias; + $join->left_field = $this->real_field; + $join->type = 'INNER'; + $join->extra = array( + array( + 'field' => 'tid', + 'value' => $tids, + 'operator' => $operator, + ) + ); + $taxonomy_index_alias = $this->query->add_relationship('taxonomy_index', $join, 'node'); + } +} diff --git a/sites/all/modules/contrib/views/views/modules/translation.views.inc b/sites/all/modules/contrib/views/views/modules/translation.views.inc index b36c7a78..584c63f9 100644 --- a/sites/all/modules/contrib/views/views/modules/translation.views.inc +++ b/sites/all/modules/contrib/views/views/modules/translation.views.inc @@ -51,7 +51,7 @@ function translation_views_data_alter(&$data) { ), ); - // The source translation. + // All translations. $data['node']['translation'] = array( 'group' => t('Content translation'), 'title' => t('Translations'), @@ -62,7 +62,7 @@ function translation_views_data_alter(&$data) { 'base' => 'node', 'base field' => 'tnid', 'relationship table' => 'node', - 'relationship field' => 'nid', + 'relationship field' => 'tnid', 'handler' => 'views_handler_relationship_translation', 'label' => t('Translations'), ), @@ -78,7 +78,7 @@ function translation_views_data_alter(&$data) { ), ); - // The source translation. + // Child translation. $data['node']['child_translation'] = array( 'group' => t('Node translation'), 'title' => t('Child translation'), diff --git a/sites/all/modules/contrib/views/views/modules/views.views.inc b/sites/all/modules/contrib/views/views/modules/views.views.inc index 7c3f4db9..ce3aad38 100644 --- a/sites/all/modules/contrib/views/views/modules/views.views.inc +++ b/sites/all/modules/contrib/views/views/modules/views.views.inc @@ -99,6 +99,14 @@ function views_views_data() { ); } + $data['views']['ctools_dropdown'] = array( + 'title' => t('Dropdown links'), + 'help' => t('Displays fields in a dropdown list, like on the views listing page.'), + 'field' => array( + 'handler' => 'views_handler_field_ctools_dropdown', + ), + ); + $data['views']['combine'] = array( 'title' => t('Combine fields filter'), 'help' => t('Combine two fields together and search by them.'), diff --git a/sites/all/modules/contrib/views/views/plugins/export_ui/views_ui.class.php b/sites/all/modules/contrib/views/views/plugins/export_ui/views_ui.class.php index 9d801382..6f87e401 100644 --- a/sites/all/modules/contrib/views/views/plugins/export_ui/views_ui.class.php +++ b/sites/all/modules/contrib/views/views/plugins/export_ui/views_ui.class.php @@ -385,8 +385,8 @@ class views_ui extends ctools_export_ui { $output = parent::list_page($js, $input); if (is_string($output)) { $output = '
' . $output . '
'; - return $output; } + return $output; } } diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_argument_validate.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_argument_validate.inc index 07b49eeb..350cb439 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_argument_validate.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_argument_validate.inc @@ -86,7 +86,7 @@ class views_plugin_argument_validate extends views_plugin { /** * Process the summary arguments for displaying. * - * Some plugins alter the argument so it uses something else interal. + * Some plugins alter the argument so it uses something else internally. * For example the user validation set's the argument to the uid, * for a faster query. But there are use cases where you want to use * the old value again, for example the summary. diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_cache_time.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_cache_time.inc index 25245ea4..d3ab7f92 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_cache_time.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_cache_time.inc @@ -107,4 +107,21 @@ class views_plugin_cache_time extends views_plugin_cache { return CACHE_PERMANENT; } } + + function cache_set($type) { + $lifespan = $this->get_lifespan($type); + if ($lifespan >= 0) { + parent::cache_set($type); + } + } + + function cache_get($type) { + $lifespan = $this->get_lifespan($type); + if ($lifespan >= 0) { + return parent::cache_get($type); + } + else { + return FALSE; + } + } } diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_display.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_display.inc index bc42db46..a4b732e8 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_display.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_display.inc @@ -53,7 +53,7 @@ class views_plugin_display extends views_plugin { $this->extender[$extender] = $plugin; } else { - vpr('Invalid display extender @extender', array('@handler' => $extender)); + vpr('Invalid display extender @extender', array('@extender' => $extender)); } } } @@ -739,7 +739,7 @@ class views_plugin_display extends views_plugin { function uses_link_display() { return !$this->has_path(); } /** - * Check to see if the display can put the exposed formin a block. + * Check to see if the display can put the exposed form in a block. * * By default, displays that do not have a path cannot disconnect * the exposed form and put it in a block, because the form has no @@ -1150,7 +1150,7 @@ class views_plugin_display extends views_plugin { ); } - $display_comment = check_plain(drupal_substr($this->get_option('display_comment'), 0, 10)); + $display_comment = check_plain(views_ui_truncate($this->get_option('display_comment'), 80)); $options['display_comment'] = array( 'category' => 'other', 'title' => t('Comment'), @@ -1419,7 +1419,7 @@ class views_plugin_display extends views_plugin { } $form['#title'] = check_plain($this->display->display_title) . ': '; - // Set the 'section' to hilite on the form. + // Set the 'section' to highlight on the form. // If it's the item we're looking at is pulling from the default display, // reflect that. Don't use is_defaulted since we want it to show up even // on the default display. @@ -1573,8 +1573,12 @@ class views_plugin_display extends views_plugin { $plugin = $this->get_plugin('access'); $form['#title'] .= t('Access options'); if ($plugin) { - $form['#help_topic'] = $plugin->definition['help topic']; - $form['#help_module'] = $plugin->definition['module']; + if (!empty($plugin->definition['help topic'])) { + $form['#help_topic'] = $plugin->definition['help topic']; + } + if (!empty($plugin->definition['module'])) { + $form['#help_module'] = $plugin->definition['module']; + } $form['access_options'] = array( '#tree' => TRUE, @@ -1615,8 +1619,12 @@ class views_plugin_display extends views_plugin { $plugin = $this->get_plugin('cache'); $form['#title'] .= t('Caching options'); if ($plugin) { - $form['#help_topic'] = $plugin->definition['help topic']; - $form['#help_module'] = $plugin->definition['module']; + if (!empty($plugin->definition['help topic'])) { + $form['#help_topic'] = $plugin->definition['help topic']; + } + if (!empty($plugin->definition['module'])) { + $form['#help_module'] = $plugin->definition['module']; + } $form['cache_options'] = array( '#tree' => TRUE, @@ -1635,11 +1643,10 @@ class views_plugin_display extends views_plugin { $form['#title'] .= t('Query options'); $this->view->init_query(); if ($this->view->query) { - if (isset($this->view->query->definition['help topic'])) { + if (!empty($this->view->query->definition['help topic'])) { $form['#help_topic'] = $this->view->query->definition['help topic']; } - - if (isset($this->view->query->definition['module'])) { + if (!empty($this->view->query->definition['module'])) { $form['#help_module'] = $this->view->query->definition['module']; } @@ -1734,8 +1741,10 @@ class views_plugin_display extends views_plugin { } $plugin = $this->get_plugin(empty($style) ? 'row' : 'style'); if ($plugin) { - if (isset($plugin->definition['help topic'])) { + if (!empty($plugin->definition['help topic'])) { $form['#help_topic'] = $plugin->definition['help topic']; + } + if (!empty($plugin->definition['module'])) { $form['#help_module'] = $plugin->definition['module']; } $form[$form_state['section']] = array( @@ -2117,7 +2126,12 @@ class views_plugin_display extends views_plugin { $plugin = $this->get_plugin('exposed_form'); $form['#title'] .= t('Exposed form options'); if ($plugin) { - $form['#help_topic'] = $plugin->definition['help topic']; + if (!empty($plugin->definition['help topic'])) { + $form['#help_topic'] = $plugin->definition['help topic']; + } + if (!empty($plugin->definition['module'])) { + $form['#help_module'] = $plugin->definition['module']; + } $form['exposed_form_options'] = array( '#tree' => TRUE, @@ -2154,7 +2168,12 @@ class views_plugin_display extends views_plugin { $plugin = $this->get_plugin('pager'); $form['#title'] .= t('Pager options'); if ($plugin) { - $form['#help_topic'] = $plugin->definition['help topic']; + if (!empty($plugin->definition['help topic'])) { + $form['#help_topic'] = $plugin->definition['help topic']; + } + if (!empty($plugin->definition['module'])) { + $form['#help_module'] = $plugin->definition['module']; + } $form['pager_options'] = array( '#tree' => TRUE, @@ -2556,6 +2575,23 @@ class views_plugin_display extends views_plugin { $url_options['query'] = $this->view->exposed_raw_input; } $theme = views_theme_functions('views_more', $this->view, $this->display); + + $parsed_url = drupal_parse_url($path); + // Preserve the query string from url. + if (!empty($parsed_url['query'])) { + if (!empty($url_options['query'])) { + $url_options['query'] = array_merge($parsed_url['query'], $url_options['query']); + } + else { + $url_options['query'] = $parsed_url['query']; + } + $path = $parsed_url['path']; + } + // Add fragment if applicable. + if (!empty($parsed_url['fragment'])) { + $url_options['fragment'] = $parsed_url['fragment']; + } + $path = check_url(url($path, $url_options)); return theme($theme, array('more_url' => $path, 'link_text' => check_plain($this->use_more_text()), 'view' => $this->view)); diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_display_block.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_display_block.inc index c903a9b6..d581a16a 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_display_block.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_display_block.inc @@ -222,8 +222,8 @@ class views_plugin_display_block extends views_plugin_display { } /** - * Save the block cache setting in the blocks table if this block allready - * exists in the blocks table. Dirty fix untill http://drupal.org/node/235673 gets in. + * Save the block cache setting in the blocks table if this block already + * exists in the blocks table. Dirty fix until http://drupal.org/node/235673 gets in. */ function save_block_cache($delta, $cache_setting) { if (strlen($delta) >= 32) { diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_query_default.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_query_default.inc index 5e0539c8..7468dd95 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_query_default.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_query_default.inc @@ -143,7 +143,7 @@ class views_plugin_query_default extends views_plugin_query { ); /** - * -- we no longer want the base field to appear automatigically. + * -- we no longer want the base field to appear automatically. if ($base_field) { $this->fields[$base_field] = array( 'table' => $base_table, @@ -888,7 +888,7 @@ class views_plugin_query_default extends views_plugin_query { /** * Add a complex WHERE clause to the query. * - * The caller is reponsible for ensuring that all fields are fully qualified + * The caller is responsible for ensuring that all fields are fully qualified * (TABLE.FIELD) and that the table already exists in the query. * Internally the dbtng method "where" is used. * @@ -1592,7 +1592,7 @@ class views_plugin_query_default extends views_plugin_query { 'sort' => 'views_handler_sort_group_by_numeric', ), ) - ); + ) + views_fetch_plugin_data('query_aggregate'); } /** @@ -1620,7 +1620,8 @@ class views_plugin_query_default extends views_plugin_query { } $entity_type = $table_data['table']['entity type']; $info = entity_get_info($entity_type); - $id_alias = $this->get_field_alias($base_table_alias, $info['entity keys']['id']); + $is_revision = !empty($table_data['table']['revision']); + $id_alias = $this->get_field_alias($base_table_alias, $info['entity keys'][$is_revision ? 'revision' : 'id']); // Assemble the ids of the entities to load. $ids = array(); @@ -1630,12 +1631,34 @@ class views_plugin_query_default extends views_plugin_query { } } - $entities = entity_load($entity_type, $ids); - // Re-key the array by row-index. - $result = array(); - foreach ($ids as $key => $id) { - $result[$key] = isset($entities[$id]) ? $entities[$id] : FALSE; + if (!$is_revision) { + $entities = entity_load($entity_type, $ids); + + // Re-key the array by row-index. + $result = array(); + foreach ($ids as $key => $id) { + $result[$key] = isset($entities[$id]) ? $entities[$id] : FALSE; + } } + else { + // There's no way in core to load revisions in bulk. + $result = array(); + foreach ($ids as $key => $id) { + // Nodes can be dealt with in core. + if ($entity_type == 'node') { + $result[$key] = node_load(NULL, $id); + } + // Otherwise see if entity is enabled. + elseif (module_exists('entity')) { + $result[$key] = entity_revision_load($entity_type, $id); + } + else { + // Otherwise this isn't supported. + watchdog('views', 'Attempt to load a revision on an unsupported entity type @entity_type.', array('@entity_type' => $entity_type), WATCHDOG_WARNING); + } + } + } + return array($entity_type, $result); } } diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_style.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_style.inc index d355e1bc..fe126071 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_style.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_style.inc @@ -123,13 +123,23 @@ class views_plugin_style extends views_plugin { function get_row_class($row_index) { if ($this->uses_row_class()) { $class = $this->options['row_class']; + if ($this->uses_fields() && $this->view->field) { - $class = strip_tags($this->tokenize_value($class, $row_index)); + $classes = array(); + + // Explode the value by whitespace, this allows the function to handle + // a single class name and multiple class names that are then tokenized. + foreach(explode(' ', $class) as $token_class) { + $classes[] = strip_tags($this->tokenize_value($token_class, $row_index)); + } + } + else { + $classes = explode(' ', $class); } - $classes = explode(' ', $class); + // Convert whatever the result is to a nice clean class name foreach ($classes as &$class) { - $class = drupal_clean_css_identifier($class); + $class = drupal_html_class($class); } return implode(' ', $classes); } @@ -182,7 +192,7 @@ class views_plugin_style extends views_plugin { function options_form(&$form, &$form_state) { parent::options_form($form, $form_state); // Only fields-based views can handle grouping. Style plugins can also exclude - // themselves from being groupable by setting their "use grouping" definiton + // themselves from being groupable by setting their "use grouping" definition // key to FALSE. // @TODO: Document "uses grouping" in docs.php when docs.php is written. if ($this->uses_fields() && $this->definition['uses grouping']) { @@ -191,7 +201,7 @@ class views_plugin_style extends views_plugin { $options += $field_labels; // If there are no fields, we can't group on them. if (count($options) > 1) { - // This is for backward compability, when there was just a single select form. + // This is for backward compatibility, when there was just a single select form. if (is_string($this->options['grouping'])) { $grouping = $this->options['grouping']; $this->options['grouping'] = array(); @@ -419,7 +429,7 @@ class views_plugin_style extends views_plugin { * @endcode */ function render_grouping($records, $groupings = array(), $group_rendered = NULL) { - // This is for backward compability, when $groupings was a string containing + // This is for backward compatibility, when $groupings was a string containing // the ID of a single field. if (is_string($groupings)) { $rendered = $group_rendered === NULL ? TRUE : $group_rendered; @@ -486,7 +496,7 @@ class views_plugin_style extends views_plugin { ); } - // If this parameter isn't explicitely set modify the output to be fully + // If this parameter isn't explicitly set modify the output to be fully // backward compatible to code before Views 7.x-3.0-rc2. // @TODO Remove this as soon as possible e.g. October 2020 if ($group_rendered === NULL) { diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_style_rss.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_style_rss.inc index 27106a89..79fef3d0 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_style_rss.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_style_rss.inc @@ -71,6 +71,36 @@ class views_plugin_style_rss extends views_plugin_style { return array(); } + /** + * Return an atom:link XHTML element to add to the channel to comply with + * the RSS 2.0 specification. + * + * @see http://validator.w3.org/feed/docs/warning/MissingAtomSelfLink.html + * + * @return + * An array that can be passed to format_xml_elements(). + */ + function get_channel_elements_atom_link() { + $url_options = array('absolute' => TRUE); + $input = $this->view->get_exposed_input(); + if ($input) { + $url_options['query'] = $input; + } + $url = url($this->view->get_url(), $url_options); + + return array( + array( + 'namespace' => array('xmlns:atom' => 'http://www.w3.org/2005/Atom'), + 'key' => 'atom:link', + 'attributes' => array( + 'href' => $url, + 'rel' => 'self', + 'type' => 'application/rss+xml', + ), + ), + ); + } + /** * Get RSS feed description. * @@ -99,7 +129,10 @@ class views_plugin_style_rss extends views_plugin_style { // Fetch any additional elements for the channel and merge in their // namespaces. - $this->channel_elements = $this->get_channel_elements(); + $this->channel_elements = array_merge( + $this->get_channel_elements(), + $this->get_channel_elements_atom_link() + ); foreach ($this->channel_elements as $element) { if (isset($element['namespace'])) { $this->namespaces = array_merge($this->namespaces, $element['namespace']); diff --git a/sites/all/modules/contrib/views/views/test_templates/README.txt b/sites/all/modules/contrib/views/views/test_templates/README.txt new file mode 100644 index 00000000..551f738f --- /dev/null +++ b/sites/all/modules/contrib/views/views/test_templates/README.txt @@ -0,0 +1,11 @@ +Workaround for: + +- https://www.drupal.org/node/2450447 +- https://www.drupal.org/node/2415991 + + +Files of this folder cannot be included inside the views/tests directory because +they are included as tests cases and make testbot crash. + +This files could be moved to tests/templates once +https://www.drupal.org/node/2415991 be properly fixed. diff --git a/sites/all/modules/contrib/views/views/tests/templates/views-view--frontpage.tpl.php b/sites/all/modules/contrib/views/views/test_templates/views-view--frontpage.tpl.php similarity index 100% rename from sites/all/modules/contrib/views/views/tests/templates/views-view--frontpage.tpl.php rename to sites/all/modules/contrib/views/views/test_templates/views-view--frontpage.tpl.php diff --git a/sites/all/modules/contrib/views/views/tests/styles/views_plugin_style.test b/sites/all/modules/contrib/views/views/tests/styles/views_plugin_style.test index dfc5413a..2bb28574 100644 --- a/sites/all/modules/contrib/views/views/tests/styles/views_plugin_style.test +++ b/sites/all/modules/contrib/views/views/tests/styles/views_plugin_style.test @@ -241,7 +241,7 @@ class ViewsPluginStyleTestCase extends ViewsPluginStyleTestBase { // Setup some random css class. $view->init_display(); $view->init_style(); - $random_name = $this->randomName(); + $random_name = drupal_html_class($this->randomName()); $view->style_plugin->options['row_class'] = $random_name . " test-token-[name]"; $rendered_output = $view->preview(); @@ -255,7 +255,7 @@ class ViewsPluginStyleTestCase extends ViewsPluginStyleTestBase { $this->assertTrue(strpos($class, $random_name) !== FALSE, 'Take sure that a custom css class is added to the output.'); // Check token replacement. - $name = $view->field['name']->get_value($view->result[$count]); + $name = drupal_html_class($view->field['name']->get_value($view->result[$count])); $this->assertTrue(strpos($class, "test-token-$name") !== FALSE, 'Take sure that a token in custom css class is replaced.'); $count++; diff --git a/sites/all/modules/contrib/views/views/tests/views_query.test b/sites/all/modules/contrib/views/views/tests/views_query.test index 735df0ea..db7d6569 100644 --- a/sites/all/modules/contrib/views/views/tests/views_query.test +++ b/sites/all/modules/contrib/views/views/tests/views_query.test @@ -132,7 +132,6 @@ abstract class ViewsSqlTest extends ViewsTestCase { variable_set('views_test_schema', $this->schemaDefinition()); variable_set('views_test_views_data', $this->viewsData()); variable_set('views_test_views_plugins', $this->viewsPlugins()); - module_enable(array('views_test')); $this->resetAll(); diff --git a/sites/all/modules/contrib/views/views/tests/views_test.info b/sites/all/modules/contrib/views/views/tests/views_test.info index a8e51a14..6e9008ed 100644 --- a/sites/all/modules/contrib/views/views/tests/views_test.info +++ b/sites/all/modules/contrib/views/views/tests/views_test.info @@ -5,9 +5,9 @@ core = 7.x dependencies[] = views hidden = TRUE -; Information added by Drupal.org packaging script on 2015-04-29 -version = "7.x-3.11" +; Information added by Drupal.org packaging script on 2016-06-15 +version = "7.x-3.14" core = "7.x" project = "views" -datestamp = "1430321048" +datestamp = "1466019588" diff --git a/sites/all/modules/contrib/views/views/tests/views_test.module b/sites/all/modules/contrib/views/views/tests/views_test.module index a7460690..be533e0c 100644 --- a/sites/all/modules/contrib/views/views/tests/views_test.module +++ b/sites/all/modules/contrib/views/views/tests/views_test.module @@ -23,7 +23,7 @@ function views_test_permission() { function views_test_views_api() { return array( 'api' => 3.0, - 'template path' => drupal_get_path('module', 'views_test') . '/templates', + 'template path' => drupal_get_path('module', 'views') . '/test_templates', ); } diff --git a/sites/all/modules/contrib/views/views/theme/views-view-table.tpl.php b/sites/all/modules/contrib/views/views/theme/views-view-table.tpl.php index 4fec9fa9..b3443fcc 100644 --- a/sites/all/modules/contrib/views/views/theme/views-view-table.tpl.php +++ b/sites/all/modules/contrib/views/views/theme/views-view-table.tpl.php @@ -27,7 +27,7 @@ $label): ?> - > + scope="col"> diff --git a/sites/all/modules/contrib/views/views/views.api.php b/sites/all/modules/contrib/views/views/views.api.php index 599d08eb..1c7b32b2 100644 --- a/sites/all/modules/contrib/views/views/views.api.php +++ b/sites/all/modules/contrib/views/views/views.api.php @@ -143,7 +143,7 @@ * responsible for building the query. Instead, they are objects that are used * to display the view or make other modifications. * - * There are 10 types of plugins in Views: + * There are several types of plugins in Views: * - Display: Display plugins are responsible for controlling *where* a view * lives; that is, how they are being exposed to other parts of Drupal. Page * and block are the most common displays, as well as the ubiquitous 'master' @@ -431,7 +431,7 @@ function hook_views_data() { 'label' => t('Published'), // This setting is used by the boolean filter handler, as possible option. 'type' => 'yes-no', - // use boolean_field = 1 instead of boolean_field <> 0 in WHERE statment. + // use boolean_field = 1 instead of boolean_field <> 0 in WHERE statement. 'use equal' => TRUE, ), 'sort' => array( @@ -602,7 +602,7 @@ function hook_field_views_data_views_data_alter(&$data, $field) { * must be one of row, display, display_extender, style, argument default, * argument validator, access, query, cache, pager, exposed_form or * localization. The plugin name should be prefixed with your module name. - * The value for each entry is an associateive array that may contain the + * The value for each entry is an associative array that may contain the * following entries: * - Used by all plugin types: * - title (required): The name of the plugin, as shown in Views. Wrap in @@ -723,7 +723,7 @@ function hook_views_plugins_alter(&$plugins) { * - path: (optional) If includes are stored somewhere other than within the * root module directory, specify its path here. * - template path: (optional) A path where the module has stored it's views - * template files. When you have specificed this key views automatically + * template files. When you have specified this key views automatically * uses the template files for the views. You can use the same naming * conventions like for normal views template files. */ @@ -859,7 +859,7 @@ function hook_views_default_views_alter(&$views) { * The View being executed. * @return * An array with keys being the strings to replace, and the values the strings - * to replace them with. The strings to replace are ofted surrounded with + * to replace them with. The strings to replace are often surrounded with * '***', as illustrated in the example implementation. */ function hook_views_query_substitutions($view) { @@ -924,7 +924,7 @@ function hook_views_pre_view(&$view, &$display_id, &$args) { * The view object about to be processed. */ function hook_views_pre_build(&$view) { - // Because of some unexplicable business logic, we should remove all + // Because of some inexplicable business logic, we should remove all // attachments from all views on Mondays. // (This alter could be done later in the execution process as well.) if (date('D') == 'Mon') { @@ -1153,8 +1153,8 @@ function hook_views_ajax_data_alter(&$commands, $view) { // Replace Views' method for scrolling to the top of the element with your // custom scrolling method. foreach ($commands as &$command) { - if ($command['method'] == 'viewsScrollTop') { - $command['method'] .= 'myScrollTop'; + if ($command['command'] == 'viewsScrollTop') { + $command['command'] .= 'myScrollTop'; } } } @@ -1171,6 +1171,32 @@ function hook_views_invalidate_cache() { cache_clear_all('views:*', 'cache_mymodule', TRUE); } +/** + * Allow modules to alter a view prior to being saved. + */ +function hook_views_view_presave($view) { + // Do some adjustments to the view. Handle with care. + if (mymodule_check_view($view)) { + mymodule_do_some_voodoo($view); + } +} + +/** + * Allow modules to respond to a view being saved. + */ +function hook_views_view_save($view) { + // Make a watchdog entry. + watchdog('views', 'The view @name was deleted by @user at @time', array('@name' => $view->name, '@user' => $GLOBALS['user']->name, '@time' => format_date(time()))); +} + +/** + * Allow modules to respond to a view being deleted or reverted. + */ +function hook_views_view_delete($view) { + // Make a watchdog entry. + watchdog('views', 'The view @name was deleted by @user at @time', array('@name' => $view->name, '@user' => $GLOBALS['user']->name, '@time' => format_date(time()))); +} + /** * @} */ diff --git a/sites/all/modules/contrib/views/views/views.info b/sites/all/modules/contrib/views/views/views.info index 70832d11..0b425f17 100644 --- a/sites/all/modules/contrib/views/views/views.info +++ b/sites/all/modules/contrib/views/views/views.info @@ -27,9 +27,11 @@ files[] = handlers/views_handler_field.inc files[] = handlers/views_handler_field_counter.inc files[] = handlers/views_handler_field_boolean.inc files[] = handlers/views_handler_field_contextual_links.inc +files[] = handlers/views_handler_field_ctools_dropdown.inc files[] = handlers/views_handler_field_custom.inc files[] = handlers/views_handler_field_date.inc files[] = handlers/views_handler_field_entity.inc +files[] = handlers/views_handler_field_links.inc files[] = handlers/views_handler_field_markup.inc files[] = handlers/views_handler_field_math.inc files[] = handlers/views_handler_field_numeric.inc @@ -116,6 +118,7 @@ files[] = modules/locale/views_handler_field_locale_link_edit.inc files[] = modules/locale/views_handler_filter_locale_group.inc files[] = modules/locale/views_handler_filter_locale_language.inc files[] = modules/locale/views_handler_filter_locale_version.inc +files[] = modules/locale/views_handler_sort_node_language.inc files[] = modules/node/views_handler_argument_dates_various.inc files[] = modules/node/views_handler_argument_node_language.inc files[] = modules/node/views_handler_argument_node_nid.inc @@ -133,11 +136,14 @@ files[] = modules/node/views_handler_field_node_revision_link_delete.inc files[] = modules/node/views_handler_field_node_revision_link_revert.inc files[] = modules/node/views_handler_field_node_path.inc files[] = modules/node/views_handler_field_node_type.inc +files[] = modules/node/views_handler_field_node_version_count.inc files[] = modules/node/views_handler_filter_history_user_timestamp.inc files[] = modules/node/views_handler_filter_node_access.inc files[] = modules/node/views_handler_filter_node_status.inc files[] = modules/node/views_handler_filter_node_type.inc files[] = modules/node/views_handler_filter_node_uid_revision.inc +files[] = modules/node/views_handler_filter_node_version_count.inc +files[] = modules/node/views_handler_sort_node_version_count.inc files[] = modules/node/views_plugin_argument_default_node.inc files[] = modules/node/views_plugin_argument_validate_node.inc files[] = modules/node/views_plugin_row_node_rss.inc @@ -151,6 +157,8 @@ files[] = modules/search/views_handler_filter_search.inc files[] = modules/search/views_handler_sort_search_score.inc files[] = modules/search/views_plugin_row_search_view.inc files[] = modules/statistics/views_handler_field_accesslog_path.inc +files[] = modules/statistics/views_handler_field_node_counter_timestamp.inc +files[] = modules/statistics/views_handler_field_statistics_numeric.inc files[] = modules/system/views_handler_argument_file_fid.inc files[] = modules/system/views_handler_field_file.inc files[] = modules/system/views_handler_field_file_extension.inc @@ -161,6 +169,7 @@ files[] = modules/system/views_handler_filter_file_status.inc files[] = modules/taxonomy/views_handler_argument_taxonomy.inc files[] = modules/taxonomy/views_handler_argument_term_node_tid.inc files[] = modules/taxonomy/views_handler_argument_term_node_tid_depth.inc +files[] = modules/taxonomy/views_handler_argument_term_node_tid_depth_join.inc files[] = modules/taxonomy/views_handler_argument_term_node_tid_depth_modifier.inc files[] = modules/taxonomy/views_handler_argument_vocabulary_vid.inc files[] = modules/taxonomy/views_handler_argument_vocabulary_machine_name.inc @@ -169,6 +178,7 @@ files[] = modules/taxonomy/views_handler_field_term_node_tid.inc files[] = modules/taxonomy/views_handler_field_term_link_edit.inc files[] = modules/taxonomy/views_handler_filter_term_node_tid.inc files[] = modules/taxonomy/views_handler_filter_term_node_tid_depth.inc +files[] = modules/taxonomy/views_handler_filter_term_node_tid_depth_join.inc files[] = modules/taxonomy/views_handler_filter_vocabulary_vid.inc files[] = modules/taxonomy/views_handler_filter_vocabulary_machine_name.inc files[] = modules/taxonomy/views_handler_relationship_node_term_data.inc @@ -318,9 +328,9 @@ files[] = tests/views_cache.test files[] = tests/views_view.test files[] = tests/views_ui.test -; Information added by Drupal.org packaging script on 2015-04-29 -version = "7.x-3.11" +; Information added by Drupal.org packaging script on 2016-06-15 +version = "7.x-3.14" core = "7.x" project = "views" -datestamp = "1430321048" +datestamp = "1466019588" diff --git a/sites/all/modules/contrib/views/views/views.install b/sites/all/modules/contrib/views/views/views.install index b69f4105..ca10d69a 100644 --- a/sites/all/modules/contrib/views/views/views.install +++ b/sites/all/modules/contrib/views/views/views.install @@ -402,7 +402,7 @@ function views_update_6008() { } /** - * Enlarge the views_display.display_options field to accomodate a larger set + * Enlarge the views_display.display_options field to accommodate a larger set * of configurations (e. g. fields, filters, etc.) on a display. */ function views_schema_6009() { @@ -631,3 +631,17 @@ function views_update_7301() { ); db_change_field('views_view', 'name', 'name', $new_field); } + +/** + * Remove headers field from cache tables + * + * @see system_update_7054(). + */ +function views_update_7302() { + if (db_field_exists('cache_views', 'headers')) { + db_drop_field('cache_views', 'headers'); + } + if (db_field_exists('cache_views_data', 'headers')) { + db_drop_field('cache_views_data', 'headers'); + } +} diff --git a/sites/all/modules/contrib/views/views/views.module b/sites/all/modules/contrib/views/views/views.module index 9cdcfb58..aab3812d 100644 --- a/sites/all/modules/contrib/views/views/views.module +++ b/sites/all/modules/contrib/views/views/views.module @@ -1020,8 +1020,21 @@ function views_access() { * permissions. If the $account argument is omitted, the current user * is used. */ -function views_check_perm($perm, $account = NULL) { - return user_access($perm, $account) || user_access('access all views', $account); +function views_check_perm($perms, $account = NULL) { + // Backward compatibility to ensure also a single permission string is + // properly processed. + $perms = is_array($perms) ? $perms : array($perms); + if (user_access('access all views', $account)) { + return TRUE; + } + // Perms are handled as OR, as soon one permission allows access TRUE is + // returned. + foreach ($perms as $perm) { + if (user_access($perm, $account)) { + return TRUE; + } + } + return FALSE; } /** @@ -1298,7 +1311,7 @@ function views_fetch_plugin_data($type = NULL, $plugin = NULL, $reset = FALSE) { * Either 'display', 'style' or 'row' * @param $key * For style plugins, this is an optional type to restrict to. May be 'normal', - * 'summary', 'feed' or others based on the neds of the display. + * 'summary', 'feed' or others based on the needs of the display. * @param $base * An array of possible base tables. * @@ -2413,7 +2426,7 @@ function views_process_check_options($element, &$form_state) { * Trim the field down to the specified length. * * @param $alter - * - max_length: Maximum lenght of the string, the rest gets truncated. + * - max_length: Maximum length of the string, the rest gets truncated. * - word_boundary: Trim only on a word boundary. * - ellipsis: Show an ellipsis (...) at the end of the trimmed string. * - html: Take sure that the html is correct. diff --git a/sites/all/modules/contrib/views/views/views_ui.info b/sites/all/modules/contrib/views/views/views_ui.info index 86671094..cbe65b06 100644 --- a/sites/all/modules/contrib/views/views/views_ui.info +++ b/sites/all/modules/contrib/views/views/views_ui.info @@ -7,9 +7,9 @@ dependencies[] = views files[] = views_ui.module files[] = plugins/views_wizard/views_ui_base_views_wizard.class.php -; Information added by Drupal.org packaging script on 2015-04-29 -version = "7.x-3.11" +; Information added by Drupal.org packaging script on 2016-06-15 +version = "7.x-3.14" core = "7.x" project = "views" -datestamp = "1430321048" +datestamp = "1466019588" diff --git a/sites/all/modules/contrib/views/views/views_ui.module b/sites/all/modules/contrib/views/views/views_ui.module index 5366f778..f35d099f 100644 --- a/sites/all/modules/contrib/views/views/views_ui.module +++ b/sites/all/modules/contrib/views/views/views_ui.module @@ -248,7 +248,7 @@ function views_ui_theme() { } /** - * Impements hook_custom_theme() + * Implements hook_custom_theme(). */ function views_ui_custom_theme() { $theme = variable_get('views_ui_custom_theme', '_default');