From 57cad5a8fd2b3435a6abcf27aa3e5f1b6a5cc0b8 Mon Sep 17 00:00:00 2001 From: Eric Rasmussen <ericrasmussen1@gmail.com> Date: Thu, 19 Jul 2012 10:01:17 -0500 Subject: [PATCH] [gh-428] Upgrade Views to 7.x-3.3 --- sites/all/modules/views/README.txt | 6 +- sites/all/modules/views/docs/views.api.php | 16 +- sites/all/modules/views/drush/views.drush.inc | 1 + .../views/handlers/views_handler_area.inc | 2 + .../handlers/views_handler_area_result.inc | 93 ++++++ .../handlers/views_handler_area_text.inc | 8 +- .../handlers/views_handler_area_view.inc | 5 + .../views/handlers/views_handler_argument.inc | 26 +- ...iews_handler_argument_group_by_numeric.inc | 5 +- .../handlers/views_handler_argument_null.inc | 2 + .../views_handler_argument_numeric.inc | 14 + .../views/handlers/views_handler_field.inc | 131 ++++++++- .../handlers/views_handler_field_boolean.inc | 1 + .../views_handler_field_contextual_links.inc | 87 ++++++ .../handlers/views_handler_field_counter.inc | 5 + .../handlers/views_handler_field_entity.inc | 20 +- .../views_handler_field_machine_name.inc | 68 +++++ .../views_handler_field_prerender_list.inc | 10 + .../views_handler_field_serialized.inc | 5 + .../views/handlers/views_handler_filter.inc | 53 +++- .../views_handler_filter_boolean_operator.inc | 6 +- ...handler_filter_boolean_operator_string.inc | 2 + .../handlers/views_handler_filter_date.inc | 2 + .../views_handler_filter_equality.inc | 2 + .../views_handler_filter_group_by_numeric.inc | 2 + .../views_handler_filter_in_operator.inc | 1 + .../views_handler_filter_many_to_one.inc | 9 + .../handlers/views_handler_filter_numeric.inc | 2 + .../handlers/views_handler_filter_string.inc | 9 +- .../handlers/views_handler_relationship.inc | 6 + ...ews_handler_relationship_groupwise_max.inc | 7 +- .../views/handlers/views_handler_sort.inc | 2 + .../views_handler_sort_group_by_numeric.inc | 2 + .../handlers/views_handler_sort_random.inc | 2 + sites/all/modules/views/help/about.html | 4 +- sites/all/modules/views/help/aggregation.html | 1 + sites/all/modules/views/help/api-forms.html | 18 +- .../all/modules/views/help/api-handlers.html | 2 + sites/all/modules/views/help/api-plugins.html | 38 ++- sites/all/modules/views/help/group-by.html | 17 ++ .../images/views3-group-aggregation-types.png | Bin 0 -> 16742 bytes .../help/images/views3-group-aggregation.png | Bin 0 -> 55825 bytes .../help/images/views3-jump-style-menu.png | Bin 0 -> 40328 bytes sites/all/modules/views/help/new.html | 2 +- sites/all/modules/views/help/reports.html | 2 +- sites/all/modules/views/help/style-jump.html | 4 + sites/all/modules/views/help/views.help.ini | 8 + sites/all/modules/views/includes/admin.inc | 74 +++-- sites/all/modules/views/includes/handlers.inc | 38 ++- sites/all/modules/views/includes/plugins.inc | 15 +- sites/all/modules/views/includes/view.inc | 272 +++++++++++------- sites/all/modules/views/js/ajax_view.js | 15 +- sites/all/modules/views/js/views-admin.js | 14 +- ...ndler_argument_aggregator_category_cid.inc | 2 + .../views_handler_argument_aggregator_fid.inc | 2 + .../views_handler_argument_aggregator_iid.inc | 2 + ...iews_handler_field_aggregator_category.inc | 2 + ...ws_handler_field_aggregator_title_link.inc | 2 + .../views_handler_field_aggregator_xss.inc | 6 +- ...handler_filter_aggregator_category_cid.inc | 2 + .../modules/views/modules/comment.views.inc | 4 + .../views/modules/comment.views_default.inc | 5 + ...iews_handler_argument_comment_user_uid.inc | 2 + .../comment/views_handler_field_comment.inc | 4 +- .../views_handler_field_comment_depth.inc | 7 +- .../views_handler_field_comment_link.inc | 11 +- ...ews_handler_field_comment_link_approve.inc | 6 +- ...iews_handler_field_comment_link_delete.inc | 2 + .../views_handler_field_comment_link_edit.inc | 11 +- ...views_handler_field_comment_link_reply.inc | 2 + .../views_handler_field_comment_node_link.inc | 11 +- .../views_handler_field_comment_username.inc | 4 +- ...s_handler_field_last_comment_timestamp.inc | 5 + ...ws_handler_field_ncs_last_comment_name.inc | 4 +- .../views_handler_field_ncs_last_updated.inc | 4 +- .../views_handler_field_node_comment.inc | 4 +- .../views_handler_field_node_new_comments.inc | 4 +- .../views_handler_filter_comment_user_uid.inc | 4 +- .../views_handler_filter_ncs_last_updated.inc | 2 + .../views_handler_filter_node_comment.inc | 2 + ...ews_handler_sort_ncs_last_comment_name.inc | 4 +- .../views_handler_sort_ncs_last_updated.inc | 4 +- .../comment/views_plugin_row_comment_rss.inc | 49 +++- .../views_handler_field_contact_link.inc | 39 +-- .../all/modules/views/modules/field.views.inc | 6 + .../views_handler_argument_field_list.inc | 56 ++++ .../field/views_handler_field_field.inc | 32 ++- .../field/views_handler_filter_field_list.inc | 5 + ...ws_handler_relationship_entity_reverse.inc | 5 + ...views_handler_field_filter_format_name.inc | 2 + .../views_handler_argument_locale_group.inc | 2 + ...views_handler_argument_locale_language.inc | 2 + .../views_handler_field_locale_group.inc | 2 + .../views_handler_field_locale_language.inc | 2 + .../views_handler_field_locale_link_edit.inc | 2 + .../views_handler_filter_locale_group.inc | 2 + .../views_handler_filter_locale_language.inc | 2 + .../views_handler_filter_locale_version.inc | 2 + .../all/modules/views/modules/node.views.inc | 1 + .../views/modules/node.views_template.inc | 2 +- ...s_handler_field_history_user_timestamp.inc | 2 + .../modules/node/views_handler_field_node.inc | 4 +- .../node/views_handler_field_node_link.inc | 2 + .../views_handler_field_node_link_delete.inc | 2 + .../views_handler_field_node_link_edit.inc | 2 + .../node/views_handler_field_node_path.inc | 2 + .../views_handler_field_node_revision.inc | 6 +- ...andler_field_node_revision_link_delete.inc | 11 +- ...andler_field_node_revision_link_revert.inc | 11 +- .../node/views_handler_field_node_type.inc | 2 + ..._handler_filter_history_user_timestamp.inc | 2 + .../node/views_handler_filter_node_access.inc | 2 + .../node/views_handler_filter_node_status.inc | 4 +- .../node/views_handler_filter_node_type.inc | 2 + ...views_handler_filter_node_uid_revision.inc | 7 +- .../node/views_plugin_row_node_rss.inc | 42 ++- .../node/views_plugin_row_node_view.inc | 2 + .../views_handler_field_profile_date.inc | 2 + .../views_handler_field_profile_list.inc | 2 + ...views_handler_filter_profile_selection.inc | 2 + .../search/views_handler_argument_search.inc | 2 + .../views_handler_field_search_score.inc | 2 + .../search/views_handler_filter_search.inc | 2 + .../views_handler_sort_search_score.inc | 2 + .../views_handler_field_accesslog_path.inc | 2 + .../modules/views/modules/system.views.inc | 2 +- .../views_handler_argument_file_fid.inc | 2 + .../system/views_handler_field_file.inc | 2 + .../views_handler_field_file_extension.inc | 4 +- .../views_handler_field_file_filemime.inc | 2 + .../views_handler_field_file_status.inc | 2 + .../views_handler_filter_file_status.inc | 4 +- .../modules/views/modules/taxonomy.views.inc | 3 + .../views_handler_argument_taxonomy.inc | 2 + .../views_handler_argument_term_node_tid.inc | 4 +- ...s_handler_argument_term_node_tid_depth.inc | 4 +- ..._argument_term_node_tid_depth_modifier.inc | 4 +- ...ndler_argument_vocabulary_machine_name.inc | 2 + .../views_handler_argument_vocabulary_vid.inc | 2 + .../taxonomy/views_handler_field_taxonomy.inc | 2 + .../views_handler_field_term_link_edit.inc | 4 +- .../views_handler_field_term_node_tid.inc | 3 +- .../views_handler_filter_term_node_tid.inc | 29 +- ...ews_handler_filter_term_node_tid_depth.inc | 6 +- ...handler_filter_vocabulary_machine_name.inc | 4 +- .../views_handler_filter_vocabulary_vid.inc | 4 +- ...ws_handler_relationship_node_term_data.inc | 6 + .../views_handler_argument_node_tnid.inc | 2 + .../views_handler_field_node_language.inc | 2 + ...iews_handler_field_node_link_translate.inc | 15 +- ...ws_handler_field_node_translation_link.inc | 2 + .../views_handler_filter_node_language.inc | 4 +- .../views_handler_filter_node_tnid.inc | 2 + .../views_handler_filter_node_tnid_child.inc | 2 + ...views_handler_relationship_translation.inc | 2 + .../all/modules/views/modules/user.views.inc | 24 ++ .../user/views_handler_argument_user_uid.inc | 5 + ...views_handler_argument_users_roles_rid.inc | 4 +- .../modules/user/views_handler_field_user.inc | 2 + .../views_handler_field_user_language.inc | 7 +- .../user/views_handler_field_user_link.inc | 2 + .../views_handler_field_user_link_cancel.inc | 2 + .../views_handler_field_user_link_edit.inc | 2 + .../user/views_handler_field_user_mail.inc | 4 +- .../user/views_handler_field_user_name.inc | 4 +- .../views_handler_field_user_permissions.inc | 2 + .../user/views_handler_field_user_picture.inc | 18 +- .../user/views_handler_field_user_roles.inc | 2 + .../views_handler_filter_user_current.inc | 4 +- .../user/views_handler_filter_user_name.inc | 4 +- .../views_handler_filter_user_permissions.inc | 4 +- .../user/views_handler_filter_user_roles.inc | 14 +- .../user/views_plugin_row_user_view.inc | 81 ++++++ .../all/modules/views/modules/views.views.inc | 18 ++ .../plugins/export_ui/views_ui.class.php | 4 +- .../views/plugins/views_plugin_cache.inc | 18 +- .../views/plugins/views_plugin_display.inc | 48 +++- .../plugins/views_plugin_display_page.inc | 14 + .../views/plugins/views_plugin_pager.inc | 5 + .../views/plugins/views_plugin_pager_full.inc | 10 + .../views/plugins/views_plugin_query.inc | 12 + .../plugins/views_plugin_query_default.inc | 42 ++- .../views/plugins/views_plugin_style.inc | 250 +++++++++++----- .../views/plugins/views_plugin_style_rss.inc | 2 +- .../plugins/views_plugin_style_summary.inc | 1 - .../views_plugin_style_summary_jump_menu.inc | 1 - .../plugins/views_plugin_style_table.inc | 24 +- .../views_ui_base_views_wizard.class.php | 2 +- .../handlers/views_handler_area_text.test | 7 +- .../tests/handlers/views_handler_field.test | 115 ++++++++ .../handlers/views_handler_field_boolean.test | 5 + .../handlers/views_handler_filter_string.test | 7 +- .../handlers/views_handler_sort_date.test | 161 +++++++++-- .../tests/styles/views_plugin_style.test | 134 ++++++++- .../user/views_handler_field_user_name.test | 92 ++++++ .../modules/views/tests/user/views_user.test | 3 + .../user/views_user_argument_validate.test | 1 - .../all/modules/views/tests/views_cache.test | 2 - .../modules/views/tests/views_groupby.test | 30 +- .../modules/views/tests/views_handlers.test | 11 +- .../all/modules/views/tests/views_module.test | 8 +- .../all/modules/views/tests/views_pager.test | 12 +- .../all/modules/views/tests/views_query.test | 5 + sites/all/modules/views/tests/views_test.info | 6 +- .../all/modules/views/tests/views_test.module | 2 +- .../views/tests/views_translatable.test | 2 - sites/all/modules/views/tests/views_ui.test | 14 + .../modules/views/tests/views_upgrade.test | 11 +- sites/all/modules/views/theme/theme.inc | 80 ++++-- .../views/theme/views-view-grouping.tpl.php | 22 ++ .../views/theme/views-view-table.tpl.php | 20 +- sites/all/modules/views/views.info | 16 +- sites/all/modules/views/views.install | 30 +- sites/all/modules/views/views.module | 61 +++- sites/all/modules/views/views_ui.info | 6 +- 215 files changed, 2664 insertions(+), 557 deletions(-) create mode 100644 sites/all/modules/views/handlers/views_handler_area_result.inc create mode 100644 sites/all/modules/views/handlers/views_handler_field_contextual_links.inc create mode 100644 sites/all/modules/views/handlers/views_handler_field_machine_name.inc create mode 100644 sites/all/modules/views/help/aggregation.html create mode 100644 sites/all/modules/views/help/group-by.html create mode 100644 sites/all/modules/views/help/images/views3-group-aggregation-types.png create mode 100644 sites/all/modules/views/help/images/views3-group-aggregation.png create mode 100644 sites/all/modules/views/help/images/views3-jump-style-menu.png create mode 100644 sites/all/modules/views/modules/field/views_handler_argument_field_list.inc create mode 100644 sites/all/modules/views/modules/user/views_plugin_row_user_view.inc create mode 100644 sites/all/modules/views/tests/handlers/views_handler_field.test create mode 100644 sites/all/modules/views/tests/user/views_handler_field_user_name.test create mode 100644 sites/all/modules/views/theme/views-view-grouping.tpl.php diff --git a/sites/all/modules/views/README.txt b/sites/all/modules/views/README.txt index 21278fc22..8097eb453 100644 --- a/sites/all/modules/views/README.txt +++ b/sites/all/modules/views/README.txt @@ -15,7 +15,5 @@ Navigate to administer >> build >> modules. Enable Views and Views UI. If you're new to Views, try the Simple Views module which can create some often used Views for you, this might save you some time. -Recommended modules for use with Views: - Voting API - Views Bonus Pack - Views Bulk Operations +Here you can find many modules extending the functionality of Views: + http://drupal.org/taxonomy/term/89 diff --git a/sites/all/modules/views/docs/views.api.php b/sites/all/modules/views/docs/views.api.php index 5dae945b1..d99ecc4a5 100644 --- a/sites/all/modules/views/docs/views.api.php +++ b/sites/all/modules/views/docs/views.api.php @@ -277,7 +277,7 @@ function hook_views_plugins_alter(&$plugins) { */ function hook_views_api() { return array( - 'api' => 2, + 'api' => 3, 'path' => drupal_get_path('module', 'example') . '/includes/views', 'template path' => drupal_get_path('module', 'example') . 'themes', ); @@ -742,6 +742,20 @@ function hook_views_ui_display_top_links_alter(&$links, $view, $display_id) { // example code here } +/** + * This hook allows to alter the commands which are used on a views ajax + * request. + * + * @param $commands + * An array of ajax commands + * @param $view view + * The view which is requested. + */ +function hook_views_ajax_data_alter(&$commands, $view) { +} + + + /** * @} */ diff --git a/sites/all/modules/views/drush/views.drush.inc b/sites/all/modules/views/drush/views.drush.inc index 569cf6dcb..4116d30ab 100644 --- a/sites/all/modules/views/drush/views.drush.inc +++ b/sites/all/modules/views/drush/views.drush.inc @@ -243,6 +243,7 @@ function views_development_settings() { variable_set('views_show_additional_queries', TRUE); variable_set('views_devel_output', TRUE); variable_set('views_devel_region', 'message'); + variable_set('views_ui_display_embed', TRUE); $message = dt("Setup the new views settings."); drush_log($message, 'success'); } diff --git a/sites/all/modules/views/handlers/views_handler_area.inc b/sites/all/modules/views/handlers/views_handler_area.inc index d0a9e0c84..295e14db6 100644 --- a/sites/all/modules/views/handlers/views_handler_area.inc +++ b/sites/all/modules/views/handlers/views_handler_area.inc @@ -84,6 +84,8 @@ class views_handler_area extends views_handler { /** * A special handler to take the place of missing or broken handlers. + * + * @ingroup views_area_handlers */ class views_handler_area_broken extends views_handler_area { function ui_name($short = FALSE) { diff --git a/sites/all/modules/views/handlers/views_handler_area_result.inc b/sites/all/modules/views/handlers/views_handler_area_result.inc new file mode 100644 index 000000000..a52aa8c4d --- /dev/null +++ b/sites/all/modules/views/handlers/views_handler_area_result.inc @@ -0,0 +1,93 @@ +<?php + +/** + * @file + * Contains views_handler_area_result handler. + */ + +/** + * Views area handler to display some configurable result summary. + * + * @ingroup views_area_handlers Views' area handlers + */ +class views_handler_area_result extends views_handler_area { + + function option_definition() { + $options = parent::option_definition(); + + $options['content'] = array( + 'default' => 'Displaying @start - @end of @total', + 'translatable' => TRUE, + ); + + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $variables = array( + 'items' => array( + '@start -- the initial record number in the set', + '@end -- the last record number in the set', + '@total -- the total records in the set', + '@name -- the human-readable name of the view', + '@per_page -- the number of items per page', + '@current_page -- the current page number', + '@page_count -- the total page count', + ), + ); + $list = theme('item_list', $variables); + $form['content'] = array( + '#title' => t('Display'), + '#type' => 'textarea', + '#rows' => 3, + '#default_value' => $this->options['content'], + '#description' => t('You may use HTML code in this field. The following tokens are supported:') . $list, + ); + } + + + /** + * Find out the information to render. + */ + function render($empty = FALSE) { + // Must have options and does not work on summaries. + if (!isset($this->options['content']) || $this->view->plugin_name == 'default_summary') { + return; + } + $output = ''; + $format = $this->options['content']; + // Calculate the page totals. + $current_page = (int) $this->view->get_current_page() + 1; + $per_page = (int) $this->view->get_items_per_page(); + $count = count($this->view->result); + $total = $this->view->total_rows; + $name = check_plain($this->view->human_name); + if ($per_page === 0) { + $page_count = 1; + $start = 1; + $end = $total; + } + else { + $page_count = (int) ceil($total / $per_page); + $total_count = $current_page * $per_page; + if ($total_count > $total) { + $total_count = $total; + } + $start = ($current_page - 1) * $per_page + 1; + $end = $total_count; + } + // Get the search information. + $items = array('start', 'end', 'total', 'name', 'per_page', 'current_page', 'page_count'); + $replacements = array(); + foreach ($items as $item) { + $replacements["@$item"] = ${$item}; + } + // Send the output. + if (!empty($total)) { + $output .= filter_xss_admin(str_replace(array_keys($replacements), array_values($replacements), $format)); + } + return $output; + } +} + diff --git a/sites/all/modules/views/handlers/views_handler_area_text.inc b/sites/all/modules/views/handlers/views_handler_area_text.inc index 425d0a901..2b9adb366 100644 --- a/sites/all/modules/views/handlers/views_handler_area_text.inc +++ b/sites/all/modules/views/handlers/views_handler_area_text.inc @@ -1,14 +1,14 @@ <?php /** -* @file -* Views area text handler. -*/ + * @file + * Contains views_handler_area_text handler. + */ /** + * Views area text handler. * @ingroup views_area_handlers Views' area handlers */ - class views_handler_area_text extends views_handler_area { function option_definition() { diff --git a/sites/all/modules/views/handlers/views_handler_area_view.inc b/sites/all/modules/views/handlers/views_handler_area_view.inc index 7e79ee081..b8fad3f5e 100644 --- a/sites/all/modules/views/handlers/views_handler_area_view.inc +++ b/sites/all/modules/views/handlers/views_handler_area_view.inc @@ -2,7 +2,12 @@ /** * @file + * Contains views_handler_area_view handler. + */ +/** * Views area handlers. Insert a view inside of an area. + * + * @ingroup views_area_handlers */ class views_handler_area_view extends views_handler_area { diff --git a/sites/all/modules/views/handlers/views_handler_argument.inc b/sites/all/modules/views/handlers/views_handler_argument.inc index e58954298..72c07e222 100644 --- a/sites/all/modules/views/handlers/views_handler_argument.inc +++ b/sites/all/modules/views/handlers/views_handler_argument.inc @@ -30,8 +30,23 @@ * @ingroup views_argument_handlers */ class views_handler_argument extends views_handler { - var $name_field = NULL; var $validator = NULL; + var $argument = NULL; + var $value = NULL; + + /** + * The table to use for the name, should it not be in the same table as the argument. + * @var string + */ + var $name_table; + + /** + * The field to use for the name to use in the summary, which is + * the displayed output. For example, for the node: nid argument, + * the argument itself is the nid, but node.title is displayed. + * @var string + */ + var $name_field; /** * Constructor @@ -446,6 +461,12 @@ class views_handler_argument extends views_handler { // Copy the now submitted options to their final resting place so they get saved. $form_state['values']['options']['validate_options'] = $options; } + + // Clear out the content of title if it's not enabled. + $options =& $form_state['values']['options']; + if (empty($options['title_enable'])) { + $options['title'] = ''; + } } /** @@ -467,6 +488,7 @@ class views_handler_argument extends views_handler { 'form method' => 'default_argument_form', 'has default argument' => TRUE, 'default only' => TRUE, // this can only be used for missing argument, not validation failure + 'breadcrumb' => TRUE, // generate a breadcrumb to here ), 'not found' => array( 'title' => t('Hide view'), @@ -568,7 +590,7 @@ class views_handler_argument extends views_handler { $summary_plugins = array(); $format_options = array(); foreach ($style_plugins as $key => $plugin) { - if ($plugin['type'] == 'summary') { + if (isset($plugin['type']) && $plugin['type'] == 'summary') { $summary_plugins[$key] = $plugin; $format_options[$key] = $plugin['title']; } diff --git a/sites/all/modules/views/handlers/views_handler_argument_group_by_numeric.inc b/sites/all/modules/views/handlers/views_handler_argument_group_by_numeric.inc index d44af1245..2ecccaf97 100644 --- a/sites/all/modules/views/handlers/views_handler_argument_group_by_numeric.inc +++ b/sites/all/modules/views/handlers/views_handler_argument_group_by_numeric.inc @@ -2,13 +2,16 @@ /** * Simple handler for arguments using group by. + * + * @ingroup views_argument_handlers */ class views_handler_argument_group_by_numeric extends views_handler_argument { function query($group_by = FALSE) { $this->ensure_my_table(); $field = $this->get_field(); + $placeholder = $this->placeholder(); - $this->query->add_having(0, $field, $this->argument); + $this->query->add_having_expression(0, "$field = $placeholder", array($placeholder => $this->argument)); } function ui_name($short = FALSE) { diff --git a/sites/all/modules/views/handlers/views_handler_argument_null.inc b/sites/all/modules/views/handlers/views_handler_argument_null.inc index 591403113..e4804dc08 100644 --- a/sites/all/modules/views/handlers/views_handler_argument_null.inc +++ b/sites/all/modules/views/handlers/views_handler_argument_null.inc @@ -1,6 +1,8 @@ <?php /** * Argument handler that ignores the argument. + * + * @ingroup views_argument_handlers */ class views_handler_argument_null extends views_handler_argument { function option_definition() { diff --git a/sites/all/modules/views/handlers/views_handler_argument_numeric.inc b/sites/all/modules/views/handlers/views_handler_argument_numeric.inc index d8f813c78..5b91232f3 100644 --- a/sites/all/modules/views/handlers/views_handler_argument_numeric.inc +++ b/sites/all/modules/views/handlers/views_handler_argument_numeric.inc @@ -11,6 +11,18 @@ * @ingroup views_argument_handlers */ class views_handler_argument_numeric extends views_handler_argument { + /** + * The operator used for the query: or|and. + * @var string + */ + var $operator; + + /** + * The actual value which is used for querying. + * @var array + */ + var $value; + function option_definition() { $options = parent::option_definition(); @@ -67,6 +79,8 @@ class views_handler_argument_numeric extends views_handler_argument { /** * Override for specific title lookups. + * @return array + * Returns all titles, if it's just one title it's an array with one entry. */ function title_query() { return $this->value; diff --git a/sites/all/modules/views/handlers/views_handler_field.inc b/sites/all/modules/views/handlers/views_handler_field.inc index 7fa9d3ecf..ff2c32d01 100644 --- a/sites/all/modules/views/handlers/views_handler_field.inc +++ b/sites/all/modules/views/handlers/views_handler_field.inc @@ -6,6 +6,23 @@ * */ +/** + * Indicator of the render_text() mehtod for rendering a single item. + * (If no render_item() is present). + */ +define('VIEWS_HANDLER_RENDER_TEXT_PHASE_SINGLE_ITEM', 0); + +/** + * Indicator of the render_text() method for rendering the whole element. + * (if no render_item() method is available). + */ +define('VIEWS_HANDLER_RENDER_TEXT_PHASE_COMPLETELY', 1); + +/** + * Indicator of the render_text() method for rendering the empty text. + */ +define('VIEWS_HANDLER_RENDER_TEXT_PHASE_EMPTY', 2); + /** * Base field handler that has no options and renders an unformatted field. * @@ -331,6 +348,9 @@ class views_handler_field extends views_handler { /** * Get the value that's supposed to be rendered. * + * This api exists so that other modules can easy set the values of the field + * without having the need to change the render method as well. + * * @param $values * An object containing all retrieved values. * @param $field @@ -369,6 +389,9 @@ class views_handler_field extends views_handler { 'max_length' => array('default' => ''), 'word_boundary' => array('default' => TRUE), 'ellipsis' => array('default' => TRUE), + 'more_link' => array('default' => FALSE), + 'more_link_text' => array('default' => '', 'translatable' => TRUE), + 'more_link_path' => array('default' => ''), 'strip_tags' => array('default' => FALSE), 'trim' => array('default' => FALSE), 'preserve_tags' => array('default' => ''), @@ -788,6 +811,7 @@ If you would like to have the characters %5B and %5D please use the html entity '#dependency' => array( 'edit-options-alter-make-link' => array(1), 'edit-options-alter-alter-text' => array(1), + 'edit-options-alter-more-link' => array(1), ), ); @@ -828,6 +852,39 @@ If you would like to have the characters %5B and %5D please use the html entity ), ); + $form['alter']['more_link'] = array( + '#type' => 'checkbox', + '#title' => t('Add a read-more link if output is trimmed.'), + '#description' => t('If checked, a read-more link will be added at the end of the trimmed output'), + '#default_value' => $this->options['alter']['more_link'], + '#dependency' => array( + 'edit-options-alter-trim' => array(1), + ), + ); + + $form['alter']['more_link_text'] = array( + '#type' => 'textfield', + '#title' => t('More link text'), + '#default_value' => $this->options['alter']['more_link_text'], + '#description' => t('The text which will be displayed on the more link. You may enter data from this view as per the "Replacement patterns" above.'), + '#dependency_count' => 2, + '#dependency' => array( + 'edit-options-alter-trim' => array(1), + 'edit-options-alter-more-link' => array(1), + ), + ); + $form['alter']['more_link_path'] = array( + '#type' => 'textfield', + '#title' => t('More link path'), + '#default_value' => $this->options['alter']['more_link_path'], + '#description' => t('The path which is used for the more link. You may enter data from this view as per the "Replacement patterns" above.'), + '#dependency_count' => 2, + '#dependency' => array( + 'edit-options-alter-trim' => array(1), + 'edit-options-alter-more-link' => array(1), + ), + ); + $form['alter']['html'] = array( '#type' => 'checkbox', '#title' => t('Field can contain HTML'), @@ -844,12 +901,7 @@ If you would like to have the characters %5B and %5D please use the html entity '#description' => t('If checked, all HTML tags will be stripped.'), '#default_value' => $this->options['alter']['strip_tags'], ); - $form['alter']['trim_whitespace'] = array( - '#type' => 'checkbox', - '#title' => t('Remove whitespace'), - '#description' => t('If checked, all whitespaces at the beginning and the end of the output will be removed.'), - '#default_value' => $this->options['alter']['trim_whitespace'], - ); + $form['alter']['preserve_tags'] = array( '#type' => 'textfield', '#title' => t('Preserve certain tags'), @@ -860,6 +912,13 @@ If you would like to have the characters %5B and %5D please use the html entity ), ); + $form['alter']['trim_whitespace'] = array( + '#type' => 'checkbox', + '#title' => t('Remove whitespace'), + '#description' => t('If checked, all whitespaces at the beginning and the end of the output will be removed.'), + '#default_value' => $this->options['alter']['trim_whitespace'], + ); + $form['alter']['nl2br'] = array( '#type' => 'checkbox', '#title' => t('Convert newlines to HTML <br> tags'), @@ -970,13 +1029,15 @@ If you would like to have the characters %5B and %5D please use the html entity $this->original_value = $this->last_render; $alter = $item + $this->options['alter']; + $alter['phase'] = VIEWS_HANDLER_RENDER_TEXT_PHASE_SINGLE_ITEM; $items[] = $this->render_text($alter); } $value = $this->render_items($items); } else { - $value = $this->render_text($this->options['alter']); + $alter = array('phase' => VIEWS_HANDLER_RENDER_TEXT_PHASE_COMPLETELY) + $this->options['alter']; + $value = $this->render_text($alter); } if (is_array($value)) { @@ -992,6 +1053,7 @@ If you would like to have the characters %5B and %5D please use the html entity $alter = $this->options['alter']; $alter['alter_text'] = 1; $alter['text'] = $this->options['empty']; + $alter['phase'] = VIEWS_HANDLER_RENDER_TEXT_PHASE_EMPTY; $this->last_render = $this->render_text($alter); } } @@ -1007,30 +1069,67 @@ If you would like to have the characters %5B and %5D please use the html entity */ function render_text($alter) { $value = $this->last_render; - if (!empty($this->options['alter']['trim_whitespace'])) { - $value = trim($value); - } if (!empty($alter['alter_text']) && $alter['text'] !== '') { $tokens = $this->get_render_tokens($alter); $value = $this->render_altered($alter, $tokens); } - if ((($this->options['hide_empty'] && empty($value)) || ($this->options['hide_alter_empty'] && empty($this->original_value))) && ($value !== 0 || $this->options['empty_zero'])) { + if (!empty($this->options['alter']['trim_whitespace'])) { + $value = trim($value); + } + + // Check if there should be no further rewrite for empty values. + $no_rewrite_for_empty = $this->options['hide_alter_empty'] && empty($this->original_value); + + // Check whether the value is empty and return nothing, so the field isn't rendered. + // First check whether the field should be hidden if the value(hide_alter_empty = TRUE) /the rewrite is empty (hide_alter_empty = FALSE). + // For numeric values you can specify whether "0"/0 should be empty. + if ((($this->options['hide_empty'] && empty($value)) + || ($alter['phase'] != VIEWS_HANDLER_RENDER_TEXT_PHASE_EMPTY && $no_rewrite_for_empty)) + && (($value !== 0 && $value !== '0') + || $this->options['empty_zero'])) { return ''; } + // Only in empty phase. + if ($alter['phase'] == VIEWS_HANDLER_RENDER_TEXT_PHASE_EMPTY && $no_rewrite_for_empty) { + // If we got here then $alter contains the value of "No results text" + // and so there is nothing left to do. + return $value; + } if (!empty($alter['strip_tags'])) { $value = strip_tags($value, $alter['preserve_tags']); } + $suffix = ''; if (!empty($alter['trim']) && !empty($alter['max_length'])) { + $length = strlen($value); $value = $this->render_trim_text($alter, $value); + if ($this->options['alter']['more_link'] && strlen($value) < $length) { + $tokens = $this->get_render_tokens($alter); + $more_link_text = $this->options['alter']['more_link_text'] ? $this->options['alter']['more_link_text'] : t('more'); + $more_link_text = strtr(filter_xss_admin($more_link_text), $tokens); + $more_link_path = $this->options['alter']['more_link_path']; + $more_link_path = strip_tags(decode_entities(strtr($more_link_path, $tokens))); + + // Take sure that paths which was runned through url() does work as well. + $base_path = base_path(); + // Checks whether the path starts with the base_path. + if (strpos($more_link_path, $base_path) === 0) { + $more_link_path = drupal_substr($more_link_path, drupal_strlen($base_path)); + } + + $more_link = l($more_link_text, $more_link_path); + + $suffix .= " " . $more_link; + } } if (!empty($alter['nl2br'])) { $value = nl2br($value); } + $this->last_render_text = $value; if (!empty($alter['make_link']) && !empty($alter['path'])) { if (!isset($tokens)) { @@ -1039,7 +1138,7 @@ If you would like to have the characters %5B and %5D please use the html entity $value = $this->render_as_link($alter, $value, $tokens); } - return $value; + return $value . $suffix; } /** @@ -1324,6 +1423,8 @@ If you would like to have the characters %5B and %5D please use the html entity /** * A special handler to take the place of missing or broken handlers. + * + * @ingroup views_field_handlers */ class views_handler_field_broken extends views_handler_field { function ui_name($short = FALSE) { @@ -1346,6 +1447,8 @@ class views_handler_field_broken extends views_handler_field { /** * Render a numeric value as a size. + * + * @ingroup views_field_handlers */ class views_handler_field_file_size extends views_handler_field { function option_definition() { @@ -1386,7 +1489,9 @@ class views_handler_field_file_size extends views_handler_field { } /** - * A handler to run a field through simple XSS filtering + * A handler to run a field through simple XSS filtering. + * + * @ingroup views_field_handlers */ class views_handler_field_xss extends views_handler_field { function render($values) { diff --git a/sites/all/modules/views/handlers/views_handler_field_boolean.inc b/sites/all/modules/views/handlers/views_handler_field_boolean.inc index 5b50af1af..c388d4f95 100644 --- a/sites/all/modules/views/handlers/views_handler_field_boolean.inc +++ b/sites/all/modules/views/handlers/views_handler_field_boolean.inc @@ -33,6 +33,7 @@ class views_handler_field_boolean extends views_handler_field { 'true-false' => array(t('True'), t('False')), 'on-off' => array(t('On'), t('Off')), 'enabled-disabled' => array(t('Enabled'), t('Disabled')), + 'unicode-yes-no' => array('✔', '✖'), ); $output_formats = isset($this->definition['output formats']) ? $this->definition['output formats'] : array(); $this->formats = array_merge($default_formats, $output_formats); diff --git a/sites/all/modules/views/handlers/views_handler_field_contextual_links.inc b/sites/all/modules/views/handlers/views_handler_field_contextual_links.inc new file mode 100644 index 000000000..a55ac583e --- /dev/null +++ b/sites/all/modules/views/handlers/views_handler_field_contextual_links.inc @@ -0,0 +1,87 @@ +<?php + +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' => 1); + + 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' => 'select', + '#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.'), + '#options' => array( + '0' => t('No'), + '1' => t('Yes'), + ), + '#default_value' => $this->options['destination'], + ); + } + + function pre_render(&$values) { + // Add a row plugin css class for the contextual link. + $class = 'contextual-links-region'; + if (!empty($this->view->style_plugin->options['row_class'])) { + $this->view->style_plugin->options['row_class'] .= " $class"; + } + else { + $this->view->style_plugin->options['row_class'] = $class; + } + } + + /** + * Render the contextual fields. + */ + function render($values) { + $links = array(); + foreach ($this->options['fields'] as $field) { + if (empty($this->view->field[$field]->last_render_text)) { + 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)) { + $links[$field] = array( + 'href' => $path, + 'title' => $title, + ); + if (!empty($this->options['destination'])) { + $links[$field]['query'] = drupal_get_destination(); + } + } + } + $build = array( + '#prefix' => '<div class="contextual-links-wrapper">', + '#suffix' => '</div>', + '#theme' => 'links__contextual', + '#links' => $links, + '#attributes' => array('class' => array('contextual-links')), + '#attached' => array( + 'library' => array(array('contextual', 'contextual-links')), + ), + '#access' => user_access('access contextual links'), + ); + + return drupal_render($build); + } + + function query() { } +} diff --git a/sites/all/modules/views/handlers/views_handler_field_counter.inc b/sites/all/modules/views/handlers/views_handler_field_counter.inc index bd0db1d8a..d4e52fc3c 100644 --- a/sites/all/modules/views/handlers/views_handler_field_counter.inc +++ b/sites/all/modules/views/handlers/views_handler_field_counter.inc @@ -1,5 +1,10 @@ <?php +/** + * Field handler to show a counter of the current row. + * + * @ingroup views_field_handlers + */ class views_handler_field_counter extends views_handler_field { function option_definition() { $options = parent::option_definition(); diff --git a/sites/all/modules/views/handlers/views_handler_field_entity.inc b/sites/all/modules/views/handlers/views_handler_field_entity.inc index 259a45fc3..0e13b2325 100644 --- a/sites/all/modules/views/handlers/views_handler_field_entity.inc +++ b/sites/all/modules/views/handlers/views_handler_field_entity.inc @@ -62,6 +62,8 @@ class views_handler_field_entity extends views_handler_field { if (method_exists($this->query, 'add_field')) { $this->field_alias = $this->query->add_field($this->table_alias, $this->base_field, ''); } + + $this->add_additional_fields(); } /** @@ -74,9 +76,23 @@ class views_handler_field_entity extends views_handler_field { } /** - * Overridden to return the entity object. + * Overridden to return the entity object, or a certain property of the entity. */ function get_value($values, $field = NULL) { - return isset($this->entities[$this->view->row_index]) ? $this->entities[$this->view->row_index] : FALSE; + if (isset($this->entities[$this->view->row_index])) { + $entity = $this->entities[$this->view->row_index]; + // Support to get a certain part of the entity. + if (isset($field) && isset($entity->{$field})) { + return $entity->{$field}; + } + // Support to get a part of the values as the normal get_value. + elseif (isset($field) && isset($values->{$this->aliases[$field]})) { + return $values->{$this->aliases[$field]}; + } + else { + return $entity; + } + } + return FALSE; } } diff --git a/sites/all/modules/views/handlers/views_handler_field_machine_name.inc b/sites/all/modules/views/handlers/views_handler_field_machine_name.inc new file mode 100644 index 000000000..96a0cf7d8 --- /dev/null +++ b/sites/all/modules/views/handlers/views_handler_field_machine_name.inc @@ -0,0 +1,68 @@ +<?php + +/** + * Field handler whichs allows to show machine name content as human name. + * @ingroup views_field_handlers + * + * Definition items: + * - options callback: The function to call in order to generate the value options. If omitted, the options 'Yes' and 'No' will be used. + * - options arguments: An array of arguments to pass to the options callback. + */ +class views_handler_field_machine_name extends views_handler_field { + /** + * @var array Stores the available options. + */ + var $value_options; + + function get_value_options() { + if (isset($this->value_options)) { + return; + } + + if (isset($this->definition['options callback']) && is_callable($this->definition['options callback'])) { + if (isset($this->definition['options arguments']) && is_array($this->definition['options arguments'])) { + $this->value_options = call_user_func_array($this->definition['options callback'], $this->definition['options arguments']); + } + else { + $this->value_options = call_user_func($this->definition['options callback']); + } + } + else { + $this->value_options = array(); + } + } + + function option_definition() { + $options = parent::option_definition(); + $options['machine_name'] = array('default' => FALSE); + + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + $form['machine_name'] = array( + '#title' => t('Output machine name'), + '#description' => t('Display field as machine name.'), + '#type' => 'checkbox', + '#default_value' => !empty($this->options['machine_name']), + ); + } + + function pre_render(&$values) { + $this->get_value_options(); + } + + function render($values) { + $value = $values->{$this->field_alias}; + if (!empty($this->options['machine_name']) || !isset($this->value_options[$value])) { + $result = check_plain($value); + } + else { + $result = $this->value_options[$value]; + } + + return $result; + } +} diff --git a/sites/all/modules/views/handlers/views_handler_field_prerender_list.inc b/sites/all/modules/views/handlers/views_handler_field_prerender_list.inc index 98ac30ffa..16b30b6ac 100644 --- a/sites/all/modules/views/handlers/views_handler_field_prerender_list.inc +++ b/sites/all/modules/views/handlers/views_handler_field_prerender_list.inc @@ -11,6 +11,16 @@ * @ingroup views_field_handlers */ class views_handler_field_prerender_list extends views_handler_field { + /** + * Stores all items which are used to render the items. + * It should be keyed first by the id of the base table, for example nid. + * The second key is the id of the thing which is displayed multiple times + * per row, for example the tid. + * + * @var array + */ + var $items = array(); + function option_definition() { $options = parent::option_definition(); diff --git a/sites/all/modules/views/handlers/views_handler_field_serialized.inc b/sites/all/modules/views/handlers/views_handler_field_serialized.inc index d53c1477d..01dd0c067 100644 --- a/sites/all/modules/views/handlers/views_handler_field_serialized.inc +++ b/sites/all/modules/views/handlers/views_handler_field_serialized.inc @@ -1,5 +1,10 @@ <?php +/** + * Field handler to show data of serialized fields. + * + * @ingroup views_field_handlers + */ class views_handler_field_serialized extends views_handler_field { function option_definition() { diff --git a/sites/all/modules/views/handlers/views_handler_filter.inc b/sites/all/modules/views/handlers/views_handler_filter.inc index 541e5df3d..b267976f6 100644 --- a/sites/all/modules/views/handlers/views_handler_filter.inc +++ b/sites/all/modules/views/handlers/views_handler_filter.inc @@ -24,6 +24,35 @@ * Base class for filters. */ class views_handler_filter extends views_handler { + /** + * Contains the actual value of the field,either configured in the views ui + * or entered in the exposed filters. + */ + var $value = NULL; + + /** + * Contains the operator which is used on the query. + */ + var $operator = '='; + + /** + * @var bool + * Disable the possibility to force a single value. + */ + var $always_multiple = FALSE; + + /** + * @var bool + * Disable the possibility to use operators. + */ + var $no_operator = FALSE; + + /** + * @var bool + * Disable the possibility to allow a exposed input to be optional. + */ + var $always_required = FALSE; + /** * Provide some extra help to get the operator/value easier to use. * @@ -60,7 +89,7 @@ class views_handler_filter extends views_handler { $options['operator'] = array('default' => '='); $options['value'] = array('default' => ''); - $options['group'] = array('default' => '0'); + $options['group'] = array('default' => '1'); $options['exposed'] = array('default' => FALSE); $options['expose'] = array( 'contains' => array( @@ -104,12 +133,15 @@ class views_handler_filter extends views_handler { $form['clear_markup_start'] = array( '#markup' => '<div class="clearfix">', ); + // Add the subform from operator_form(). $this->show_operator_form($form, $form_state); + // Add the subform from value_form(). $this->show_value_form($form, $form_state); $form['clear_markup_end'] = array( '#markup' => '</div>', ); if ($this->can_expose()) { + // Add the subform from expose_form(). $this->show_expose_form($form, $form_state); } } @@ -147,10 +179,12 @@ class views_handler_filter extends views_handler { } /** - * Provide a form for setting the operator. + * Options form subform for setting the operator. * * This may be overridden by child classes, and it must * define $form['operator']; + * + * @see options_form(). */ function operator_form(&$form, &$form_state) { $options = $this->operator_options(); @@ -193,10 +227,12 @@ class views_handler_filter extends views_handler { } /** - * Provide a form for setting options. + * Options form subform for setting options. * * This should be overridden by all child classes and it must * define $form['value'] + * + * @see options_form(). */ function value_form(&$form, &$form_state) { $form['value'] = array(); } @@ -260,6 +296,11 @@ class views_handler_filter extends views_handler { } } + /** + * Options form subform for exposed filter options. + * + * @see options_form(). + */ function expose_form(&$form, &$form_state) { $form['#theme'] = 'views_ui_expose_filter_form'; // #flatten will move everything from $form['expose'][$key] to $form[$key] @@ -470,7 +511,7 @@ class views_handler_filter extends views_handler { * Tell the renderer about our exposed form. This only needs to be * overridden for particularly complex forms. And maybe not even then. * - * @return + * @return array|null * An array with the following keys: * - operator: The $form key of the operator. Set to NULL if no operator. * - value: The $form key of the value. Set to NULL if no value. @@ -600,6 +641,8 @@ class views_handler_filter extends views_handler { * with OR groups. Some filters must also use HAVING which also makes * them not groupable. These filters will end up in a special group * if OR grouping is in use. + * + * @return bool */ function can_group() { return TRUE; @@ -609,6 +652,8 @@ class views_handler_filter extends views_handler { /** * A special handler to take the place of missing or broken handlers. + * + * @ingroup views_filter_handlers */ class views_handler_filter_broken extends views_handler_filter { function ui_name($short = FALSE) { diff --git a/sites/all/modules/views/handlers/views_handler_filter_boolean_operator.inc b/sites/all/modules/views/handlers/views_handler_filter_boolean_operator.inc index 5f8013e27..f795b9f84 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_boolean_operator.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_boolean_operator.inc @@ -10,6 +10,10 @@ * - on-off: On/Off * - enabled-disabled: Enabled/Disabled * - accept null: Treat a NULL value as false. + * - use equal: If you use this flag the query will use = 1 instead of <> 0. + * This might be helpful for performance reasons. + * + * @ingroup views_filter_handlers */ class views_handler_filter_boolean_operator extends views_handler_filter { // exposed filter options @@ -102,7 +106,7 @@ class views_handler_filter_boolean_operator extends views_handler_filter { $form_state['input'][$identifier] = $this->value; } // If we're configuring an exposed filter, add an <Any> option. - if (empty($form_state['exposed']) || empty($this->options['required'])) { + if (empty($form_state['exposed']) || empty($this->options['expose']['required'])) { $any_label = variable_get('views_exposed_filter_any_label', 'new_any') == 'old_any' ? '<Any>' : t('- Any -'); if ($form['value']['#type'] != 'select') { $any_label = check_plain($any_label); diff --git a/sites/all/modules/views/handlers/views_handler_filter_boolean_operator_string.inc b/sites/all/modules/views/handlers/views_handler_filter_boolean_operator_string.inc index bd7bd87ef..b27cae4f4 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_boolean_operator_string.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_boolean_operator_string.inc @@ -7,6 +7,8 @@ * * Definition items: * - label: (REQUIRED) The label for the checkbox. + * + * @ingroup views_filter_handlers */ class views_handler_filter_boolean_operator_string extends views_handler_filter_boolean_operator { function query() { diff --git a/sites/all/modules/views/handlers/views_handler_filter_date.inc b/sites/all/modules/views/handlers/views_handler_filter_date.inc index e95bc6230..b89d003d6 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_date.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_date.inc @@ -2,6 +2,8 @@ /** * Filter to handle dates stored as a timestamp. + * + * @ingroup views_filter_handlers */ class views_handler_filter_date extends views_handler_filter_numeric { function option_definition() { diff --git a/sites/all/modules/views/handlers/views_handler_filter_equality.inc b/sites/all/modules/views/handlers/views_handler_filter_equality.inc index a212eb6be..dfe244507 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_equality.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_equality.inc @@ -1,6 +1,8 @@ <?php /** * Simple filter to handle equal to / not equal to filters + * + * @ingroup views_filter_handlers */ class views_handler_filter_equality extends views_handler_filter { // exposed filter options diff --git a/sites/all/modules/views/handlers/views_handler_filter_group_by_numeric.inc b/sites/all/modules/views/handlers/views_handler_filter_group_by_numeric.inc index 60e5bced8..2332d3983 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_group_by_numeric.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_group_by_numeric.inc @@ -2,6 +2,8 @@ /** * Simple filter to handle greater than/less than filters + * + * @ingroup views_filter_handlers */ class views_handler_filter_group_by_numeric extends views_handler_filter_numeric { function query() { diff --git a/sites/all/modules/views/handlers/views_handler_filter_in_operator.inc b/sites/all/modules/views/handlers/views_handler_filter_in_operator.inc index 0426a7c3a..80545421e 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_in_operator.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_in_operator.inc @@ -6,6 +6,7 @@ * - options callback: The function to call in order to generate the value options. If omitted, the options 'Yes' and 'No' will be used. * - options arguments: An array of arguments to pass to the options callback. * + * @ingroup views_filter_handlers */ class views_handler_filter_in_operator extends views_handler_filter { var $value_form_type = 'checkboxes'; diff --git a/sites/all/modules/views/handlers/views_handler_filter_many_to_one.inc b/sites/all/modules/views/handlers/views_handler_filter_many_to_one.inc index 58fb0d0b0..c6d6d20db 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_many_to_one.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_many_to_one.inc @@ -7,8 +7,17 @@ * The construct method needs to be overridden to provide a list of options; * alternately, the value_form and admin_summary methods need to be overriden * to provide something that isn't just a select list. + * + * @ingroup views_filter_handlers */ class views_handler_filter_many_to_one extends views_handler_filter_in_operator { + /** + * @var views_many_to_one_helper + * + * Stores the Helper object which handles the many_to_one complexity. + */ + var $helper = NULL; + function init(&$view, &$options) { parent::init($view, $options); $this->helper = new views_many_to_one_helper($this); diff --git a/sites/all/modules/views/handlers/views_handler_filter_numeric.inc b/sites/all/modules/views/handlers/views_handler_filter_numeric.inc index 767654b86..71d8b9e30 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_numeric.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_numeric.inc @@ -2,6 +2,8 @@ /** * Simple filter to handle greater than/less than filters + * + * @ingroup views_filter_handlers */ class views_handler_filter_numeric extends views_handler_filter { var $always_multiple = TRUE; diff --git a/sites/all/modules/views/handlers/views_handler_filter_string.inc b/sites/all/modules/views/handlers/views_handler_filter_string.inc index d3bc60da5..eec7a07d4 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_string.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_string.inc @@ -3,6 +3,8 @@ /** * Basic textfield filter to handle string filtering commands * including equality, like, not like, etc. + * + * @ingroup views_filter_handlers */ class views_handler_filter_string extends views_handler_filter { // exposed filter options @@ -250,6 +252,11 @@ class views_handler_filter_string extends views_handler_filter { function op_word($field) { $where = $this->operator == 'word' ? db_or() : db_and(); + // Don't filter on empty strings. + if (empty($this->value)) { + return; + } + preg_match_all('/ (-?)("[^"]+"|[^" ]+)/i', ' ' . $this->value, $matches, PREG_SET_ORDER); foreach ($matches as $match) { $phrase = false; @@ -262,7 +269,7 @@ class views_handler_filter_string extends views_handler_filter { $words = $phrase ? array($words) : preg_split('/ /', $words, -1, PREG_SPLIT_NO_EMPTY); foreach ($words as $word) { $placeholder = $this->placeholder(); - $where->where("$field LIKE $placeholder", array($placeholder => '%' . db_like(trim($word, " ,!?")) . '%')); + $where->condition($field, '%' . db_like(trim($word, " ,!?")) . '%', 'LIKE'); } } diff --git a/sites/all/modules/views/handlers/views_handler_relationship.inc b/sites/all/modules/views/handlers/views_handler_relationship.inc index afeaba82d..18f21f88d 100644 --- a/sites/all/modules/views/handlers/views_handler_relationship.inc +++ b/sites/all/modules/views/handlers/views_handler_relationship.inc @@ -118,6 +118,10 @@ class views_handler_relationship extends views_handler { $def['type'] = 'INNER'; } + if (!empty($this->definition['extra'])) { + $def['extra'] = $this->definition['extra']; + } + if (!empty($def['join_handler']) && class_exists($def['join_handler'])) { $join = new $def['join_handler']; } @@ -152,6 +156,8 @@ class views_handler_relationship extends views_handler { /** * A special handler to take the place of missing or broken handlers. + * + * @ingroup views_relationship_handlers */ class views_handler_relationship_broken extends views_handler_relationship { function ui_name($short = FALSE) { diff --git a/sites/all/modules/views/handlers/views_handler_relationship_groupwise_max.inc b/sites/all/modules/views/handlers/views_handler_relationship_groupwise_max.inc index cdfd0bdc6..b02735772 100644 --- a/sites/all/modules/views/handlers/views_handler_relationship_groupwise_max.inc +++ b/sites/all/modules/views/handlers/views_handler_relationship_groupwise_max.inc @@ -50,6 +50,8 @@ * If your use of this relationship handler is likely to result in large * data sets, you might want to consider storing statistics in a separate table, * in the same way as node_comment_statistics. + * + * @ingroup views_relationship_handlers */ class views_handler_relationship_groupwise_max extends views_handler_relationship { @@ -190,10 +192,7 @@ class views_handler_relationship_groupwise_max extends views_handler_relationshi function left_query($options) { // Either load another view, or create one on the fly. if ($options['subquery_view']) { - // We don't use views_get_view because we want our own class of view. - views_include('view'); - $temp_view = view::load($options['subquery_view']); - + $temp_view = views_get_view($options['subquery_view']); // Remove all fields from default display unset($temp_view->display['default']->display_options['fields']); } diff --git a/sites/all/modules/views/handlers/views_handler_sort.inc b/sites/all/modules/views/handlers/views_handler_sort.inc index f767b9939..3587290e6 100644 --- a/sites/all/modules/views/handlers/views_handler_sort.inc +++ b/sites/all/modules/views/handlers/views_handler_sort.inc @@ -204,6 +204,8 @@ class views_handler_sort extends views_handler { /** * A special handler to take the place of missing or broken handlers. + * + * @ingroup views_sort_handlers */ class views_handler_sort_broken extends views_handler_sort { function ui_name($short = FALSE) { diff --git a/sites/all/modules/views/handlers/views_handler_sort_group_by_numeric.inc b/sites/all/modules/views/handlers/views_handler_sort_group_by_numeric.inc index 61b3409d4..1d1be4163 100644 --- a/sites/all/modules/views/handlers/views_handler_sort_group_by_numeric.inc +++ b/sites/all/modules/views/handlers/views_handler_sort_group_by_numeric.inc @@ -1,6 +1,8 @@ <?php /** * Handler for GROUP BY on simple numeric fields. + * + * @ingroup views_sort_handlers */ class views_handler_sort_group_by_numeric extends views_handler_sort { function init(&$view, &$options) { diff --git a/sites/all/modules/views/handlers/views_handler_sort_random.inc b/sites/all/modules/views/handlers/views_handler_sort_random.inc index 3b670cb9e..75f3153ef 100644 --- a/sites/all/modules/views/handlers/views_handler_sort_random.inc +++ b/sites/all/modules/views/handlers/views_handler_sort_random.inc @@ -2,6 +2,8 @@ /** * Handle a random sort. + * + * @ingroup views_sort_handlers */ class views_handler_sort_random extends views_handler_sort { function query() { diff --git a/sites/all/modules/views/help/about.html b/sites/all/modules/views/help/about.html index df0ad848d..fd0a57689 100644 --- a/sites/all/modules/views/help/about.html +++ b/sites/all/modules/views/help/about.html @@ -1,4 +1,6 @@ -The views module allows administrators and site designers to create, manage, and display lists of content. Each list managed by the views module is known as a "view", and the output of a view is known as a "display". Displays are provided in either block or page form, and a single view may have multiple displays. Optional navigation aids, including a system path and menu item, can be set for each page-based display of a view. By default, views may be created that list content (a <em>Node</em> view type), content revisions (a <em>Node revisions</em> view type) or users (a <em>User</em> view type). A view may be restricted to members of specific user roles, and may be added, edited or deleted at the <a href="base_url:admin/structure/views">views administration page</a> +The views module allows administrators and site designers to create, manage, and display lists of content. Each list managed by the views module is known as a "view", and the output of a view is known as a "display". Displays are provided in either block or page form, and a single view may have multiple displays. Optional navigation aids, including a system path and menu item, can be set for each page-based display of a view. By default, views may be created that list content (a <em>Node</em> view type), content revisions (a <em>Node revisions</em> view type) or users (a <em>User</em> view type). A view may be restricted to members of specific user roles, and may be added, edited or deleted at the <a href="base_url:admin/structure/views">views administration page</a>. + +For more technical users and in terms views can be understood simple as a user interface to compose SQL-queries and to pull information (Content, Users, etc.) from the database and show it on a screen as desired. The "building block" design of the views system provides power and flexibility, allowing parameters to be specified only when needed. While an advanced view may use all of available parameters to create complex and highly interactive applications, a simple content listing may specify only a few options. All views rely on a conceptual framework that includes: diff --git a/sites/all/modules/views/help/aggregation.html b/sites/all/modules/views/help/aggregation.html new file mode 100644 index 000000000..83ad880d8 --- /dev/null +++ b/sites/all/modules/views/help/aggregation.html @@ -0,0 +1 @@ +See: <a href="topic:views/group-by">Group by</a> diff --git a/sites/all/modules/views/help/api-forms.html b/sites/all/modules/views/help/api-forms.html index 749c56538..f7f4ff681 100644 --- a/sites/all/modules/views/help/api-forms.html +++ b/sites/all/modules/views/help/api-forms.html @@ -11,19 +11,31 @@ The views handler can also implement views_form_validate() and views_form_submit return '<!--form-item-' . $this->options['id'] . '--' . $this->view->row_index . '-->'; } + function form_element_name() { + // Make sure this value is unique for all the view fields + return $this->options['id']; + } + + function form_element_row_id($row_id) { + // You could use values from $this->view->result[$row_id] + // to provide complex row ids. + return $row_id; + } + function views_form(&$form, &$form_state) { // The view is empty, abort. if (empty($this->view->result)) { return; } - $field_name = $this->options['id']; + $field_name = $this->form_element_name(); $form[$field_name] = array( '#tree' => TRUE, ); // At this point, the query has already been run, so we can access the results foreach ($this->view->result as $row_id => $row) { - $form[$field_name][$row_id] = array( + $form_element_row_id = $this->form_element_row_id($row_id); + $form[$field_name][$form_element_row_id] = array( '#type' => 'textfield', '#title' => t('Your name'), '#default_value' => '', @@ -33,7 +45,7 @@ The views handler can also implement views_form_validate() and views_form_submit // Optional validate function. function views_form_validate($form, &$form_state) { - $field_name = $this->options['id']; + $field_name = $this->form_element_name(); foreach ($form_state['values'][$field_name] as $row_id => $value) { if ($value == 'Drupal') { form_set_error($field_name . '][' . $row_id, "You can't be named Drupal. That's my name."); diff --git a/sites/all/modules/views/help/api-handlers.html b/sites/all/modules/views/help/api-handlers.html index eda52ae6c..9eca851c8 100644 --- a/sites/all/modules/views/help/api-handlers.html +++ b/sites/all/modules/views/help/api-handlers.html @@ -32,6 +32,8 @@ Most handlers are just extensions of existing classes with a few tweaks that are <pre> /** * Filter by node type + * + * @ingroup views_filter_handlers */ class views_handler_filter_node_type extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/help/api-plugins.html b/sites/all/modules/views/help/api-plugins.html index 25fbffbe7..4d1c120d0 100644 --- a/sites/all/modules/views/help/api-plugins.html +++ b/sites/all/modules/views/help/api-plugins.html @@ -1,6 +1,6 @@ In Views, a plugin is a bit like a handler, but plugins are not directly responsible for building the query. Instead, they are objects that are used to display the view or make other modifications. -There are 6 types of plugins in Views: +There are 10 types of plugins in Views: <dl> <dt>Display</dt> <dd>Display plugins are responsible for controlling <strong>where</strong> a view lives. Page and block are the most common displays, as well as the ubiquitous 'default' display which is likely what will be embedded.</dd> @@ -14,9 +14,30 @@ There are 6 types of plugins in Views: <dd>Validator plugins can ensure arguments are valid, and even do transformations on the arguments.</dd> <dt>Access</dt> <dd>Access plugins are responsible for controlling access to the view.</dd> +<dt>Query</dt> +<dd>Query plugins generate and execute a query, it can be seen as a data backend. The default implementation +is using sql.</dd> +<dt>Cache</dt> +<dd>Cache plugins control the storage and loading of caches. Currently they can do both result and render caching, +but maybe one day cache the generated query</dd> +<dt>Pager plugins</dt> +<dd>Pager plugins take care of everything regarding pagers. From getting and setting the total amount of items +to render the pager and setting the global pager arrays.</dd> +<dt>Exposed form plugins</dt> +<dd>Exposed form plugins are responsible for building, rendering and controlling exposed forms. They can expose new +parts of the view to the user and more.</dd> +<dt>Localization plugins</dt> +<dd>Localization plugins take care how the view options are translated. There are example implementations +for t(), none translation and i18n.</dd> </dl> Plugins are registered by implementing <strong>hook_views_plugins()</strong> in your modulename.views.inc file and returning an array of data. +For examples please look at views_views_plugins() in views/includes/plugins.inc as it has examples +for all of them. + +For example plugins please look at the one provided by views, too. + +Similar to handlers take sure that you added the plugin file to the module.info. The array will look something like this: <pre> @@ -39,6 +60,21 @@ The array will look something like this: 'access' => array( // ... list of access plugins, ), + 'query' => array( + // ... list of query plugins, + ),, + 'cache' => array( + // ... list of cache plugins, + ),, + 'pager' => array( + // ... list of pager plugins, + ),, + 'exposed_form' => array( + // ... list of exposed_form plugins, + ),, + 'localization' => array( + // ... list of localization plugins, + ), ); </pre> diff --git a/sites/all/modules/views/help/group-by.html b/sites/all/modules/views/help/group-by.html new file mode 100644 index 000000000..d90ed62a9 --- /dev/null +++ b/sites/all/modules/views/help/group-by.html @@ -0,0 +1,17 @@ +This is another major new feature for Views that has been long requested. It incorporates another module that has seen a relatively wide amount of use: views_groupby. This feature provides multiple new options for manipulating data. First, it includes the important “group” SQL functionality, and then enables aggregation functions for Views, such as SUM and COUNT. +<div class="help-box" style="text-align:center"> +<a href="path:images/views3-group-aggregation.png"><img src="path:images/views3-group-aggregation.png" /></a> +<em>Where to set aggregation to get group settings</em> +</div> + +Grouping is available for sorts and filters. To use grouping, “Use grouping” must be enabled on a per-view basis in the Views UI. This is toggled in the Advanced settings box by clicking the link next to “Use grouping”. Once you activate this checkbox (be sure to read the notes in the UI!), functions for aggregating particular fields will become available. The gear icon that should be familiar to users with any amount of Views experience will now appear next to any sorted or filtered field with aggregation capabilities. Choosing that icon will open up the configuration for the aggregation functions. As an example, this could be used to count things like number of posts in a day, or number of published posts. This could also be used to sum the values of a row, instead of everything in the view. + +Setting only the "Use aggregation" turned on itself does nothing. It only gives the possibility to set Aggregation types. + +<div class="help-box" style="text-align:center"> +<a href="path:images/views3-group-aggregation-types.png"><img src="path:images/views3-group-aggregation-types.png" /></a> +<em>Different aggregation possibilities</em> +</div> + + +It should be noted that modules that are providing data to Views are responsible for noting whether a field supports aggregation or not; modules that do not provide this information may not have all of their fields available to Views if this data is not in place. diff --git a/sites/all/modules/views/help/images/views3-group-aggregation-types.png b/sites/all/modules/views/help/images/views3-group-aggregation-types.png new file mode 100644 index 0000000000000000000000000000000000000000..ac6f32fe598e484ba41d36268a5da21db0bb4732 GIT binary patch literal 16742 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 KpUXO@geCxxG!2~q literal 0 HcmV?d00001 diff --git a/sites/all/modules/views/help/images/views3-group-aggregation.png b/sites/all/modules/views/help/images/views3-group-aggregation.png new file mode 100644 index 0000000000000000000000000000000000000000..ef93bba66e1683101dc6f9f039f32ca7e8a9be3c GIT binary patch literal 55825 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 literal 0 HcmV?d00001 diff --git a/sites/all/modules/views/help/images/views3-jump-style-menu.png b/sites/all/modules/views/help/images/views3-jump-style-menu.png new file mode 100644 index 0000000000000000000000000000000000000000..6945b94efeb49026cbc2edf90ae2f8e9ca28952c GIT binary patch literal 40328 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 literal 0 HcmV?d00001 diff --git a/sites/all/modules/views/help/new.html b/sites/all/modules/views/help/new.html index 0951f3384..bee52e9f0 100644 --- a/sites/all/modules/views/help/new.html +++ b/sites/all/modules/views/help/new.html @@ -1,10 +1,10 @@ Views 3 is the newest major release of Views and is coded for Drupal 6. Views 3 retains all of the core functionality of previous releases, together with a completely revamped user interface and a large set of new features. - Major new features (these need help files): <ol> <li>Views Or has been incorporated.</li> <li><a href="topic:views/semantic-views">Semantic views</a> have been incorporated.</li> +<li><a href="topic:views/group-by">Group by</a> possibility.</li> <li>The Jump Menu style has been added.</li> <li>The Panel Fields style has been added.</li> <li>Pluggable back ends</li> diff --git a/sites/all/modules/views/help/reports.html b/sites/all/modules/views/help/reports.html index 2a585fab2..2a6087355 100644 --- a/sites/all/modules/views/help/reports.html +++ b/sites/all/modules/views/help/reports.html @@ -1,3 +1,3 @@ -Visit <a href="admin/reports/views-fields">admin/reports/views-fields</a> to see an overview of fields usage across all the views. +Visit <a href="/admin/reports/views-fields">admin/reports/views-fields</a> to see an overview of fields usage across all the views. It's useful to check for unused or misused fields. diff --git a/sites/all/modules/views/help/style-jump.html b/sites/all/modules/views/help/style-jump.html index a579b8b5c..d08e67fce 100644 --- a/sites/all/modules/views/help/style-jump.html +++ b/sites/all/modules/views/help/style-jump.html @@ -1,3 +1,7 @@ +With the <strong>jump menu</strong> style can you create selectbox menus for the content of your site. + +<a href="path:images/views3-jump-style-menu.png"><img src="path:images/views3-jump-style-menu.png" /></a> + The <strong>jump menu</strong> style will display each row of your view within a jump menu. This style requires that your view's <a href="topic:views/style-row">row style</a> is set to <a href="topic:views/style-fields">fields</a>. To properly configure a jump menu, you must select one field that will represent the path to utilize. In most cases, you will need to rewrite the output of this field. You should set that field to exclude from display. All other displayed fields will be part of the menu. Please note that all HTML will be stripped from this output as select boxes cannot show HTML. diff --git a/sites/all/modules/views/help/views.help.ini b/sites/all/modules/views/help/views.help.ini index e0a1d770a..4a249f5de 100644 --- a/sites/all/modules/views/help/views.help.ini +++ b/sites/all/modules/views/help/views.help.ini @@ -177,6 +177,10 @@ weight = 20 title = "Semantic Views" parent = style-settings +[group-by] +title = "Group by" +parent = field + [menu] title = "Menu options (page display)" parent = display-page @@ -209,6 +213,10 @@ weight = 80 title = "Relationships" weight = 90 +[aggregation] +title = "Aggregation" +weight = 90 + [argument] title = "Arguments/Contextual Filters" weight = 100 diff --git a/sites/all/modules/views/includes/admin.inc b/sites/all/modules/views/includes/admin.inc index 6ae420ebc..80aa592e5 100644 --- a/sites/all/modules/views/includes/admin.inc +++ b/sites/all/modules/views/includes/admin.inc @@ -311,7 +311,7 @@ function views_ui_add_form($form, &$form_state) { ); $form['name'] = array( '#type' => 'machine_name', - '#maxlength' => 32, + '#maxlength' => 128, '#machine_name' => array( 'exists' => 'views_get_view', 'source' => array('human_name'), @@ -743,7 +743,15 @@ function views_ui_add_form_store_edit_submit($form, &$form_state) { } // Just cache it temporarily to edit it. views_ui_cache_set($view); - $form_state['redirect'] = 'admin/structure/views/view/' . $view->name; + + // If there is a destination query, ensure we still redirect the user to the + // edit view page, and then redirect the user to the destination. + $destination = array(); + if (isset($_GET['destination'])) { + $destination = drupal_get_destination(); + unset($_GET['destination']); + } + $form_state['redirect'] = array('admin/structure/views/view/' . $view->name, array('query' => $destination)); } /** @@ -1188,8 +1196,8 @@ function views_ui_preview_form($form, &$form_state, $view, $display_id = 'defaul // Add the preview button $form['button'] = array( '#type' => 'submit', - '#value' => t('Update preview'), - '#attributes' => array('class' => array('arguments-preview', 'ctools-auto-submit-click')), + '#value' => t('Update preview'), + '#attributes' => array('class' => array('arguments-preview', 'ctools-auto-submit-click')), '#pre_render' => array('ctools_dependent_pre_render'), '#prefix' => '<div id="preview-submit-wrapper">', '#suffix' => '</div>', @@ -1947,6 +1955,11 @@ function views_ui_import_page($form, &$form_state) { '#description' => t('Enter the name to use for this view if it is different from the source view. Leave blank to use the name of the view.'), ); + $form['name_override'] = array( + '#type' => 'checkbox', + '#title' => t('Replace an existing view if one exists with the same name'), + ); + $form['view'] = array( '#type' => 'textarea', '#title' => t('Paste view code here'), @@ -2000,8 +2013,15 @@ function views_ui_import_validate($form, &$form_state) { } $test = views_get_view($view->name); - if ($test && $test->type != t('Default')) { - form_set_error('', t('A view by that name already exists; please choose a different name')); + if (!$form_state['values']['name_override']) { + if ($test && $test->type != t('Default')) { + form_set_error('', t('A view by that name already exists; please choose a different name')); + } + } + else { + if ($test->vid) { + $view->vid = $test->vid; + } } // Make sure base table gets set properly if it got moved. @@ -3612,7 +3632,7 @@ function views_ui_rearrange_filter_form($form, &$form_state) { ); $form['remove_groups'][$id] = array(); // to prevent a notice - if ($id != 0) { + if ($id != 1) { $form['remove_groups'][$id] = array( '#type' => 'submit', '#value' => t('Remove group @group', array('@group' => $id)), @@ -3623,7 +3643,7 @@ function views_ui_rearrange_filter_form($form, &$form_state) { '#group' => $id, ); } - $group_options[$id] = $id == 0 ? t('Default group') : t('Group @group', array('@group' => $id)); + $group_options[$id] = $id == 1 ? t('Default group') : t('Group @group', array('@group' => $id)); $form['#group_renders'][$id] = array(); } @@ -3635,7 +3655,7 @@ function views_ui_rearrange_filter_form($form, &$form_state) { foreach ($handlers as $id => $field) { // If the group does not exist, move the filters to the default group. if (empty($field['group']) || empty($groups['groups'][$field['group']])) { - $field['group'] = 0; + $field['group'] = 1; } $handler = $display->handler->get_handler($type, $id); @@ -3647,7 +3667,7 @@ function views_ui_rearrange_filter_form($form, &$form_state) { // the default group to prevent weird errors from having it be in its // own group: if (!$grouping && $field['group'] == 'ungroupable') { - $field['group'] = 0; + $field['group'] = 1; } // Place this item into the proper group for rendering. @@ -3883,11 +3903,11 @@ function views_ui_rearrange_filter_form_submit($form, &$form_state) { // The actual update button was clicked. Remove the empty groups, and // renumber them sequentially. ksort($remember_groups); - $groups['groups'] = array_values(array_intersect_key($groups['groups'], $remember_groups)); + $groups['groups'] = views_array_key_plus(array_values(array_intersect_key($groups['groups'], $remember_groups))); // Change the 'group' key on each field to match. Here, $mapping is an // array whose keys are the old group numbers and whose values are the new // (sequentially numbered) ones. - $mapping = array_flip(array_keys($remember_groups)); + $mapping = array_flip(views_array_key_plus(array_keys($remember_groups))); foreach ($new_fields as &$new_field) { $new_field['group'] = $mapping[$new_field['group']]; } @@ -4254,9 +4274,11 @@ function views_ui_config_item_form_submit_temporary($form, &$form_state) { $item = $form_state['handler']->options; $types = views_object_types(); - $type = $form_state['type']; + // For footer/header $handler_type is area but $type is footer/header. + // For all other handle types it's the same. + $handler_type = $type = $form_state['type']; if (!empty($types[$type]['type'])) { - $type = $types[$type]['type']; + $handler_type = $types[$type]['type']; } $override = NULL; @@ -4272,7 +4294,7 @@ function views_ui_config_item_form_submit_temporary($form, &$form_state) { // Create a new handler and unpack the options from the form onto it. We // can use that for storage. - $handler = views_get_handler($item['table'], $item['field'], $type, $override); + $handler = views_get_handler($item['table'], $item['field'], $handler_type, $override); $handler->init($form_state['view'], $item); @@ -4307,9 +4329,11 @@ function views_ui_config_item_form_submit($form, &$form_state) { $item = $form_state['handler']->options; $types = views_object_types(); - $type = $form_state['type']; + // For footer/header $handler_type is area but $type is footer/header. + // For all other handle types it's the same. + $handler_type = $type = $form_state['type']; if (!empty($types[$type]['type'])) { - $type = $types[$type]['type']; + $handler_type = $types[$type]['type']; } $override = NULL; @@ -4325,7 +4349,7 @@ function views_ui_config_item_form_submit($form, &$form_state) { // Create a new handler and unpack the options from the form onto it. We // can use that for storage. - $handler = views_get_handler($item['table'], $item['field'], $type, $override); + $handler = views_get_handler($item['table'], $item['field'], $handler_type, $override); $handler->init($form_state['view'], $item); @@ -4473,7 +4497,7 @@ function views_ui_config_item_extra_form($form, &$form_state) { $item = $view->get_item($display_id, $type, $id); if ($item) { - $handler = views_get_handler($item['table'], $item['field'], $type); + $handler = $view->display_handler->get_handler($type, $id); if (empty($handler)) { $form['markup'] = array('#markup' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); } @@ -4651,6 +4675,13 @@ function views_ui_admin_settings_basic() { '#default_value' => variable_get('views_ui_show_advanced_column', FALSE), ); + $form['basic']['views_ui_display_embed'] = array( + '#type' => 'checkbox', + '#title' => t('Show the embed display in the ui.'), + '#description' => t('Allow advanced user to use the embed view display. The plugin itself works if it\'s not visible in the ui'), + '#default_value' => variable_get('views_ui_display_embed', FALSE), + ); + $form['basic']['views_ui_custom_theme'] = array( '#type' => 'select', '#title' => t('Custom admin theme for the Views UI'), @@ -4761,7 +4792,8 @@ function views_ui_admin_settings_advanced() { $form['debug']['views_sql_signature'] = array( '#type' => 'checkbox', '#title' => t('Add Views signature to all SQL queries'), - '#description' => t("All Views-generated queries will include a special 'VIEWS' = 'VIEWS' string in the WHERE clause. This makes identifying Views queries in database server logs simpler, but should only be used when troubleshooting."), + '#description' => t("All Views-generated queries will include the name of the views and display 'view-name:display-name' as a string at the end of the SELECT clause. This makes identifying Views queries in database server logs simpler, but should only be used when troubleshooting."), + '#default_value' => variable_get('views_sql_signature', FALSE), ); @@ -4792,7 +4824,7 @@ function views_ui_admin_settings_advanced() { '#description' => t('Select a translation method to use for Views data like header, footer, and empty text.'), ); - $regions = system_region_list(variable_get('theme_default', 'garland')); + $regions = array(); $regions['watchdog'] = t('Watchdog'); if (module_exists('devel')) { $regions['message'] = t('Devel message(dpm)'); diff --git a/sites/all/modules/views/includes/handlers.inc b/sites/all/modules/views/includes/handlers.inc index 35484f959..45a3a45ef 100644 --- a/sites/all/modules/views/includes/handlers.inc +++ b/sites/all/modules/views/includes/handlers.inc @@ -10,16 +10,35 @@ function _views_create_handler($definition, $type = 'handler', $handler_type = NULL) { // debug('Instantiating handler ' . $definition['handler']); if (empty($definition['handler'])) { + vpr('_views_create_handler - type: @type - failed: handler has not been provided.', + array('@type' => isset($handler_type) ? ( $type . '(handler type: ' . $handler_type . ')' ) : $type) + ); return; } // class_exists will automatically load the code file. if (!empty($definition['override handler']) && !class_exists($definition['override handler'])) { + vpr( + '_views_create_handler - loading override handler @type failed: class @override_handler could not be loaded. ' . + 'Verify the class file has been registered in the corresponding .info-file (files[]).', + array( + '@type' => isset($handler_type) ? ( $type . '(handler type: ' . $handler_type . ')' ) : $type, + '@override_handler' => $definition['override handler'] + ) + ); return; } if (!class_exists($definition['handler'])) { + vpr( + '_views_create_handler - loading handler @type failed: class @handler could not be loaded. ' . + 'Verify the class file has been registered in the corresponding .info-file (files[]).', + array( + '@type' => isset($handler_type) ? ( $type . '(handler type: ' . $handler_type . ')' ) : $type, + '@handler' => $definition['handler'] + ) + ); return; } @@ -155,6 +174,17 @@ class views_handler extends views_object { */ public $table_alias; + /** + * The actual field in the database table, maybe different + * on other kind of query plugins/special handlers. + */ + var $real_field; + + /** + * The relationship used for this field. + */ + var $relationship = NULL; + /** * init the handler with necessary data. * @param $view @@ -265,9 +295,11 @@ class views_handler extends views_object { // If grouping, check to see if the aggregation method needs to modify the field. if ($this->view->display_handler->use_group_by()) { $this->view->init_query(); - $info = $this->query->get_aggregation_info(); - if (!empty($info[$this->options['group_type']]['method']) && function_exists($info[$this->options['group_type']]['method'])) { - return $info[$this->options['group_type']]['method']($this->options['group_type'], $field); + if ($this->query) { + $info = $this->query->get_aggregation_info(); + if (!empty($info[$this->options['group_type']]['method']) && function_exists($info[$this->options['group_type']]['method'])) { + return $info[$this->options['group_type']]['method']($this->options['group_type'], $field); + } } } diff --git a/sites/all/modules/views/includes/plugins.inc b/sites/all/modules/views/includes/plugins.inc index 9f6459f29..51d0e93f8 100644 --- a/sites/all/modules/views/includes/plugins.inc +++ b/sites/all/modules/views/includes/plugins.inc @@ -82,6 +82,17 @@ function views_views_plugins() { 'admin' => t('Feed'), 'help topic' => 'display-feed', ), + 'embed' => array( + 'title' => t('Embed'), + 'help' => t('Provide a display which can be embedded using the views api.'), + 'handler' => 'views_plugin_display_embed', + 'uses hook menu' => FALSE, + 'use ajax' => TRUE, + 'use pager' => TRUE, + 'accept attachments' => FALSE, + 'admin' => t('Embed'), + 'no ui' => !variable_get('views_ui_display_embed', FALSE), + ), ), 'display_extender' => array( // Default settings for all display_extender plugins. @@ -452,9 +463,9 @@ class views_plugin extends views_object { var $view = NULL; /** - * The current used display plugin. + * The current used views display. * - * @var views_plugin_display + * @var views_display */ var $display = NULL; diff --git a/sites/all/modules/views/includes/view.inc b/sites/all/modules/views/includes/view.inc index 602e90ed5..4848879f4 100644 --- a/sites/all/modules/views/includes/view.inc +++ b/sites/all/modules/views/includes/view.inc @@ -27,6 +27,60 @@ class view extends views_db_object { */ var $name = ""; + /** + * The id of the view, which is used only for views in the database. + * + * @var number + */ + var $vid; + + /** + * The description of the view, which is used only in the interface. + * + * @var string + */ + var $description; + + /** + * The "tags" of a view. + * The tags are stored as a single string, though it is used as multiple tags + * for example in the views overview. + * + * @var string + */ + var $tag; + + /** + * The human readable name of the view. + * + * @var string + */ + var $human_name; + + /** + * The core version the view was created for. + * @var int + */ + var $core; + + /** + * The views-api version this view was created by. + * + * Some examples of the variable are 3.0 or 3.0-alpha1 + * + * @var string + */ + var $api_version; + + /** + * Is the view disabled. + * + * This value is used for exported view, to provide some default views which aren't enabled. + * + * @var bool + */ + var $disabled; + // State variables var $built = FALSE; var $executed = FALSE; @@ -53,13 +107,18 @@ class view extends views_db_object { // Exposed widget input var $exposed_data = array(); var $exposed_input = array(); + // Exposed widget input directly from the $form_state['values']. + var $exposed_raw_input = array(); // Used to store views that were previously running if we recurse. var $old_view = array(); - // To avoid recursion in views embebed into areas + // To avoid recursion in views embedded into areas. var $parent_views = array(); + // Is the current stored view runned as an attachment to another view. + var $is_attachment = NULL; + // Stores the next steps of form items to handle. // It's an array of stack items, which contain the form id, the type of form, // the view, the display and some additional arguments. @@ -87,6 +146,13 @@ class view extends views_db_object { */ var $display_handler; + /** + * Stores all display handlers of this view. + * + * @var array[views_display] + */ + var $display; + /** * The current used style plugin. * @@ -94,6 +160,21 @@ class view extends views_db_object { */ var $style_plugin; + /** + * Stored the changed options of the style plugin. + * + * @deprecated Better use $view->style_plugin->options + * @var array + */ + var $style_options; + + /** + * Stores the current active row while rendering. + * + * @var int + */ + var $row_index; + /** * Allow to override the url of the current view. * @@ -113,6 +194,58 @@ class view extends views_db_object { */ var $base_database = NULL; + /** + * Here comes a list of the possible handler which are active on this view. + */ + + /** + * Stores the field handlers which are initialized on this view. + * @var array[views_handler_field] + */ + var $field; + + /** + * Stores the argument handlers which are initialized on this view. + * @var array[views_handler_argument] + */ + var $argument; + + /** + * Stores the sort handlers which are initialized on this view. + * @var array[views_handler_sort] + */ + var $sort; + + /** + * Stores the filter handlers which are initialized on this view. + * @var array[views_handler_filter] + */ + var $filter; + + /** + * Stores the relationship handlers which are initialized on this view. + * @var array[views_handler_relationship] + */ + var $relationship; + + /** + * Stores the area handlers for the header which are initialized on this view. + * @var array[views_handler_area] + */ + var $header; + + /** + * Stores the area handlers for the footer which are initialized on this view. + * @var array[views_handler_area] + */ + var $footer; + + /** + * Stores the area handlers for the empty text which are initialized on this view. + * @var array[views_handler_area] + */ + var $empty; + /** * Constructor */ @@ -608,39 +741,6 @@ class view extends views_db_object { } } - /** - * Prepare arguments and set default args to args. - */ - function _pre_query_argument() { - // build arguments. - $position = -1; - - // Iterate through each argument and process. - foreach ($this->argument as $id => $arg) { - $position++; - $argument = &$this->argument[$id]; - - if ($argument->broken()) { - continue; - } - - $arg = isset($this->args[$position]) ? $this->args[$position] : NULL; - $argument->position = $position; - - if (isset($arg) || $argument->has_default_argument()) { - if (!isset($arg)) { - $arg = $argument->get_default_argument(); - // make sure default args get put back. - if (isset($arg)) { - $this->args[$position] = $arg; - } - // remember that this argument was computed, not passed on the URL. - $argument->is_default = TRUE; - } - } - } - } - /** * Build all the arguments. */ @@ -677,7 +777,17 @@ class view extends views_db_object { $arg = isset($this->args[$position]) ? $this->args[$position] : NULL; $argument->position = $position; - if (isset($arg)) { + if (isset($arg) || $argument->has_default_argument()) { + if (!isset($arg)) { + $arg = $argument->get_default_argument(); + // make sure default args get put back. + if (isset($arg)) { + $this->args[$position] = $arg; + } + // remember that this argument was computed, not passed on the URL. + $argument->is_default = TRUE; + } + // Set the argument, which will also validate that the argument can be set. if (!$argument->set_argument($arg)) { $status = $argument->validate_fail($arg); @@ -817,9 +927,6 @@ class view extends views_db_object { // Run through our handlers and ensure they have necessary information. $this->init_handlers(); - // Setup the default arguments. - $this->_pre_query_argument(); - // Let the handlers interact with each other if they really want. $this->_pre_query(); @@ -1039,6 +1146,11 @@ class view extends views_db_object { $cache->cache_start(); } + // Run pre_render for the pager as it might change the result. + if (!empty($this->query->pager)) { + $this->query->pager->pre_render($this->result); + } + // Initialize the style plugin. $this->init_style(); @@ -1167,19 +1279,17 @@ class view extends views_db_object { views_set_current_view($this); $display_id = $this->current_display; - // Let modules modify the view just prior to executing it. - foreach (module_implements('views_pre_view') as $module) { - $function = $module . '_views_pre_view'; - $function($this, $display_id, $args); - } - // Prepare the view with the information we have, but only if we were // passed arguments, as they may have been set previously. if ($args) { $this->set_arguments($args); } -// $this->attach_displays(); + // Let modules modify the view just prior to executing it. + foreach (module_implements('views_pre_view') as $module) { + $function = $module . '_views_pre_view'; + $function($this, $display_id, $this->args); + } // Allow the display handler to set up for execution $this->display_handler->pre_execute(); @@ -1537,69 +1647,6 @@ class view extends views_db_object { $this->additional_queries = $temp; } - /** - * Load a view from the database based upon either vid or name. - * - * This is a static factory method that implements internal caching for - * view objects. - * - * @param $arg - * The name of the view or its internal view id (vid) - * @param $reset - * If TRUE, reset this entry in the load cache. - * @return view - * A view object or NULL if it was not available. - */ - static function &load($arg, $reset = FALSE) { - static $cache = array(); - - // We want a NULL value to return TRUE here, so we can't use isset() or empty(). - if (!array_key_exists($arg, $cache) || $reset) { - $result = db_select('views_view', 'v') - ->fields('v') - ->condition(is_numeric($arg) ? 'vid' : 'name', $arg) - ->execute(); - if ($result->rowCount() == 0) { - $cache[$arg] = NULL; - } - else { - $view = new view(); - $view->load_row($result->fetchObject()); - $view->type = t('Normal'); - // Load all of our subtables. - foreach ($view->db_objects() as $key) { - $object_name = "views_$key"; - $result = db_select($object_name, 'v') - ->fields('v') - ->condition('vid', $view->vid) - ->orderBy('position') - ->execute(); - foreach ($result as $data) { - $object = new $object_name(FALSE); - $object->load_row($data); - - // Because it can get complicated with this much indirection, - // make a shortcut reference. - $location = &$view->$key; - - // If we have a basic id field, load the item onto the view based on - // this ID, otherwise push it on. - if (!empty($object->id)) { - $location[$object->id] = $object; - } - else { - $location[] = $object; - } - } - } - $view->loaded = TRUE; - $cache[$arg] = $view; - } - } - - return $cache[$arg]; - } - /** * Static factory method to load a list of views based upon a $where clause. * @@ -1967,6 +2014,8 @@ class view extends views_db_object { * Base class for views' database objects. */ class views_db_object { + public $db_table; + /** * Initialize this object, setting values from schema defaults. * @@ -2377,6 +2426,13 @@ class views_display extends views_db_object { */ var $handler; + /** + * Stores all options of the display, like fields, filters etc. + * + * @var array + */ + var $display_options; + var $db_table = 'views_display'; function views_display($init = TRUE) { parent::init($init); diff --git a/sites/all/modules/views/js/ajax_view.js b/sites/all/modules/views/js/ajax_view.js index c22bbf0d0..a89d4aa94 100644 --- a/sites/all/modules/views/js/ajax_view.js +++ b/sites/all/modules/views/js/ajax_view.js @@ -35,8 +35,19 @@ Drupal.views.ajaxView = function(settings) { ajax_path = ajax_path[0]; } + // Check if there are any GET parameters to send to views. + var queryString = window.location.search || ''; + if (queryString !== '') { + // Remove the question mark and Drupal path component if any. + var queryString = queryString.slice(1).replace(/q=[^&]+&?|&?render=[^&]+/, ''); + if (queryString !== '') { + // If there is a '?' in ajax_path, clean url are on and & should be used to add parameters. + queryString = ((/\?/.test(ajax_path)) ? '&' : '?') + queryString; + } + } + this.element_settings = { - url: ajax_path + window.location.search, + url: ajax_path + queryString, submit: settings, setClick: true, event: 'click', @@ -115,7 +126,7 @@ Drupal.ajax.prototype.commands.viewsScrollTop = function (ajax, response, status // and scroll the first element that has a non-zero top. var scrollTarget = response.selector; while ($(scrollTarget).scrollTop() == 0 && $(scrollTarget).parent()) { - scrollTarget = $(scrollTarget).parent() + scrollTarget = $(scrollTarget).parent(); } // Only scroll upward if (offset.top - 10 < $(scrollTarget).scrollTop()) { diff --git a/sites/all/modules/views/js/views-admin.js b/sites/all/modules/views/js/views-admin.js index 104239aed..e2cd16f33 100644 --- a/sites/all/modules/views/js/views-admin.js +++ b/sites/all/modules/views/js/views-admin.js @@ -1,5 +1,17 @@ Drupal.viewsUi = {}; +Drupal.behaviors.viewsUiEditView = {}; + +/** + * Improve the user experience of the views edit interface. + */ +Drupal.behaviors.viewsUiEditView.attach = function (context, settings) { + // Only show the SQL rewrite warning when the user has chosen the + // corresponding checkbox. + jQuery('#edit-query-options-disable-sql-rewrite').click(function () { + jQuery('.sql-rewrite-warning').toggleClass('js-hide'); + }); +}; Drupal.behaviors.viewsUiAddView = {}; @@ -547,7 +559,7 @@ Drupal.viewsUi.rearrangeFilterHandler.prototype.duplicateGroupsOperator = functi dropdowns = this.operator; // Move the operator to a new row just above the second group. - titleRow = $('tr#views-group-title-1'); + titleRow = $('tr#views-group-title-2'); newRow = $('<tr class="filter-group-operator-row"><td colspan="5"></td></tr>'); newRow.find('td').append(this.operator); newRow.insertBefore(titleRow); diff --git a/sites/all/modules/views/modules/aggregator/views_handler_argument_aggregator_category_cid.inc b/sites/all/modules/views/modules/aggregator/views_handler_argument_aggregator_category_cid.inc index 7d64f3ef2..c67832cdc 100644 --- a/sites/all/modules/views/modules/aggregator/views_handler_argument_aggregator_category_cid.inc +++ b/sites/all/modules/views/modules/aggregator/views_handler_argument_aggregator_category_cid.inc @@ -2,6 +2,8 @@ /** * Argument handler to accept an aggregator category id. + * + * @ingroup views_argument_handlers */ class views_handler_argument_aggregator_category_cid extends views_handler_argument_numeric { /** diff --git a/sites/all/modules/views/modules/aggregator/views_handler_argument_aggregator_fid.inc b/sites/all/modules/views/modules/aggregator/views_handler_argument_aggregator_fid.inc index 6a3a9d818..ed1128841 100644 --- a/sites/all/modules/views/modules/aggregator/views_handler_argument_aggregator_fid.inc +++ b/sites/all/modules/views/modules/aggregator/views_handler_argument_aggregator_fid.inc @@ -2,6 +2,8 @@ /** * Argument handler to accept an aggregator feed id. + * + * @ingroup views_argument_handlers */ class views_handler_argument_aggregator_fid extends views_handler_argument_numeric { /** diff --git a/sites/all/modules/views/modules/aggregator/views_handler_argument_aggregator_iid.inc b/sites/all/modules/views/modules/aggregator/views_handler_argument_aggregator_iid.inc index 575e74307..fe19ab68e 100644 --- a/sites/all/modules/views/modules/aggregator/views_handler_argument_aggregator_iid.inc +++ b/sites/all/modules/views/modules/aggregator/views_handler_argument_aggregator_iid.inc @@ -2,6 +2,8 @@ /** * Argument handler to accept an aggregator item id. + * + * @ingroup views_argument_handlers */ class views_handler_argument_aggregator_iid extends views_handler_argument_numeric { /** diff --git a/sites/all/modules/views/modules/aggregator/views_handler_field_aggregator_category.inc b/sites/all/modules/views/modules/aggregator/views_handler_field_aggregator_category.inc index b0ca9c5d6..0564810be 100644 --- a/sites/all/modules/views/modules/aggregator/views_handler_field_aggregator_category.inc +++ b/sites/all/modules/views/modules/aggregator/views_handler_field_aggregator_category.inc @@ -3,6 +3,8 @@ /** * Field handler to provide simple renderer that allows linking to aggregator * category. + * + * @ingroup views_field_handlers */ class views_handler_field_aggregator_category extends views_handler_field { /** diff --git a/sites/all/modules/views/modules/aggregator/views_handler_field_aggregator_title_link.inc b/sites/all/modules/views/modules/aggregator/views_handler_field_aggregator_title_link.inc index e3e4c51cf..d428f4427 100644 --- a/sites/all/modules/views/modules/aggregator/views_handler_field_aggregator_title_link.inc +++ b/sites/all/modules/views/modules/aggregator/views_handler_field_aggregator_title_link.inc @@ -3,6 +3,8 @@ /** * Field handler that turns an item's title into a clickable link to the original * source article. + * + * @ingroup views_field_handlers */ class views_handler_field_aggregator_title_link extends views_handler_field { function construct() { diff --git a/sites/all/modules/views/modules/aggregator/views_handler_field_aggregator_xss.inc b/sites/all/modules/views/modules/aggregator/views_handler_field_aggregator_xss.inc index 3fa87c48f..0813e35fa 100644 --- a/sites/all/modules/views/modules/aggregator/views_handler_field_aggregator_xss.inc +++ b/sites/all/modules/views/modules/aggregator/views_handler_field_aggregator_xss.inc @@ -1,9 +1,9 @@ <?php /** - * @file - * Filters htmls tags from item. + * Filters htmls tags from item. + * + * @ingroup views_field_handlers */ - class views_handler_field_aggregator_xss extends views_handler_field { function render($values) { $value = $this->get_value($values); diff --git a/sites/all/modules/views/modules/aggregator/views_handler_filter_aggregator_category_cid.inc b/sites/all/modules/views/modules/aggregator/views_handler_filter_aggregator_category_cid.inc index 2f797a80b..27cf6749d 100644 --- a/sites/all/modules/views/modules/aggregator/views_handler_filter_aggregator_category_cid.inc +++ b/sites/all/modules/views/modules/aggregator/views_handler_filter_aggregator_category_cid.inc @@ -1,6 +1,8 @@ <?php /** * Filter by aggregator category cid + * + * @ingroup views_filter_handlers */ class views_handler_filter_aggregator_category_cid extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/modules/comment.views.inc b/sites/all/modules/views/modules/comment.views.inc index 772ac2439..e22ccd54e 100644 --- a/sites/all/modules/views/modules/comment.views.inc +++ b/sites/all/modules/views/modules/comment.views.inc @@ -256,6 +256,9 @@ function comment_views_data() { 'field' => array( 'handler' => 'views_handler_field_boolean', 'click sortable' => TRUE, + 'output formats' => array( + 'approved-not-approved' => array(t('Approved'), t('Not Approved')), + ), ), 'filter' => array( 'handler' => 'views_handler_filter_boolean_operator', @@ -606,6 +609,7 @@ function comment_views_plugins() { 'theme' => 'views_view_row_rss', 'path' => drupal_get_path('module', 'views') . '/modules/comment', // not necessary for most modules 'base' => array('comment'), // only works with 'comment' as base. + 'uses options' => TRUE, 'type' => 'feed', 'help topic' => 'style-comment-rss', ), diff --git a/sites/all/modules/views/modules/comment.views_default.inc b/sites/all/modules/views/modules/comment.views_default.inc index 5a4587cc9..44ebac901 100644 --- a/sites/all/modules/views/modules/comment.views_default.inc +++ b/sites/all/modules/views/modules/comment.views_default.inc @@ -182,6 +182,10 @@ function comment_views_default_views() { ); $handler->display->display_options['style_options']['override'] = 1; $handler->display->display_options['style_options']['order'] = 'desc'; + /* Relationship: Content: Author */ + $handler->display->display_options['relationships']['uid']['id'] = 'uid'; + $handler->display->display_options['relationships']['uid']['table'] = 'node'; + $handler->display->display_options['relationships']['uid']['field'] = 'uid'; /* Field: Content: Type */ $handler->display->display_options['fields']['type']['id'] = 'type'; $handler->display->display_options['fields']['type']['table'] = 'node'; @@ -194,6 +198,7 @@ function comment_views_default_views() { $handler->display->display_options['fields']['name']['id'] = 'name'; $handler->display->display_options['fields']['name']['table'] = 'users'; $handler->display->display_options['fields']['name']['field'] = 'name'; + $handler->display->display_options['fields']['name']['relationship'] = 'uid'; $handler->display->display_options['fields']['name']['label'] = 'Author'; /* Field: Content: Comment count */ $handler->display->display_options['fields']['comment_count']['id'] = 'comment_count'; diff --git a/sites/all/modules/views/modules/comment/views_handler_argument_comment_user_uid.inc b/sites/all/modules/views/modules/comment/views_handler_argument_comment_user_uid.inc index dfba09ca4..11144a9d9 100644 --- a/sites/all/modules/views/modules/comment/views_handler_argument_comment_user_uid.inc +++ b/sites/all/modules/views/modules/comment/views_handler_argument_comment_user_uid.inc @@ -3,6 +3,8 @@ /** * Argument handler to accept a user id to check for nodes that * user posted or commented on. + * + * @ingroup views_argument_handlers */ class views_handler_argument_comment_user_uid extends views_handler_argument { function title() { diff --git a/sites/all/modules/views/modules/comment/views_handler_field_comment.inc b/sites/all/modules/views/modules/comment/views_handler_field_comment.inc index 9458bad5e..b855b6335 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_comment.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_comment.inc @@ -1,6 +1,8 @@ <?php /** - * Field handler to allow linking to a comment + * Field handler to allow linking to a comment. + * + * @ingroup views_field_handlers */ class views_handler_field_comment extends views_handler_field { /** diff --git a/sites/all/modules/views/modules/comment/views_handler_field_comment_depth.inc b/sites/all/modules/views/modules/comment/views_handler_field_comment_depth.inc index 17b080a9f..8872a6ad4 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_comment_depth.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_comment_depth.inc @@ -1,12 +1,15 @@ <?php /** - * Field handler to display the depth of a comment + * Field handler to display the depth of a comment. + * + * @ingroup views_field_handlers */ class views_handler_field_comment_depth extends views_handler_field { /** * Work out the depth of this comment */ function render($values) { - return count(explode('.', $values->comments_thread)) - 1; + $comment_thread = $this->get_value($values); + return count(explode('.', $comment_thread)) - 1; } } diff --git a/sites/all/modules/views/modules/comment/views_handler_field_comment_link.inc b/sites/all/modules/views/modules/comment/views_handler_field_comment_link.inc index fd4ed7a82..e0e0ba713 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_comment_link.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_comment_link.inc @@ -1,12 +1,12 @@ <?php /** * Base field handler to present a link. + * + * @ingroup views_field_handlers */ -class views_handler_field_comment_link extends views_handler_field { +class views_handler_field_comment_link extends views_handler_field_entity { function construct() { parent::construct(); - $this->additional_fields['cid'] = 'cid'; - $this->additional_fields['nid'] = 'nid'; } function option_definition() { @@ -42,8 +42,9 @@ class views_handler_field_comment_link extends views_handler_field { function render_link($data, $values) { $text = !empty($this->options['text']) ? $this->options['text'] : t('view'); - $nid = $this->get_value($values, 'nid'); - $cid = $this->get_value($values, 'cid'); + $comment = $this->get_value($values); + $nid = $comment->nid; + $cid = $comment->cid; $this->options['alter']['make_link'] = TRUE; $this->options['alter']['html'] = TRUE; diff --git a/sites/all/modules/views/modules/comment/views_handler_field_comment_link_approve.inc b/sites/all/modules/views/modules/comment/views_handler_field_comment_link_approve.inc index bd39fa9d8..8063e2012 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_comment_link_approve.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_comment_link_approve.inc @@ -2,12 +2,10 @@ /** * @file * Provides a comment approve link. + * + * @ingroup views_field_handlers */ class views_handler_field_comment_link_approve extends views_handler_field_comment_link { - function construct() { - parent::construct(); - $this->additional_fields['status'] = 'status'; - } function access() { //needs permission to administer comments in general return user_access('administer comments'); diff --git a/sites/all/modules/views/modules/comment/views_handler_field_comment_link_delete.inc b/sites/all/modules/views/modules/comment/views_handler_field_comment_link_delete.inc index da669a08c..b74661b32 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_comment_link_delete.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_comment_link_delete.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to present a link to delete a node. + * + * @ingroup views_field_handlers */ class views_handler_field_comment_link_delete extends views_handler_field_comment_link { function access() { diff --git a/sites/all/modules/views/modules/comment/views_handler_field_comment_link_edit.inc b/sites/all/modules/views/modules/comment/views_handler_field_comment_link_edit.inc index 2cac79b55..ffd1f935c 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_comment_link_edit.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_comment_link_edit.inc @@ -1,13 +1,10 @@ <?php /** * Field handler to present a link node edit. + * + * @ingroup views_field_handlers */ class views_handler_field_comment_link_edit extends views_handler_field_comment_link { - function construct() { - parent::construct(); - $this->additional_fields['uid'] = 'uid'; - } - function option_definition() { $options = parent::option_definition(); $options['destination'] = array('default' => FALSE); @@ -30,9 +27,7 @@ class views_handler_field_comment_link_edit extends views_handler_field_comment_ function render_link($data, $values) { parent::render_link($data, $values); // ensure user has access to edit this comment. - $comment = new stdClass(); - $comment->cid = $this->get_value($values, 'cid'); - $comment->uid = $this->get_value($values, 'uid'); + $comment = $this->get_value($values); if (!comment_access('edit', $comment)) { return; } diff --git a/sites/all/modules/views/modules/comment/views_handler_field_comment_link_reply.inc b/sites/all/modules/views/modules/comment/views_handler_field_comment_link_reply.inc index 1b922c716..156416468 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_comment_link_reply.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_comment_link_reply.inc @@ -2,6 +2,8 @@ /** * Field handler to present a link to delete a node. + * + * @ingroup views_field_handlers */ class views_handler_field_comment_link_reply extends views_handler_field_comment_link { function access() { diff --git a/sites/all/modules/views/modules/comment/views_handler_field_comment_node_link.inc b/sites/all/modules/views/modules/comment/views_handler_field_comment_node_link.inc index 4cd78de77..0e4f6101e 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_comment_node_link.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_comment_node_link.inc @@ -1,8 +1,10 @@ <?php /** -* Handler for showing comment module's node link. + * Handler for showing comment module's node link. + * + * @ingroup views_field_handlers */ -class views_handler_field_comment_node_link extends views_handler_field { +class views_handler_field_comment_node_link extends views_handler_field_entity { function construct() { parent::construct(); @@ -43,10 +45,7 @@ class views_handler_field_comment_node_link extends views_handler_field { function render($values) { // Build fake $node. - $node = new stdClass(); - $node->nid = $this->get_value($values, 'nid'); - $node->type = $this->get_value($values, 'type'); - $node->comment = $this->get_value($values, 'comment'); + $node = $this->get_value($values); // Call comment.module's hook_link: comment_link($type, $node = NULL, $teaser = FALSE) // Call node by reference so that something is changed here diff --git a/sites/all/modules/views/modules/comment/views_handler_field_comment_username.inc b/sites/all/modules/views/modules/comment/views_handler_field_comment_username.inc index 7362643ae..6b6186e44 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_comment_username.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_comment_username.inc @@ -1,6 +1,8 @@ <?php /** - * Field handler to allow linking to a user account or homepage + * Field handler to allow linking to a user account or homepage. + * + * @ingroup views_field_handlers */ class views_handler_field_comment_username extends views_handler_field { /** diff --git a/sites/all/modules/views/modules/comment/views_handler_field_last_comment_timestamp.inc b/sites/all/modules/views/modules/comment/views_handler_field_last_comment_timestamp.inc index 64ed7dd13..2bfa970bb 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_last_comment_timestamp.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_last_comment_timestamp.inc @@ -1,5 +1,10 @@ <?php +/** + * Field handler to display the timestamp of a comment with the count of comments. + * + * @ingroup views_field_handlers + */ class views_handler_field_last_comment_timestamp extends views_handler_field_date { function construct() { parent::construct(); diff --git a/sites/all/modules/views/modules/comment/views_handler_field_ncs_last_comment_name.inc b/sites/all/modules/views/modules/comment/views_handler_field_ncs_last_comment_name.inc index 648be92ba..63f948f0b 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_ncs_last_comment_name.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_ncs_last_comment_name.inc @@ -1,7 +1,9 @@ <?php /** - * Field handler to present the name of the last comment poster + * Field handler to present the name of the last comment poster. + * + * @ingroup views_field_handlers */ class views_handler_field_ncs_last_comment_name extends views_handler_field { function query() { diff --git a/sites/all/modules/views/modules/comment/views_handler_field_ncs_last_updated.inc b/sites/all/modules/views/modules/comment/views_handler_field_ncs_last_updated.inc index 6c3e139dc..3950ffbbd 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_ncs_last_updated.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_ncs_last_updated.inc @@ -1,6 +1,8 @@ <?php /** - * Field handler to display the newer of last comment / node updated + * Field handler to display the newer of last comment / node updated. + * + * @ingroup views_field_handlers */ class views_handler_field_ncs_last_updated extends views_handler_field_date { function query() { diff --git a/sites/all/modules/views/modules/comment/views_handler_field_node_comment.inc b/sites/all/modules/views/modules/comment/views_handler_field_node_comment.inc index 4f89d64c6..6892feda4 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_node_comment.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_node_comment.inc @@ -1,7 +1,9 @@ <?php /** - * Display node comment status + * Display node comment status. + * + * @ingroup views_field_handlers */ class views_handler_field_node_comment extends views_handler_field { function render($values) { diff --git a/sites/all/modules/views/modules/comment/views_handler_field_node_new_comments.inc b/sites/all/modules/views/modules/comment/views_handler_field_node_new_comments.inc index 6c5835f00..0ecdfc657 100644 --- a/sites/all/modules/views/modules/comment/views_handler_field_node_new_comments.inc +++ b/sites/all/modules/views/modules/comment/views_handler_field_node_new_comments.inc @@ -1,7 +1,9 @@ <?php /** - * Field handler to display the number of new comments + * Field handler to display the number of new comments. + * + * @ingroup views_field_handlers */ class views_handler_field_node_new_comments extends views_handler_field_numeric { function init(&$view, &$options) { diff --git a/sites/all/modules/views/modules/comment/views_handler_filter_comment_user_uid.inc b/sites/all/modules/views/modules/comment/views_handler_filter_comment_user_uid.inc index 8d83b2559..4f9e71189 100644 --- a/sites/all/modules/views/modules/comment/views_handler_filter_comment_user_uid.inc +++ b/sites/all/modules/views/modules/comment/views_handler_filter_comment_user_uid.inc @@ -3,6 +3,8 @@ /** * Filter handler to accept a user id to check for nodes that user posted or * commented on. + * + * @ingroup views_filter_handlers */ class views_handler_filter_comment_user_uid extends views_handler_filter_user_name { function query() { @@ -17,6 +19,6 @@ class views_handler_filter_comment_user_uid extends views_handler_filter_user_na ->condition("$this->table_alias.uid", $this->value, $this->operator) ->exists($subselect); - $this->query->add_where(0, $condition); + $this->query->add_where($this->options['group'], $condition); } } diff --git a/sites/all/modules/views/modules/comment/views_handler_filter_ncs_last_updated.inc b/sites/all/modules/views/modules/comment/views_handler_filter_ncs_last_updated.inc index f931fe97c..3818db966 100644 --- a/sites/all/modules/views/modules/comment/views_handler_filter_ncs_last_updated.inc +++ b/sites/all/modules/views/modules/comment/views_handler_filter_ncs_last_updated.inc @@ -1,6 +1,8 @@ <?php /** * Filter handler for the newer of last comment / node updated + * + * @ingroup views_filter_handlers */ class views_handler_filter_ncs_last_updated extends views_handler_filter_date { function query() { diff --git a/sites/all/modules/views/modules/comment/views_handler_filter_node_comment.inc b/sites/all/modules/views/modules/comment/views_handler_filter_node_comment.inc index 9351c185e..659eaa643 100644 --- a/sites/all/modules/views/modules/comment/views_handler_filter_node_comment.inc +++ b/sites/all/modules/views/modules/comment/views_handler_filter_node_comment.inc @@ -2,6 +2,8 @@ /** * Filter based on comment node status + * + * @ingroup views_filter_handlers */ class views_handler_filter_node_comment extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/modules/comment/views_handler_sort_ncs_last_comment_name.inc b/sites/all/modules/views/modules/comment/views_handler_sort_ncs_last_comment_name.inc index 397bb6c68..8eca17730 100644 --- a/sites/all/modules/views/modules/comment/views_handler_sort_ncs_last_comment_name.inc +++ b/sites/all/modules/views/modules/comment/views_handler_sort_ncs_last_comment_name.inc @@ -1,7 +1,9 @@ <?php /** * Sort handler to sort by last comment name which might be in 2 different - * fields + * fields. + * + * @ingroup views_sort_handlers */ class views_handler_sort_ncs_last_comment_name extends views_handler_sort { function query() { diff --git a/sites/all/modules/views/modules/comment/views_handler_sort_ncs_last_updated.inc b/sites/all/modules/views/modules/comment/views_handler_sort_ncs_last_updated.inc index 39ab749a6..04b01a1e5 100644 --- a/sites/all/modules/views/modules/comment/views_handler_sort_ncs_last_updated.inc +++ b/sites/all/modules/views/modules/comment/views_handler_sort_ncs_last_updated.inc @@ -1,6 +1,8 @@ <?php /** - * Sort handler for the newer of last comment / node updated + * Sort handler for the newer of last comment / node updated. + * + * @ingroup views_sort_handlers */ class views_handler_sort_ncs_last_updated extends views_handler_sort_date { function query() { diff --git a/sites/all/modules/views/modules/comment/views_plugin_row_comment_rss.inc b/sites/all/modules/views/modules/comment/views_plugin_row_comment_rss.inc index 46a9d8714..7576bb51b 100644 --- a/sites/all/modules/views/modules/comment/views_plugin_row_comment_rss.inc +++ b/sites/all/modules/views/modules/comment/views_plugin_row_comment_rss.inc @@ -11,6 +11,32 @@ class views_plugin_row_comment_rss extends views_plugin_row { var $base_table = 'comment'; var $base_field = 'cid'; + function option_definition() { + $options = parent::option_definition(); + + $options['item_length'] = array('default' => 'default'); + $options['links'] = FALSE; + + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + $form['item_length'] = array( + '#type' => 'select', + '#title' => t('Display type'), + '#options' => $this->options_form_summary_options(), + '#default_value' => $this->options['item_length'], + ); + $form['links'] = array( + '#type' => 'checkbox', + '#title' => t('Display links'), + '#default_value' => $this->options['links'], + ); + } + + function pre_render($result) { $cids = array(); $nids = array(); @@ -28,6 +54,27 @@ class views_plugin_row_comment_rss extends views_plugin_row { $this->nodes = node_load_multiple($nids); } + /** + * Return the main options, which are shown in the summary title + * + * @see views_plugin_row_node_rss::options_form_summary_options() + * @todo: Maybe provide a views_plugin_row_rss_entity and reuse this method + * in views_plugin_row_comment|node_rss.inc + */ + function options_form_summary_options() { + $entity_info = entity_get_info('node'); + $options = array(); + if (!empty($entity_info['view modes'])) { + foreach ($entity_info['view modes'] as $mode => $settings) { + $options[$mode] = $settings['label']; + } + } + $options['title'] = t('Title only'); + $options['default'] = t('Use site default RSS settings'); + return $options; + } + + function render($row) { global $base_url; @@ -70,7 +117,7 @@ class views_plugin_row_comment_rss extends views_plugin_row { // The comment gets built and modules add to or modify // $comment->rss_elements and $comment->rss_namespaces. - $build = comment_view($comment, $this->nodes[$comment->cid], 'rss'); + $build = comment_view($comment, $this->nodes[$comment->nid], 'rss'); unset($build['#theme']); if (!empty($comment->rss_namespaces)) { diff --git a/sites/all/modules/views/modules/contact/views_handler_field_contact_link.inc b/sites/all/modules/views/modules/contact/views_handler_field_contact_link.inc index 3bf0ad15d..0a44f21b2 100644 --- a/sites/all/modules/views/modules/contact/views_handler_field_contact_link.inc +++ b/sites/all/modules/views/modules/contact/views_handler_field_contact_link.inc @@ -1,25 +1,12 @@ <?php /** * A field that links to the user contact page, if access is permitted. + * + * @ingroup views_field_handlers */ class views_handler_field_contact_link extends views_handler_field_user_link { - function option_definition() { - $options = parent::option_definition(); - $options['link_display'] = array('default' => 'link', 'translatable' => FALSE); - return $options; - } - function options_form(&$form, &$form_state) { - $form['link_display'] = array( - '#title' => t('Type of link'), - '#default_value' => $this->options['link_display'], - '#type' => 'select', - '#options' => array( - 'link' => t('Link'), - 'icon' => t('Icon'), - ), - ); $form['text']['#title'] = t('Link label'); $form['text']['#required'] = TRUE; $form['text']['#default_value'] = empty($this->options['text']) ? t('contact') : $this->options['text']; @@ -30,14 +17,7 @@ class views_handler_field_contact_link extends views_handler_field_user_link { // We must override the access method in the parent class, as that requires // the 'access user profiles' permission, which the contact form does not. function access() { - global $user; - - // Only registered users can view other registered user's contact page. - if (empty($user->uid)) { - return FALSE; - } - - return TRUE; + return user_access('access user contact forms'); } function render_link($data, $values) { @@ -56,20 +36,15 @@ class views_handler_field_contact_link extends views_handler_field_user_link { // Check access when we pull up the user account so we know // if the user has made the contact page available. $menu_item = menu_get_item("user/$uid/contact"); - if (!$menu_item['access'] || empty($account->contact)) { + if (!$menu_item['access'] || empty($account->data['contact'])) { return; } - $this->options['alter']['path'] = 'user/'. $account->uid .'/contact'; + $this->options['alter']['make_link'] = TRUE; + $this->options['alter']['path'] = 'user/' . $account->uid . '/contact'; $this->options['alter']['attributes'] = array('title' => t('Contact %user', array('%user' => $account->name))); - if ($this->options['link_display'] == 'icon') { - $text = theme('image', array('path' => 'misc/forum-new.png')); - $this->options['alter']['html'] = TRUE; - } - else { - $text = $this->options['text']; - } + $text = $this->options['text']; return $text; } diff --git a/sites/all/modules/views/modules/field.views.inc b/sites/all/modules/views/modules/field.views.inc index 7dc5cb20c..dd4363fd1 100644 --- a/sites/all/modules/views/modules/field.views.inc +++ b/sites/all/modules/views/modules/field.views.inc @@ -373,6 +373,9 @@ function field_views_field_default_views_data($field) { 'title short' => $title_short_delta, 'help' => t('Delta - Appears in: @bundles.', array('@bundles' => implode(', ', $bundles_names))), ); + $data[$table]['delta']['field'] = array( + 'handler' => 'views_handler_field_numeric', + ); $data[$table]['delta']['argument'] = array( 'field' => 'delta', 'table' => $table, @@ -413,6 +416,9 @@ function list_field_views_data($field) { if (isset($field_data['filter']) && $field != 'delta') { $data[$table_name][$field]['filter']['handler'] = 'views_handler_filter_field_list'; } + if (isset($field_data['argument']) && $field != 'delta') { + $data[$table_name][$field]['argument']['handler'] = 'views_handler_argument_field_list'; + } } } return $data; diff --git a/sites/all/modules/views/modules/field/views_handler_argument_field_list.inc b/sites/all/modules/views/modules/field/views_handler_argument_field_list.inc new file mode 100644 index 000000000..f8f10e961 --- /dev/null +++ b/sites/all/modules/views/modules/field/views_handler_argument_field_list.inc @@ -0,0 +1,56 @@ +<?php +/** + * @file + * Contains views_handler_argument_field_list handler + */ + +/** + * Argument handler for list field to show the human readable name in the summary. + * + * @ingroup views_argument_handlers + */ +class views_handler_argument_field_list extends views_handler_argument_numeric { + /** + * @var array + * Stores the allowed values of this field. + */ + var $allowed_values = NULL; + + function init(&$view, &$options) { + parent::init($view, $options); + $field = field_info_field($this->definition['field_name']); + $this->allowed_values = list_allowed_values($field); + } + + function option_definition() { + $options = parent::option_definition(); + $options['summary']['contains']['human'] = array('default' => FALSE); + + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + $form['summary']['human'] = array( + '#title' => t('Display list value as human readable'), + '#type' => 'checkbox', + '#default_value' => $this->options['summary']['human'],# + '#dependency' => array('radio:options[default_action]' => array('summary')), + ); + } + + + function summary_name($data) { + $value = $data->{$this->name_alias}; + // If the list element has a human readable name show it, + if (isset($this->allowed_values[$value]) && !empty($this->options['summary']['human'])) { + return field_filter_xss($this->allowed_values[$value]); + } + // else fallback to the key. + else { + return check_plain($value); + } + } +} + diff --git a/sites/all/modules/views/modules/field/views_handler_field_field.inc b/sites/all/modules/views/modules/field/views_handler_field_field.inc index 26c54fcdc..8e0b76750 100644 --- a/sites/all/modules/views/modules/field/views_handler_field_field.inc +++ b/sites/all/modules/views/modules/field/views_handler_field_field.inc @@ -147,7 +147,7 @@ class views_handler_field_field extends views_handler_field { } else { $this->field_alias = $this->query->add_field($this->base_table_alias, $entity_info['entity keys']['revision'], '', $params); - $this->aliases['entity id'] = $this->query->add_field($this->base_table_alias, $entity_info['entity keys']['id'], '', $params); + $this->aliases['entity_id'] = $this->query->add_field($this->base_table_alias, $entity_info['entity keys']['id'], '', $params); } @@ -166,7 +166,7 @@ class views_handler_field_field extends views_handler_field { // Add the fields that we're actually grouping on. $options = array(); - if ($this->options['group_column'] != 'entity id') { + if ($this->options['group_column'] != 'entity_id') { $options = array($this->options['group_column'] => $this->options['group_column']); } @@ -195,11 +195,24 @@ class views_handler_field_field extends views_handler_field { // Filter by language, if field translation is enabled. $field = $this->field_info; - if (field_is_translatable($entity_type, $field) && !empty($this->query->options['field_language_add_to_query'])) { + if (field_is_translatable($entity_type, $field) && !empty($this->view->display_handler->options['field_language_add_to_query'])) { $column = $this->table_alias . '.language'; // By the same reason as field_language the field might be LANGUAGE_NONE in reality so allow it as well. // @see this::field_language() - $this->query->add_where(0, $column, array($this->query->options['field_language'], LANGUAGE_NONE)); + global $language_content; + $default_language = language_default('language'); + $language = str_replace(array('***CURRENT_LANGUAGE***', '***DEFAULT_LANGUAGE***'), + array($language_content->language, $default_language), + $this->view->display_handler->options['field_language']); + $placeholder = $this->placeholder(); + $language_fallback_candidates = array($language); + if (variable_get('locale_field_language_fallback', TRUE) && module_exists('locale')) { + $language_fallback_candidates = array_merge($language_fallback_candidates, language_fallback_get_candidates()); + } + else { + $language_fallback_candidates[] = LANGUAGE_NONE; + } + $this->query->add_where_expression(0, "$column IN($placeholder) OR $column IS NULL", array($placeholder => $language_fallback_candidates)); } } @@ -520,7 +533,7 @@ class views_handler_field_field extends views_handler_field { // With "field API" fields, the column target of the grouping function // and any additional grouping columns must be specified. $group_columns = array( - 'entity id' => t('Entity ID'), + 'entity_id' => t('Entity ID'), ) + drupal_map_assoc(array_keys($this->field_info['columns']), 'ucfirst'); $form['group_column'] = array( @@ -569,7 +582,7 @@ class views_handler_field_field extends views_handler_field { } else { $revision_id = $object->{$this->field_alias}; - $entity_id = $object->{$this->aliases['entity id']}; + $entity_id = $object->{$this->aliases['entity_id']}; $entities_by_type[$entity_type][$key] = array($entity_id, $revision_id); } } @@ -697,10 +710,15 @@ class views_handler_field_field extends views_handler_field { // Offset is calculated differently when row grouping for a field is // not enabled. Since there are multiple rows, the delta needs to be // taken into account, so that different values are shown per row. - if (!$this->options['group_rows'] && isset($values->{$this->aliases['delta']})) { + if (!$this->options['group_rows'] && isset($this->aliases['delta']) && isset($values->{$this->aliases['delta']})) { $delta_limit = 1; $offset = $values->{$this->aliases['delta']}; } + // Single fields don't have a delta available so choose 0. + elseif (!$this->options['group_rows'] && !$this->multiple) { + $delta_limit = 1; + $offset = 0; + } else { $delta_limit = $this->options['delta_limit']; $offset = intval($this->options['delta_offset']); diff --git a/sites/all/modules/views/modules/field/views_handler_filter_field_list.inc b/sites/all/modules/views/modules/field/views_handler_filter_field_list.inc index dcae18164..971fb353e 100644 --- a/sites/all/modules/views/modules/field/views_handler_filter_field_list.inc +++ b/sites/all/modules/views/modules/field/views_handler_filter_field_list.inc @@ -1,5 +1,10 @@ <?php +/** + * Filter handler which uses list-fields as options. + * + * @ingroup views_filter_handlers + */ class views_handler_filter_field_list extends views_handler_filter_in_operator { function get_value_options() { $field = field_info_field($this->definition['field_name']); diff --git a/sites/all/modules/views/modules/field/views_handler_relationship_entity_reverse.inc b/sites/all/modules/views/modules/field/views_handler_relationship_entity_reverse.inc index 72b54da0e..c83fa11fe 100644 --- a/sites/all/modules/views/modules/field/views_handler_relationship_entity_reverse.inc +++ b/sites/all/modules/views/modules/field/views_handler_relationship_entity_reverse.inc @@ -4,6 +4,11 @@ * Views' relationship handlers. */ +/** + * A relationship handlers which reverse entity references. + * + * @ingroup views_relationship_handlers + */ class views_handler_relationship_entity_reverse extends views_handler_relationship { function init(&$view, &$options) { parent::init($view, $options); diff --git a/sites/all/modules/views/modules/filter/views_handler_field_filter_format_name.inc b/sites/all/modules/views/modules/filter/views_handler_field_filter_format_name.inc index dec6dacc7..9b7b4570b 100644 --- a/sites/all/modules/views/modules/filter/views_handler_field_filter_format_name.inc +++ b/sites/all/modules/views/modules/filter/views_handler_field_filter_format_name.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to output the name of an input format. + * + * @ingroup views_field_handlers */ class views_handler_field_filter_format_name extends views_handler_field { function construct() { diff --git a/sites/all/modules/views/modules/locale/views_handler_argument_locale_group.inc b/sites/all/modules/views/modules/locale/views_handler_argument_locale_group.inc index 0b092b401..152556034 100644 --- a/sites/all/modules/views/modules/locale/views_handler_argument_locale_group.inc +++ b/sites/all/modules/views/modules/locale/views_handler_argument_locale_group.inc @@ -2,6 +2,8 @@ /** * Argument handler to accept a language. + * + * @ingroup views_argument_handlers */ class views_handler_argument_locale_group extends views_handler_argument { function construct() { diff --git a/sites/all/modules/views/modules/locale/views_handler_argument_locale_language.inc b/sites/all/modules/views/modules/locale/views_handler_argument_locale_language.inc index 42afbe78c..8d4f38c76 100644 --- a/sites/all/modules/views/modules/locale/views_handler_argument_locale_language.inc +++ b/sites/all/modules/views/modules/locale/views_handler_argument_locale_language.inc @@ -2,6 +2,8 @@ /** * Argument handler to accept a language. + * + * @ingroup views_argument_handlers */ class views_handler_argument_locale_language extends views_handler_argument { function construct() { diff --git a/sites/all/modules/views/modules/locale/views_handler_field_locale_group.inc b/sites/all/modules/views/modules/locale/views_handler_field_locale_group.inc index a8e7a32e9..22339e81f 100644 --- a/sites/all/modules/views/modules/locale/views_handler_field_locale_group.inc +++ b/sites/all/modules/views/modules/locale/views_handler_field_locale_group.inc @@ -2,6 +2,8 @@ /** * Field handler to translate a group into its readable form. + * + * @ingroup views_field_handlers */ class views_handler_field_locale_group extends views_handler_field { function render($values) { diff --git a/sites/all/modules/views/modules/locale/views_handler_field_locale_language.inc b/sites/all/modules/views/modules/locale/views_handler_field_locale_language.inc index 140c23adf..0ff36a877 100644 --- a/sites/all/modules/views/modules/locale/views_handler_field_locale_language.inc +++ b/sites/all/modules/views/modules/locale/views_handler_field_locale_language.inc @@ -2,6 +2,8 @@ /** * Field handler to translate a language into its readable form. + * + * @ingroup views_field_handlers */ class views_handler_field_locale_language extends views_handler_field { function option_definition() { diff --git a/sites/all/modules/views/modules/locale/views_handler_field_locale_link_edit.inc b/sites/all/modules/views/modules/locale/views_handler_field_locale_link_edit.inc index 271f858e6..6c8f8f420 100644 --- a/sites/all/modules/views/modules/locale/views_handler_field_locale_link_edit.inc +++ b/sites/all/modules/views/modules/locale/views_handler_field_locale_link_edit.inc @@ -2,6 +2,8 @@ /** * Field handler to present a link to edit a translation. + * + * @ingroup views_field_handlers */ class views_handler_field_locale_link_edit extends views_handler_field { function construct() { diff --git a/sites/all/modules/views/modules/locale/views_handler_filter_locale_group.inc b/sites/all/modules/views/modules/locale/views_handler_filter_locale_group.inc index 75820edfe..1941549b2 100644 --- a/sites/all/modules/views/modules/locale/views_handler_filter_locale_group.inc +++ b/sites/all/modules/views/modules/locale/views_handler_filter_locale_group.inc @@ -2,6 +2,8 @@ /** * Filter by locale group. + * + * @ingroup views_filter_handlers */ class views_handler_filter_locale_group extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/modules/locale/views_handler_filter_locale_language.inc b/sites/all/modules/views/modules/locale/views_handler_filter_locale_language.inc index ed18bce11..9c7ba9098 100644 --- a/sites/all/modules/views/modules/locale/views_handler_filter_locale_language.inc +++ b/sites/all/modules/views/modules/locale/views_handler_filter_locale_language.inc @@ -2,6 +2,8 @@ /** * Filter by language. + * + * @ingroup views_filter_handlers */ class views_handler_filter_locale_language extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/modules/locale/views_handler_filter_locale_version.inc b/sites/all/modules/views/modules/locale/views_handler_filter_locale_version.inc index 7a472cf7b..d828b2c7f 100644 --- a/sites/all/modules/views/modules/locale/views_handler_filter_locale_version.inc +++ b/sites/all/modules/views/modules/locale/views_handler_filter_locale_version.inc @@ -2,6 +2,8 @@ /** * Filter by version. + * + * @ingroup views_filter_handlers */ class views_handler_filter_locale_version extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/modules/node.views.inc b/sites/all/modules/views/modules/node.views.inc index 917df0cef..bff3544da 100644 --- a/sites/all/modules/views/modules/node.views.inc +++ b/sites/all/modules/views/modules/node.views.inc @@ -692,6 +692,7 @@ function node_views_query_substitutions() { return array( '***ADMINISTER_NODES***' => intval(user_access('administer nodes')), '***VIEW_OWN_UNPUBLISHED_NODES***' => intval(user_access('view own unpublished content')), + '***BYPASS_NODE_ACCESS***' => intval(user_access('bypass node access')), ); } diff --git a/sites/all/modules/views/modules/node.views_template.inc b/sites/all/modules/views/modules/node.views_template.inc index 67b1986d3..ca0ed75bb 100644 --- a/sites/all/modules/views/modules/node.views_template.inc +++ b/sites/all/modules/views/modules/node.views_template.inc @@ -15,7 +15,7 @@ function node_views_templates() { $view->base_table = 'node'; $view->human_name = 'Image Gallery'; $view->core = 7; - $view->api_version = '3.0-alpha1'; + $view->api_version = '3.0'; $view->disabled = TRUE; /* Edit this to true to make a default view disabled initially */ /* Display: Defaults */ diff --git a/sites/all/modules/views/modules/node/views_handler_field_history_user_timestamp.inc b/sites/all/modules/views/modules/node/views_handler_field_history_user_timestamp.inc index 196d443ca..45f6c5684 100644 --- a/sites/all/modules/views/modules/node/views_handler_field_history_user_timestamp.inc +++ b/sites/all/modules/views/modules/node/views_handler_field_history_user_timestamp.inc @@ -3,6 +3,8 @@ * Field handler to display the marker for new content. * * The handler is named history_user, because of compability reasons, the table is history. + * + * @ingroup views_field_handlers */ class views_handler_field_history_user_timestamp extends views_handler_field_node { function init(&$view, &$options) { diff --git a/sites/all/modules/views/modules/node/views_handler_field_node.inc b/sites/all/modules/views/modules/node/views_handler_field_node.inc index 49ac468c9..eb90f0136 100644 --- a/sites/all/modules/views/modules/node/views_handler_field_node.inc +++ b/sites/all/modules/views/modules/node/views_handler_field_node.inc @@ -8,13 +8,15 @@ * Field handler to provide simple renderer that allows linking to a node. * Definition terms: * - link_to_node default: Should this field have the checkbox "link to node" enabled by default. + * + * @ingroup views_field_handlers */ class views_handler_field_node extends views_handler_field { function init(&$view, &$options) { parent::init($view, $options); // Don't add the additional fields to groupby - if (!empty($this->options['link_to_node']) && !$this->view->display_handler->use_group_by()) { + if (!empty($this->options['link_to_node'])) { $this->additional_fields['nid'] = array('table' => 'node', 'field' => 'nid'); if (module_exists('translation')) { $this->additional_fields['language'] = array('table' => 'node', 'field' => 'language'); diff --git a/sites/all/modules/views/modules/node/views_handler_field_node_link.inc b/sites/all/modules/views/modules/node/views_handler_field_node_link.inc index 8bff50a4d..ee9c2b9e4 100644 --- a/sites/all/modules/views/modules/node/views_handler_field_node_link.inc +++ b/sites/all/modules/views/modules/node/views_handler_field_node_link.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to present a link to the node. + * + * @ingroup views_field_handlers */ class views_handler_field_node_link extends views_handler_field_entity { diff --git a/sites/all/modules/views/modules/node/views_handler_field_node_link_delete.inc b/sites/all/modules/views/modules/node/views_handler_field_node_link_delete.inc index 274886201..3e8075cb9 100644 --- a/sites/all/modules/views/modules/node/views_handler_field_node_link_delete.inc +++ b/sites/all/modules/views/modules/node/views_handler_field_node_link_delete.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to present a link to delete a node. + * + * @ingroup views_field_handlers */ class views_handler_field_node_link_delete extends views_handler_field_node_link { diff --git a/sites/all/modules/views/modules/node/views_handler_field_node_link_edit.inc b/sites/all/modules/views/modules/node/views_handler_field_node_link_edit.inc index de9e8a49c..f082c3149 100644 --- a/sites/all/modules/views/modules/node/views_handler_field_node_link_edit.inc +++ b/sites/all/modules/views/modules/node/views_handler_field_node_link_edit.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to present a link node edit. + * + * @ingroup views_field_handlers */ class views_handler_field_node_link_edit extends views_handler_field_node_link { diff --git a/sites/all/modules/views/modules/node/views_handler_field_node_path.inc b/sites/all/modules/views/modules/node/views_handler_field_node_path.inc index b0cc5fb8c..725869ba2 100644 --- a/sites/all/modules/views/modules/node/views_handler_field_node_path.inc +++ b/sites/all/modules/views/modules/node/views_handler_field_node_path.inc @@ -7,6 +7,8 @@ /** * Field handler to present the path to the node. + * + * @ingroup views_field_handlers */ class views_handler_field_node_path extends views_handler_field { diff --git a/sites/all/modules/views/modules/node/views_handler_field_node_revision.inc b/sites/all/modules/views/modules/node/views_handler_field_node_revision.inc index f4ca17d45..3195e64ea 100644 --- a/sites/all/modules/views/modules/node/views_handler_field_node_revision.inc +++ b/sites/all/modules/views/modules/node/views_handler_field_node_revision.inc @@ -1,9 +1,13 @@ <?php /** - * @file * Contains the basic 'node_revision' field handler. */ +/** + * A basic node_revision handler. + * + * @ingroup views_field_handlers + */ class views_handler_field_node_revision extends views_handler_field_node { function init(&$view, &$options) { parent::init($view, $options); diff --git a/sites/all/modules/views/modules/node/views_handler_field_node_revision_link_delete.inc b/sites/all/modules/views/modules/node/views_handler_field_node_revision_link_delete.inc index 87000caa4..b005c2e0e 100644 --- a/sites/all/modules/views/modules/node/views_handler_field_node_revision_link_delete.inc +++ b/sites/all/modules/views/modules/node/views_handler_field_node_revision_link_delete.inc @@ -1,14 +1,13 @@ <?php /** * Field handler to present delete a node revision. + * + * @ingroup views_field_handlers */ class views_handler_field_node_revision_link_delete extends views_handler_field_node_link { function construct() { parent::construct(); - $this->additional_fields['uid'] = array('table' => 'node', 'field' => 'uid'); $this->additional_fields['node_vid'] = array('table' => 'node', 'field' => 'vid'); - $this->additional_fields['vid'] = 'vid'; - $this->additional_fields['type'] = array('table' => 'node', 'field' => 'type'); } function access() { @@ -17,11 +16,7 @@ class views_handler_field_node_revision_link_delete extends views_handler_field_ function render_link($data, $values) { // ensure user has access to delete this node. - $node = new stdClass(); - $node->nid = $this->get_value($values, 'nid'); - $node->vid = $this->get_value($values, 'vid'); - $node->uid = $this->get_value($values, 'uid'); - $node->type = $this->get_value($values, 'type'); + $node = $this->get_value($values); $node->status = 1; // unpublished nodes ignore access control if (!node_access('delete', $node)) { return; diff --git a/sites/all/modules/views/modules/node/views_handler_field_node_revision_link_revert.inc b/sites/all/modules/views/modules/node/views_handler_field_node_revision_link_revert.inc index a7fcb7371..f26c0a3ae 100644 --- a/sites/all/modules/views/modules/node/views_handler_field_node_revision_link_revert.inc +++ b/sites/all/modules/views/modules/node/views_handler_field_node_revision_link_revert.inc @@ -1,13 +1,13 @@ <?php /** - * Field handler to present a link to revert a node to a revision + * Field handler to present a link to revert a node to a revision. + * + * @ingroup views_field_handlers */ class views_handler_field_node_revision_link_revert extends views_handler_field_node_link { function construct() { parent::construct(); - $this->additional_fields['uid'] = array('table' => 'node', 'field' => 'uid'); $this->additional_fields['node_vid'] = array('table' => 'node', 'field' => 'vid'); - $this->additional_fields['vid'] = 'vid'; } function access() { @@ -16,10 +16,7 @@ class views_handler_field_node_revision_link_revert extends views_handler_field_ function render_link($data, $values) { // ensure user has access to edit this node. - $node = new stdClass(); - $node->nid = $this->get_value($values, 'nid'); - $node->vid = $this->get_value($values, 'vid'); - $node->uid = $this->get_value($values, 'uid'); + $node = $this->get_value($values); $node->status = 1; // unpublished nodes ignore access control if (!node_access('update', $node)) { return; diff --git a/sites/all/modules/views/modules/node/views_handler_field_node_type.inc b/sites/all/modules/views/modules/node/views_handler_field_node_type.inc index 3c8f66f18..6d6202afb 100644 --- a/sites/all/modules/views/modules/node/views_handler_field_node_type.inc +++ b/sites/all/modules/views/modules/node/views_handler_field_node_type.inc @@ -2,6 +2,8 @@ /** * Field handler to translate a node type into its readable form. + * + * @ingroup views_field_handlers */ class views_handler_field_node_type extends views_handler_field_node { function option_definition() { diff --git a/sites/all/modules/views/modules/node/views_handler_filter_history_user_timestamp.inc b/sites/all/modules/views/modules/node/views_handler_filter_history_user_timestamp.inc index f725b4c8f..a13f5319d 100644 --- a/sites/all/modules/views/modules/node/views_handler_filter_history_user_timestamp.inc +++ b/sites/all/modules/views/modules/node/views_handler_filter_history_user_timestamp.inc @@ -3,6 +3,8 @@ * Filter for new content * * The handler is named history_user, because of compability reasons, the table is history. + * + * @ingroup views_filter_handlers */ class views_handler_filter_history_user_timestamp extends views_handler_filter { // Don't display empty space where the operator would be. diff --git a/sites/all/modules/views/modules/node/views_handler_filter_node_access.inc b/sites/all/modules/views/modules/node/views_handler_filter_node_access.inc index 333b9b2b9..37306f8af 100644 --- a/sites/all/modules/views/modules/node/views_handler_filter_node_access.inc +++ b/sites/all/modules/views/modules/node/views_handler_filter_node_access.inc @@ -1,6 +1,8 @@ <?php /** * Filter by node_access records. + * + * @ingroup views_filter_handlers */ class views_handler_filter_node_access extends views_handler_filter { function admin_summary() { } diff --git a/sites/all/modules/views/modules/node/views_handler_filter_node_status.inc b/sites/all/modules/views/modules/node/views_handler_filter_node_status.inc index 2b79b9e95..0babe5b28 100644 --- a/sites/all/modules/views/modules/node/views_handler_filter_node_status.inc +++ b/sites/all/modules/views/modules/node/views_handler_filter_node_status.inc @@ -1,6 +1,8 @@ <?php /** * Filter by published status + * + * @ingroup views_filter_handlers */ class views_handler_filter_node_status extends views_handler_filter { function admin_summary() { } @@ -9,6 +11,6 @@ class views_handler_filter_node_status extends views_handler_filter { function query() { $table = $this->ensure_my_table(); - $this->query->add_where_expression($this->options['group'], "$table.status = 1 OR ($table.uid = ***CURRENT_USER*** AND ***CURRENT_USER*** <> 0 AND ***VIEW_OWN_UNPUBLISHED_NODES*** = 1) OR ***ADMINISTER_NODES*** = 1"); + $this->query->add_where_expression($this->options['group'], "$table.status = 1 OR ($table.uid = ***CURRENT_USER*** AND ***CURRENT_USER*** <> 0 AND ***VIEW_OWN_UNPUBLISHED_NODES*** = 1) OR ***BYPASS_NODE_ACCESS*** = 1"); } } diff --git a/sites/all/modules/views/modules/node/views_handler_filter_node_type.inc b/sites/all/modules/views/modules/node/views_handler_filter_node_type.inc index c287697c0..83126915b 100644 --- a/sites/all/modules/views/modules/node/views_handler_filter_node_type.inc +++ b/sites/all/modules/views/modules/node/views_handler_filter_node_type.inc @@ -1,6 +1,8 @@ <?php /** * Filter by node type + * + * @ingroup views_filter_handlers */ class views_handler_filter_node_type extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/modules/node/views_handler_filter_node_uid_revision.inc b/sites/all/modules/views/modules/node/views_handler_filter_node_uid_revision.inc index 56441b55e..9c6055c4f 100644 --- a/sites/all/modules/views/modules/node/views_handler_filter_node_uid_revision.inc +++ b/sites/all/modules/views/modules/node/views_handler_filter_node_uid_revision.inc @@ -1,8 +1,13 @@ <?php -// $Id$ /** * @file + * Contains handler views_handler_filter_node_uid_revision. + */ + +/** * Filter handler to check for revisions a certain user has created. + * + * @ingroup views_filter_handlers */ class views_handler_filter_node_uid_revision extends views_handler_filter_user_name { function query($group_by = FALSE) { diff --git a/sites/all/modules/views/modules/node/views_plugin_row_node_rss.inc b/sites/all/modules/views/modules/node/views_plugin_row_node_rss.inc index c1086ccb2..189ff1f2e 100644 --- a/sites/all/modules/views/modules/node/views_plugin_row_node_rss.inc +++ b/sites/all/modules/views/modules/node/views_plugin_row_node_rss.inc @@ -25,6 +25,17 @@ class views_plugin_row_node_rss extends views_plugin_row { return $options; } + /** + * Override init function to convert fulltext view-mode to full. + */ + function init(&$view, &$display, $options = NULL) { + parent::init($view, $display, $options); + + if ($this->options['item_length'] == 'fulltext') { + $this->options['item_length'] = 'full'; + } + } + function options_form(&$form, &$form_state) { parent::options_form($form, $form_state); @@ -45,12 +56,16 @@ class views_plugin_row_node_rss extends views_plugin_row { * Return the main options, which are shown in the summary title. */ function options_form_summary_options() { - return array( - 'fulltext' => t('Full text'), - 'teaser' => t('Title plus teaser'), - 'title' => t('Title only'), - 'default' => t('Use default RSS settings'), - ); + $entity_info = entity_get_info('node'); + $options = array(); + if (!empty($entity_info['view modes'])) { + foreach ($entity_info['view modes'] as $mode => $settings) { + $options[$mode] = $settings['label']; + } + } + $options['title'] = t('Title only'); + $options['default'] = t('Use site default RSS settings'); + return $options; } function summary_title() { @@ -78,9 +93,9 @@ class views_plugin_row_node_rss extends views_plugin_row { return; } - $item_length = $this->options['item_length']; - if ($item_length == 'default') { - $item_length = variable_get('feed_item_length', 'teaser'); + $display_mode = $this->options['item_length']; + if ($display_mode == 'default') { + $display_mode = variable_get('feed_item_length', 'teaser'); } // Load the specified node: @@ -112,11 +127,16 @@ class views_plugin_row_node_rss extends views_plugin_row { // The node gets built and modules add to or modify $node->rss_elements // and $node->rss_namespaces. - $build = node_view($node, 'rss'); + + $build_mode = $display_mode; + + $build = node_view($node, $build_mode); unset($build['#theme']); if (!empty($node->rss_namespaces)) { $this->view->style_plugin->namespaces = array_merge($this->view->style_plugin->namespaces, $node->rss_namespaces); + } else if (module_exists('rdf')) { + $this->view->style_plugin->namespaces = array_merge($this->view->style_plugin->namespaces, rdf_get_namespaces()); } // Hide the links if desired. @@ -124,7 +144,7 @@ class views_plugin_row_node_rss extends views_plugin_row { hide($build['links']); } - if ($item_length != 'title') { + if ($display_mode != 'title') { // We render node contents and force links to be last. $build['links']['#weight'] = 1000; $item_text .= drupal_render($build); diff --git a/sites/all/modules/views/modules/node/views_plugin_row_node_view.inc b/sites/all/modules/views/modules/node/views_plugin_row_node_view.inc index 040e7bd4b..d745addd0 100644 --- a/sites/all/modules/views/modules/node/views_plugin_row_node_view.inc +++ b/sites/all/modules/views/modules/node/views_plugin_row_node_view.inc @@ -8,6 +8,8 @@ * Plugin which performs a node_view on the resulting object. * * Most of the code on this object is in the theme function. + * + * @ingroup views_row_plugins */ class views_plugin_row_node_view extends views_plugin_row { // Basic properties that let the row style follow relationships. diff --git a/sites/all/modules/views/modules/profile/views_handler_field_profile_date.inc b/sites/all/modules/views/modules/profile/views_handler_field_profile_date.inc index 6c1cc6684..e6b5fbc14 100644 --- a/sites/all/modules/views/modules/profile/views_handler_field_profile_date.inc +++ b/sites/all/modules/views/modules/profile/views_handler_field_profile_date.inc @@ -4,6 +4,8 @@ * * The dates are stored serialized, which makes them mostly useless from * SQL. About all we can do is unserialize and display them. + * + * @ingroup views_field_handlers */ class views_handler_field_profile_date extends views_handler_field_date { function options_form(&$form, &$form_state) { diff --git a/sites/all/modules/views/modules/profile/views_handler_field_profile_list.inc b/sites/all/modules/views/modules/profile/views_handler_field_profile_list.inc index bb09015dd..e3eaa30f2 100644 --- a/sites/all/modules/views/modules/profile/views_handler_field_profile_list.inc +++ b/sites/all/modules/views/modules/profile/views_handler_field_profile_list.inc @@ -1,6 +1,8 @@ <?php /** * Field handler display a profile list item. + * + * @ingroup views_field_handlers */ class views_handler_field_profile_list extends views_handler_field_prerender_list { /** diff --git a/sites/all/modules/views/modules/profile/views_handler_filter_profile_selection.inc b/sites/all/modules/views/modules/profile/views_handler_filter_profile_selection.inc index 77c34f433..99067535d 100644 --- a/sites/all/modules/views/modules/profile/views_handler_filter_profile_selection.inc +++ b/sites/all/modules/views/modules/profile/views_handler_filter_profile_selection.inc @@ -2,6 +2,8 @@ /** * Filter by a selection widget in the profile. + * + * @ingroup views_filter_handlers */ class views_handler_filter_profile_selection extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/modules/search/views_handler_argument_search.inc b/sites/all/modules/views/modules/search/views_handler_argument_search.inc index 7fbdebb38..1b2c6e565 100644 --- a/sites/all/modules/views/modules/search/views_handler_argument_search.inc +++ b/sites/all/modules/views/modules/search/views_handler_argument_search.inc @@ -2,6 +2,8 @@ /** * Argument that accepts query keys for search. + * + * @ingroup views_argument_handlers */ class views_handler_argument_search extends views_handler_argument { diff --git a/sites/all/modules/views/modules/search/views_handler_field_search_score.inc b/sites/all/modules/views/modules/search/views_handler_field_search_score.inc index b3d6fe3ab..96f124dbf 100644 --- a/sites/all/modules/views/modules/search/views_handler_field_search_score.inc +++ b/sites/all/modules/views/modules/search/views_handler_field_search_score.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to provide simple renderer that allows linking to a node. + * + * @ingroup views_field_handlers */ class views_handler_field_search_score extends views_handler_field_numeric { function option_definition() { diff --git a/sites/all/modules/views/modules/search/views_handler_filter_search.inc b/sites/all/modules/views/modules/search/views_handler_filter_search.inc index 4ed228dac..c5defd816 100644 --- a/sites/all/modules/views/modules/search/views_handler_filter_search.inc +++ b/sites/all/modules/views/modules/search/views_handler_filter_search.inc @@ -2,6 +2,8 @@ /** * Field handler to provide simple renderer that allows linking to a node. + * + * @ingroup views_filter_handlers */ class views_handler_filter_search extends views_handler_filter { var $always_multiple = TRUE; diff --git a/sites/all/modules/views/modules/search/views_handler_sort_search_score.inc b/sites/all/modules/views/modules/search/views_handler_sort_search_score.inc index b34a60bb4..614d83acc 100644 --- a/sites/all/modules/views/modules/search/views_handler_sort_search_score.inc +++ b/sites/all/modules/views/modules/search/views_handler_sort_search_score.inc @@ -2,6 +2,8 @@ /** * Field handler to provide simple renderer that allows linking to a node. + * + * @ingroup views_sort_handlers */ class views_handler_sort_search_score extends views_handler_sort { function query() { diff --git a/sites/all/modules/views/modules/statistics/views_handler_field_accesslog_path.inc b/sites/all/modules/views/modules/statistics/views_handler_field_accesslog_path.inc index 674eb34cb..d0daa6941 100644 --- a/sites/all/modules/views/modules/statistics/views_handler_field_accesslog_path.inc +++ b/sites/all/modules/views/modules/statistics/views_handler_field_accesslog_path.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to provide simple renderer that turns a URL into a clickable link. + * + * @ingroup views_field_handlers */ class views_handler_field_accesslog_path extends views_handler_field { /** diff --git a/sites/all/modules/views/modules/system.views.inc b/sites/all/modules/views/modules/system.views.inc index d7975cdc0..d49385cf6 100644 --- a/sites/all/modules/views/modules/system.views.inc +++ b/sites/all/modules/views/modules/system.views.inc @@ -253,7 +253,7 @@ function system_views_data() { 'base' => 'node', 'base field' => 'nid', 'relationship field' => 'id', - 'extra' => array(array('table' => 'file_usage', 'field' => 'type', 'operator' => '=', 'value' => 'node')), + 'extra' => array(array('field' => 'type', 'value' => 'node')), ), ); $data['file_usage']['node_to_file'] = array( diff --git a/sites/all/modules/views/modules/system/views_handler_argument_file_fid.inc b/sites/all/modules/views/modules/system/views_handler_argument_file_fid.inc index f24f0920c..8a4088f81 100644 --- a/sites/all/modules/views/modules/system/views_handler_argument_file_fid.inc +++ b/sites/all/modules/views/modules/system/views_handler_argument_file_fid.inc @@ -1,6 +1,8 @@ <?php /** * Argument handler to accept multiple file ids. + * + * @ingroup views_argument_handlers */ class views_handler_argument_file_fid extends views_handler_argument_numeric { /** diff --git a/sites/all/modules/views/modules/system/views_handler_field_file.inc b/sites/all/modules/views/modules/system/views_handler_field_file.inc index aeef6ad9a..f642b8913 100644 --- a/sites/all/modules/views/modules/system/views_handler_field_file.inc +++ b/sites/all/modules/views/modules/system/views_handler_field_file.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to provide simple renderer that allows linking to a file. + * + * @ingroup views_field_handlers */ class views_handler_field_file extends views_handler_field { /** diff --git a/sites/all/modules/views/modules/system/views_handler_field_file_extension.inc b/sites/all/modules/views/modules/system/views_handler_field_file_extension.inc index f26dee868..e64fbc91d 100644 --- a/sites/all/modules/views/modules/system/views_handler_field_file_extension.inc +++ b/sites/all/modules/views/modules/system/views_handler_field_file_extension.inc @@ -1,9 +1,9 @@ <?php + /** - * @file * Returns a pure file extension of the file, for example 'module'. + * @ingroup views_field_handlers */ - class views_handler_field_file_extension extends views_handler_field { function render($values) { $value = $this->get_value($values); diff --git a/sites/all/modules/views/modules/system/views_handler_field_file_filemime.inc b/sites/all/modules/views/modules/system/views_handler_field_file_filemime.inc index 74dba9ef2..0b29c79a2 100644 --- a/sites/all/modules/views/modules/system/views_handler_field_file_filemime.inc +++ b/sites/all/modules/views/modules/system/views_handler_field_file_filemime.inc @@ -2,6 +2,8 @@ /** * Field handler to add rendering MIME type images as an option on the filemime field. + * + * @ingroup views_field_handlers */ class views_handler_field_file_filemime extends views_handler_field_file { function option_definition() { diff --git a/sites/all/modules/views/modules/system/views_handler_field_file_status.inc b/sites/all/modules/views/modules/system/views_handler_field_file_status.inc index 8b42aa809..84d9148aa 100644 --- a/sites/all/modules/views/modules/system/views_handler_field_file_status.inc +++ b/sites/all/modules/views/modules/system/views_handler_field_file_status.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to translate a node type into its readable form. + * + * @ingroup views_field_handlers */ class views_handler_field_file_status extends views_handler_field { function render($values) { diff --git a/sites/all/modules/views/modules/system/views_handler_filter_file_status.inc b/sites/all/modules/views/modules/system/views_handler_filter_file_status.inc index e24531a51..31337550f 100644 --- a/sites/all/modules/views/modules/system/views_handler_filter_file_status.inc +++ b/sites/all/modules/views/modules/system/views_handler_filter_file_status.inc @@ -1,6 +1,8 @@ <?php /** - * Filter by file status + * Filter by file status. + * + * @ingroup views_filter_handlers */ class views_handler_filter_file_status extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/modules/taxonomy.views.inc b/sites/all/modules/views/modules/taxonomy.views.inc index 5dcbc18e8..7dd225bbd 100644 --- a/sites/all/modules/views/modules/taxonomy.views.inc +++ b/sites/all/modules/views/modules/taxonomy.views.inc @@ -214,6 +214,9 @@ function taxonomy_views_data() { 'handler' => 'views_handler_field_markup', 'format' => array('field' => 'format'), ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), ); // Term vocabulary diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_argument_taxonomy.inc b/sites/all/modules/views/modules/taxonomy/views_handler_argument_taxonomy.inc index 7f14e4d21..5c32ea4c2 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_argument_taxonomy.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_argument_taxonomy.inc @@ -2,6 +2,8 @@ /** * Argument handler for basic taxonomy tid. + * + * @ingroup views_argument_handlers */ class views_handler_argument_taxonomy extends views_handler_argument_numeric { diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_argument_term_node_tid.inc b/sites/all/modules/views/modules/taxonomy/views_handler_argument_term_node_tid.inc index cf83d46ef..e36c7789a 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_argument_term_node_tid.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_argument_term_node_tid.inc @@ -1,6 +1,8 @@ <?php /** - * Allow taxonomy term ID(s) as argument + * Allow taxonomy term ID(s) as argument. + * + * @ingroup views_argument_handlers */ class views_handler_argument_term_node_tid extends views_handler_argument_many_to_one { function option_definition() { diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_argument_term_node_tid_depth.inc b/sites/all/modules/views/modules/taxonomy/views_handler_argument_term_node_tid_depth.inc index ab519612f..03b14099a 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_argument_term_node_tid_depth.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_argument_term_node_tid_depth.inc @@ -3,7 +3,9 @@ * Argument handler for taxonomy terms with depth. * * This handler is actually part of the node table and has some restrictions, - * because it uses a subquery to find nodes with + * because it uses a subquery to find nodes with. + * + * @ingroup views_argument_handlers */ class views_handler_argument_term_node_tid_depth extends views_handler_argument { function option_definition() { diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_argument_term_node_tid_depth_modifier.inc b/sites/all/modules/views/modules/taxonomy/views_handler_argument_term_node_tid_depth_modifier.inc index 3f3186499..da717962d 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_argument_term_node_tid_depth_modifier.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_argument_term_node_tid_depth_modifier.inc @@ -4,7 +4,9 @@ * Argument handler for to modify depth for a previous term. * * This handler is actually part of the node table and has some restrictions, - * because it uses a subquery to find nodes with + * because it uses a subquery to find nodes with. + * + * @ingroup views_argument_handlers */ class views_handler_argument_term_node_tid_depth_modifier extends views_handler_argument { function options_form(&$form, &$form_state) { } diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_argument_vocabulary_machine_name.inc b/sites/all/modules/views/modules/taxonomy/views_handler_argument_vocabulary_machine_name.inc index 4999d274e..b91b08faf 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_argument_vocabulary_machine_name.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_argument_vocabulary_machine_name.inc @@ -2,6 +2,8 @@ /** * Argument handler to accept a vocabulary machine name. + * + * @ingroup views_argument_handlers */ class views_handler_argument_vocabulary_machine_name extends views_handler_argument_string { /** diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_argument_vocabulary_vid.inc b/sites/all/modules/views/modules/taxonomy/views_handler_argument_vocabulary_vid.inc index 5b6358822..d79859b86 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_argument_vocabulary_vid.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_argument_vocabulary_vid.inc @@ -2,6 +2,8 @@ /** * Argument handler to accept a vocabulary id. + * + * @ingroup views_argument_handlers */ class views_handler_argument_vocabulary_vid extends views_handler_argument_numeric { /** diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_field_taxonomy.inc b/sites/all/modules/views/modules/taxonomy/views_handler_field_taxonomy.inc index b910e395e..c1ccb6d69 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_field_taxonomy.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_field_taxonomy.inc @@ -3,6 +3,8 @@ /** * Field handler to provide simple renderer that allows linking to a taxonomy * term. + * + * @ingroup views_field_handlers */ class views_handler_field_taxonomy extends views_handler_field { /** diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_field_term_link_edit.inc b/sites/all/modules/views/modules/taxonomy/views_handler_field_term_link_edit.inc index 31cc0ea16..ae1f0a5c1 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_field_term_link_edit.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_field_term_link_edit.inc @@ -1,7 +1,9 @@ <?php /** - * Field handler to present a term edit link . + * Field handler to present a term edit link. + * + * @ingroup views_field_handlers */ class views_handler_field_term_link_edit extends views_handler_field { function construct() { diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_field_term_node_tid.inc b/sites/all/modules/views/modules/taxonomy/views_handler_field_term_node_tid.inc index e46add8c5..4a6c7a449 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_field_term_node_tid.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_field_term_node_tid.inc @@ -1,8 +1,9 @@ <?php /** - * @file * Field handler to display all taxonomy terms of a node. + * + * @ingroup views_field_handlers */ class views_handler_field_term_node_tid extends views_handler_field_prerender_list { function init(&$view, &$options) { diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_filter_term_node_tid.inc b/sites/all/modules/views/modules/taxonomy/views_handler_filter_term_node_tid.inc index 5e0467342..25f9a7bcd 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_filter_term_node_tid.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_filter_term_node_tid.inc @@ -1,9 +1,14 @@ <?php /** - * Filter by term id + * Filter by term id. + * + * @ingroup views_filter_handlers */ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_one { + // Stores the exposed input for this filter. + var $validated_exposed_input = NULL; + function init(&$view, &$options) { parent::init($view, $options); if (!empty($this->definition['vocabulary'])) { @@ -11,7 +16,7 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on } // Convert legacy vid option to machine name vocabulary. - if (!empty($this->options['vid']) & empty($this->options['vocabulary'])) { + if (isset($this->options['vid']) && !empty($this->options['vid']) & empty($this->options['vocabulary'])) { $vocabularies = taxonomy_get_vocabularies(); $vid = $this->options['vid']; if (isset($vocabularies[$vid], $vocabularies[$vid]->machine_name)) { @@ -38,13 +43,14 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on function extra_options_form(&$form, &$form_state) { $vocabularies = taxonomy_get_vocabularies(); + $options = array(); foreach ($vocabularies as $voc) { $options[$voc->machine_name] = check_plain($voc->name); } if ($this->options['limit']) { // We only do this when the form is displayed. - if ($this->options['vocabulary'] == 0) { + if (empty($this->options['vocabulary'])) { $first_vocabulary = reset($vocabularies); $this->options['vocabulary'] = $first_vocabulary->machine_name; } @@ -177,7 +183,7 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on '#default_value' => $default_value, ); - if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier])) { + if (!empty($form_state['exposed']) && isset($identifier) && !isset($form_state['input'][$identifier])) { $form_state['input'][$identifier] = $default_value; } } @@ -261,6 +267,14 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on * Validate the user string. Since this can come from either the form * or the exposed filter, this is abstracted out a bit so it can * handle the multiple input sources. + * + * @param $form + * The form which is used, either the views ui or the exposed filters. + * @param $values + * The taxonomy names which will be converted to tids. + * + * @return array + * The taxonomy ids fo all validated terms. */ function validate_term_strings(&$form, $values) { if (empty($values)) { @@ -268,16 +282,15 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on } $tids = array(); - $placeholders = array(); - $args = array(); - $results = array(); + $names = array(); + $missing = array(); foreach ($values as $value) { $missing[strtolower($value)] = TRUE; $names[] = $value; } if (!$names) { - return; + return FALSE; } $query = db_select('taxonomy_term_data', 'td'); diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_filter_term_node_tid_depth.inc b/sites/all/modules/views/modules/taxonomy/views_handler_filter_term_node_tid_depth.inc index 96a991cc0..39552695f 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_filter_term_node_tid_depth.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_filter_term_node_tid_depth.inc @@ -3,7 +3,9 @@ * Filter handler for taxonomy terms with depth. * * This handler is actually part of the node table and has some restrictions, - * because it uses a subquery to find nodes with + * because it uses a subquery to find nodes with. + * + * @ingroup views_filter_handlers */ class views_handler_filter_term_node_tid_depth extends views_handler_filter_term_node_tid { function operator_options($which = 'title') { @@ -87,6 +89,6 @@ class views_handler_filter_term_node_tid_depth extends views_handler_filter_term } $subquery->condition($where); - $this->query->add_where(0, "$this->table_alias.$this->real_field", $subquery, 'IN'); + $this->query->add_where($this->options['group'], "$this->table_alias.$this->real_field", $subquery, 'IN'); } } diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_filter_vocabulary_machine_name.inc b/sites/all/modules/views/modules/taxonomy/views_handler_filter_vocabulary_machine_name.inc index e75d6a730..5d2c9f591 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_filter_vocabulary_machine_name.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_filter_vocabulary_machine_name.inc @@ -1,7 +1,9 @@ <?php /** - * Filter by vocabulary machine name + * Filter by vocabulary machine name. + * + * @ingroup views_filter_handlers */ class views_handler_filter_vocabulary_machine_name extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_filter_vocabulary_vid.inc b/sites/all/modules/views/modules/taxonomy/views_handler_filter_vocabulary_vid.inc index cb624dca2..a02f7b217 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_filter_vocabulary_vid.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_filter_vocabulary_vid.inc @@ -1,7 +1,9 @@ <?php /** - * Filter by vocabulary id + * Filter by vocabulary id. + * + * @ingroup views_filter_handlers */ class views_handler_filter_vocabulary_vid extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/modules/taxonomy/views_handler_relationship_node_term_data.inc b/sites/all/modules/views/modules/taxonomy/views_handler_relationship_node_term_data.inc index 2f013daf7..1855caee0 100644 --- a/sites/all/modules/views/modules/taxonomy/views_handler_relationship_node_term_data.inc +++ b/sites/all/modules/views/modules/taxonomy/views_handler_relationship_node_term_data.inc @@ -4,6 +4,12 @@ * Views' relationship handlers. */ + +/** + * Relationship handler to return the taxonomy terms of nodes. + * + * @ingroup views_relationship_handlers + */ class views_handler_relationship_node_term_data extends views_handler_relationship { function init(&$view, &$options) { parent::init($view, $options); diff --git a/sites/all/modules/views/modules/translation/views_handler_argument_node_tnid.inc b/sites/all/modules/views/modules/translation/views_handler_argument_node_tnid.inc index 483ce6f7f..9dd29a108 100644 --- a/sites/all/modules/views/modules/translation/views_handler_argument_node_tnid.inc +++ b/sites/all/modules/views/modules/translation/views_handler_argument_node_tnid.inc @@ -6,6 +6,8 @@ /** * Argument handler to accept a node translation id. + * + * @ingroup views_argument_handlers */ class views_handler_argument_node_tnid extends views_handler_argument_numeric { /** diff --git a/sites/all/modules/views/modules/translation/views_handler_field_node_language.inc b/sites/all/modules/views/modules/translation/views_handler_field_node_language.inc index 93bd88327..b2e8d9c38 100644 --- a/sites/all/modules/views/modules/translation/views_handler_field_node_language.inc +++ b/sites/all/modules/views/modules/translation/views_handler_field_node_language.inc @@ -2,6 +2,8 @@ /** * Field handler to translate a language into its readable form. + * + * @ingroup views_field_handlers */ class views_handler_field_node_language extends views_handler_field_node { function option_definition() { diff --git a/sites/all/modules/views/modules/translation/views_handler_field_node_link_translate.inc b/sites/all/modules/views/modules/translation/views_handler_field_node_link_translate.inc index 6e356ea28..962b4f939 100644 --- a/sites/all/modules/views/modules/translation/views_handler_field_node_link_translate.inc +++ b/sites/all/modules/views/modules/translation/views_handler_field_node_link_translate.inc @@ -1,22 +1,13 @@ <?php /** * Field handler to present a link node translate. + * + * @ingroup views_field_handlers */ class views_handler_field_node_link_translate extends views_handler_field_node_link { - function construct() { - parent::construct(); - $this->additional_fields['uid'] = 'uid'; - $this->additional_fields['type'] = 'type'; - $this->additional_fields['language'] = 'language'; - } - function render_link($data, $values) { // ensure user has access to edit this node. - $node = new stdClass(); - $node->nid = $this->get_value($values, 'nid'); - $node->uid = $this->get_value($values, 'uid'); - $node->type = $this->get_value($values, 'type'); - $node->language = $this->get_value($values, 'language'); + $node = $this->get_value($values); $node->status = 1; // unpublished nodes ignore access control if (empty($node->language) || !translation_supported_type($node->type) || !node_access('view', $node) || !user_access('translate content')) { return; diff --git a/sites/all/modules/views/modules/translation/views_handler_field_node_translation_link.inc b/sites/all/modules/views/modules/translation/views_handler_field_node_translation_link.inc index cefeec0b9..537ba6070 100644 --- a/sites/all/modules/views/modules/translation/views_handler_field_node_translation_link.inc +++ b/sites/all/modules/views/modules/translation/views_handler_field_node_translation_link.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to present a link to the node. + * + * @ingroup views_field_handlers */ class views_handler_field_node_translation_link extends views_handler_field { function construct() { diff --git a/sites/all/modules/views/modules/translation/views_handler_filter_node_language.inc b/sites/all/modules/views/modules/translation/views_handler_filter_node_language.inc index b4c17b9c9..73af1636a 100644 --- a/sites/all/modules/views/modules/translation/views_handler_filter_node_language.inc +++ b/sites/all/modules/views/modules/translation/views_handler_filter_node_language.inc @@ -1,6 +1,8 @@ <?php /** - * Filter by language + * Filter by language. + * + * @ingroup views_filter_handlers */ class views_handler_filter_node_language extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/modules/translation/views_handler_filter_node_tnid.inc b/sites/all/modules/views/modules/translation/views_handler_filter_node_tnid.inc index 460e16f06..6d8cfe7aa 100644 --- a/sites/all/modules/views/modules/translation/views_handler_filter_node_tnid.inc +++ b/sites/all/modules/views/modules/translation/views_handler_filter_node_tnid.inc @@ -1,6 +1,8 @@ <?php /** * Filter by whether the node is the original translation. + * + * @ingroup views_filter_handlers */ class views_handler_filter_node_tnid extends views_handler_filter { function admin_summary() { } diff --git a/sites/all/modules/views/modules/translation/views_handler_filter_node_tnid_child.inc b/sites/all/modules/views/modules/translation/views_handler_filter_node_tnid_child.inc index e1cda3ac9..f0d953b55 100644 --- a/sites/all/modules/views/modules/translation/views_handler_filter_node_tnid_child.inc +++ b/sites/all/modules/views/modules/translation/views_handler_filter_node_tnid_child.inc @@ -1,6 +1,8 @@ <?php /** * Filter by whether the node is not the original translation. + * + * @ingroup views_filter_handlers */ class views_handler_filter_node_tnid_child extends views_handler_filter { function admin_summary() { } diff --git a/sites/all/modules/views/modules/translation/views_handler_relationship_translation.inc b/sites/all/modules/views/modules/translation/views_handler_relationship_translation.inc index ab4713236..b7d26411d 100644 --- a/sites/all/modules/views/modules/translation/views_handler_relationship_translation.inc +++ b/sites/all/modules/views/modules/translation/views_handler_relationship_translation.inc @@ -3,6 +3,8 @@ /** * Handles relationships for content translation sets and provides multiple * options. + * + * @ingroup views_relationship_handlers */ class views_handler_relationship_translation extends views_handler_relationship { function option_definition() { diff --git a/sites/all/modules/views/modules/user.views.inc b/sites/all/modules/views/modules/user.views.inc index 8ecc8f5e6..1d7f16134 100644 --- a/sites/all/modules/views/modules/user.views.inc +++ b/sites/all/modules/views/modules/user.views.inc @@ -182,6 +182,15 @@ function user_views_data() { ), ); + // link + $data['users']['view_user'] = array( + 'field' => array( + 'title' => t('Link'), + 'help' => t('Provide a simple link to the user.'), + 'handler' => 'views_handler_field_user_link', + ), + ); + // created field $data['users']['created'] = array( 'title' => t('Created date'), // The item it appears as on the UI, @@ -293,6 +302,9 @@ function user_views_data() { 'field' => array( 'handler' => 'views_handler_field_boolean', 'click sortable' => TRUE, + 'output formats' => array( + 'active-blocked' => array(t('Active'), t('Blocked')), + ), ), 'filter' => array( 'handler' => 'views_handler_filter_boolean_operator', @@ -377,6 +389,7 @@ function user_views_data() { 'filter' => array( 'handler' => 'views_handler_filter_user_roles', 'numeric' => TRUE, + 'allow empty' => TRUE, ), 'argument' => array( 'handler' => 'views_handler_argument_users_roles_rid', @@ -513,6 +526,17 @@ function user_views_data() { function user_views_plugins() { return array( 'module' => 'views', // This just tells our themes are elsewhere. + 'row' => array( + 'user' => array( + 'title' => t('User'), + 'help' => t('Display the user with standard user view.'), + 'handler' => 'views_plugin_row_user_view', + 'base' => array('users'), // only works with 'users' as base. + 'uses options' => TRUE, + 'type' => 'normal', + 'help topic' => 'style-users', + ), + ), 'argument default' => array( 'user' => array( 'title' => t('User ID from URL'), diff --git a/sites/all/modules/views/modules/user/views_handler_argument_user_uid.inc b/sites/all/modules/views/modules/user/views_handler_argument_user_uid.inc index e5a7d1c7a..21785a9f8 100644 --- a/sites/all/modules/views/modules/user/views_handler_argument_user_uid.inc +++ b/sites/all/modules/views/modules/user/views_handler_argument_user_uid.inc @@ -6,10 +6,15 @@ /** * Argument handler to accept a user id. + * + * @ingroup views_argument_handlers */ class views_handler_argument_user_uid extends views_handler_argument_numeric { /** * Override the behavior of title(). Get the name of the user. + * + * @return array + * A list of usernames. */ function title_query() { if (!$this->argument) { diff --git a/sites/all/modules/views/modules/user/views_handler_argument_users_roles_rid.inc b/sites/all/modules/views/modules/user/views_handler_argument_users_roles_rid.inc index 0facece32..89b3704b0 100644 --- a/sites/all/modules/views/modules/user/views_handler_argument_users_roles_rid.inc +++ b/sites/all/modules/views/modules/user/views_handler_argument_users_roles_rid.inc @@ -1,6 +1,8 @@ <?php /** - * Allow role ID(s) as argument + * Allow role ID(s) as argument. + * + * @ingroup views_argument_handlers */ class views_handler_argument_users_roles_rid extends views_handler_argument_many_to_one { function title_query() { diff --git a/sites/all/modules/views/modules/user/views_handler_field_user.inc b/sites/all/modules/views/modules/user/views_handler_field_user.inc index e88033a9e..f90a6f9a9 100644 --- a/sites/all/modules/views/modules/user/views_handler_field_user.inc +++ b/sites/all/modules/views/modules/user/views_handler_field_user.inc @@ -2,6 +2,8 @@ /** * Field handler to provide simple renderer that allows linking to a user. + * + * @ingroup views_field_handlers */ class views_handler_field_user extends views_handler_field { /** diff --git a/sites/all/modules/views/modules/user/views_handler_field_user_language.inc b/sites/all/modules/views/modules/user/views_handler_field_user_language.inc index 3d3e72287..96b784b00 100644 --- a/sites/all/modules/views/modules/user/views_handler_field_user_language.inc +++ b/sites/all/modules/views/modules/user/views_handler_field_user_language.inc @@ -1,9 +1,10 @@ <?php + /** - * @file - * Views field handler for userlanguage. + * Views field handler for user language. + * + * @ingroup views_field_handlers */ - class views_handler_field_user_language extends views_handler_field_user { function render_link($data, $values) { diff --git a/sites/all/modules/views/modules/user/views_handler_field_user_link.inc b/sites/all/modules/views/modules/user/views_handler_field_user_link.inc index 7f26f060d..36135d51a 100644 --- a/sites/all/modules/views/modules/user/views_handler_field_user_link.inc +++ b/sites/all/modules/views/modules/user/views_handler_field_user_link.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to present a link to the user. + * + * @ingroup views_field_handlers */ class views_handler_field_user_link extends views_handler_field { function construct() { diff --git a/sites/all/modules/views/modules/user/views_handler_field_user_link_cancel.inc b/sites/all/modules/views/modules/user/views_handler_field_user_link_cancel.inc index 272de3bcd..4debce933 100644 --- a/sites/all/modules/views/modules/user/views_handler_field_user_link_cancel.inc +++ b/sites/all/modules/views/modules/user/views_handler_field_user_link_cancel.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to present a link to user cancel. + * + * @ingroup views_field_handlers */ class views_handler_field_user_link_cancel extends views_handler_field_user_link { diff --git a/sites/all/modules/views/modules/user/views_handler_field_user_link_edit.inc b/sites/all/modules/views/modules/user/views_handler_field_user_link_edit.inc index bdeecf0dc..4f25bf654 100644 --- a/sites/all/modules/views/modules/user/views_handler_field_user_link_edit.inc +++ b/sites/all/modules/views/modules/user/views_handler_field_user_link_edit.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to present a link to user edit. + * + * @ingroup views_field_handlers */ class views_handler_field_user_link_edit extends views_handler_field_user_link { function render_link($data, $values) { diff --git a/sites/all/modules/views/modules/user/views_handler_field_user_mail.inc b/sites/all/modules/views/modules/user/views_handler_field_user_mail.inc index 692b6b3dd..8408e6449 100644 --- a/sites/all/modules/views/modules/user/views_handler_field_user_mail.inc +++ b/sites/all/modules/views/modules/user/views_handler_field_user_mail.inc @@ -1,6 +1,8 @@ <?php /** - * Field handler to provide acess control for the email field + * Field handler to provide acess control for the email field. + * + * @ingroup views_field_handlers */ class views_handler_field_user_mail extends views_handler_field_user { function option_definition() { diff --git a/sites/all/modules/views/modules/user/views_handler_field_user_name.inc b/sites/all/modules/views/modules/user/views_handler_field_user_name.inc index fe1056917..26cdbce71 100644 --- a/sites/all/modules/views/modules/user/views_handler_field_user_name.inc +++ b/sites/all/modules/views/modules/user/views_handler_field_user_name.inc @@ -1,6 +1,8 @@ <?php /** - * Field handler to provide simple renderer that allows using a themed user link + * Field handler to provide simple renderer that allows using a themed user link. + * + * @ingroup views_field_handlers */ class views_handler_field_user_name extends views_handler_field_user { /** diff --git a/sites/all/modules/views/modules/user/views_handler_field_user_permissions.inc b/sites/all/modules/views/modules/user/views_handler_field_user_permissions.inc index 7bdb31666..e20f27fa9 100644 --- a/sites/all/modules/views/modules/user/views_handler_field_user_permissions.inc +++ b/sites/all/modules/views/modules/user/views_handler_field_user_permissions.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to provide a list of permissions. + * + * @ingroup views_field_handlers */ class views_handler_field_user_permissions extends views_handler_field_prerender_list { function construct() { diff --git a/sites/all/modules/views/modules/user/views_handler_field_user_picture.inc b/sites/all/modules/views/modules/user/views_handler_field_user_picture.inc index 663b74307..940a89a7b 100644 --- a/sites/all/modules/views/modules/user/views_handler_field_user_picture.inc +++ b/sites/all/modules/views/modules/user/views_handler_field_user_picture.inc @@ -1,7 +1,9 @@ <?php /** - * Field handler to provide simple renderer that allows using a themed user link + * Field handler to provide simple renderer that allows using a themed user link. + * + * @ingroup views_field_handlers */ class views_handler_field_user_picture extends views_handler_field { function construct() { @@ -15,6 +17,20 @@ class views_handler_field_user_picture extends views_handler_field { if ($inline) { return 'span'; } + if ($none_supported) { + if ($this->options['element_type'] === '0') { + return ''; + } + } + if ($this->options['element_type']) { + return check_plain($this->options['element_type']); + } + if ($default_empty) { + return ''; + } + if (isset($this->definition['element type'])) { + return $this->definition['element type']; + } return 'div'; } diff --git a/sites/all/modules/views/modules/user/views_handler_field_user_roles.inc b/sites/all/modules/views/modules/user/views_handler_field_user_roles.inc index e1d583bf5..f55610781 100644 --- a/sites/all/modules/views/modules/user/views_handler_field_user_roles.inc +++ b/sites/all/modules/views/modules/user/views_handler_field_user_roles.inc @@ -1,6 +1,8 @@ <?php /** * Field handler to provide a list of roles. + * + * @ingroup views_field_handlers */ class views_handler_field_user_roles extends views_handler_field_prerender_list { function construct() { diff --git a/sites/all/modules/views/modules/user/views_handler_filter_user_current.inc b/sites/all/modules/views/modules/user/views_handler_filter_user_current.inc index ee119619e..14deb0d2c 100644 --- a/sites/all/modules/views/modules/user/views_handler_filter_user_current.inc +++ b/sites/all/modules/views/modules/user/views_handler_filter_user_current.inc @@ -1,7 +1,9 @@ <?php /** - * Filter handler for the current user + * Filter handler for the current user. + * + * @ingroup views_filter_handlers */ class views_handler_filter_user_current extends views_handler_filter_boolean_operator { function construct() { diff --git a/sites/all/modules/views/modules/user/views_handler_filter_user_name.inc b/sites/all/modules/views/modules/user/views_handler_filter_user_name.inc index a1b409c3a..c885e1b8f 100644 --- a/sites/all/modules/views/modules/user/views_handler_filter_user_name.inc +++ b/sites/all/modules/views/modules/user/views_handler_filter_user_name.inc @@ -1,7 +1,9 @@ <?php /** - * Filter handler for usernames + * Filter handler for usernames. + * + * @ingroup views_filter_handlers */ class views_handler_filter_user_name extends views_handler_filter_in_operator { var $always_multiple = TRUE; diff --git a/sites/all/modules/views/modules/user/views_handler_filter_user_permissions.inc b/sites/all/modules/views/modules/user/views_handler_filter_user_permissions.inc index 904ba9f90..4cf51db46 100644 --- a/sites/all/modules/views/modules/user/views_handler_filter_user_permissions.inc +++ b/sites/all/modules/views/modules/user/views_handler_filter_user_permissions.inc @@ -1,6 +1,8 @@ <?php /** - * Filter handler for user roles + * Filter handler for user roles. + * + * @ingroup views_filter_handlers */ class views_handler_filter_user_permissions extends views_handler_filter_many_to_one { function get_value_options() { diff --git a/sites/all/modules/views/modules/user/views_handler_filter_user_roles.inc b/sites/all/modules/views/modules/user/views_handler_filter_user_roles.inc index 3442aa9cf..cbf985df2 100644 --- a/sites/all/modules/views/modules/user/views_handler_filter_user_roles.inc +++ b/sites/all/modules/views/modules/user/views_handler_filter_user_roles.inc @@ -1,10 +1,22 @@ <?php /** - * Filter handler for user roles + * Filter handler for user roles. + * + * @ingroup views_filter_handlers */ class views_handler_filter_user_roles extends views_handler_filter_many_to_one { function get_value_options() { $this->value_options = user_roles(TRUE); unset($this->value_options[DRUPAL_AUTHENTICATED_RID]); } + + /** + * Override empty and not empty operator labels to be clearer for user roles. + */ + function operators() { + $operators = parent::operators(); + $operators['empty']['title'] = t("Only has the 'authenticated user' role"); + $operators['not empty']['title'] = t("Has roles in addition to 'authenticated user'"); + return $operators; + } } diff --git a/sites/all/modules/views/modules/user/views_plugin_row_user_view.inc b/sites/all/modules/views/modules/user/views_plugin_row_user_view.inc new file mode 100644 index 000000000..b48f4596e --- /dev/null +++ b/sites/all/modules/views/modules/user/views_plugin_row_user_view.inc @@ -0,0 +1,81 @@ +<?php + +/** + * @file + * Contains the user view row plugin. + */ + +/** + * A row plugin which renders a user via user_view. + * + * @ingroup views_row_plugins + */ +class views_plugin_row_user_view extends views_plugin_row { + var $base_table = 'users'; + var $base_field = 'uid'; + + // Store the users to be used for pre_render. + var $users = array(); + + function option_definition() { + $options = parent::option_definition(); + $options['view_mode'] = array('default' => 'full'); + + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + $options = $this->options_form_summary_options(); + $form['view_mode'] = array( + '#type' => 'select', + '#options' => $options, + '#title' => t('View mode'), + '#default_value' => $this->options['view_mode'], + ); + $form['help']['#markup'] = t("Display the user with standard user view. It might be necessary to add a user-profile.tpl.php in your themes template folder, because the default <a href=\"@user-profile-api-link\">user-profile</a>e template don't show the username per default.", array('@user-profile-api-link' => url('http://api.drupal.org/api/drupal/modules--user--user-profile.tpl.php/7'))); + } + + + /** + * Return the main options, which are shown in the summary title. + */ + function options_form_summary_options() { + $entity_info = entity_get_info('user'); + $options = array(); + if (!empty($entity_info['view modes'])) { + foreach ($entity_info['view modes'] as $mode => $settings) { + $options[$mode] = $settings['label']; + } + } + if (empty($options)) { + $options = array( + 'full' => t('User account') + ); + } + + return $options; + } + + function summary_title() { + $options = $this->options_form_summary_options(); + return check_plain($options[$this->options['view_mode']]); + } + + function pre_render($values) { + $uids = array(); + foreach ($values as $row) { + $uids[] = $row->{$this->field_alias}; + } + $this->users = user_load_multiple($uids); + } + + function render($row) { + $account = $this->users[$row->{$this->field_alias}]; + $account->view = $this->view; + $build = user_view($account, $this->options['view_mode']); + + return drupal_render($build); + } +} diff --git a/sites/all/modules/views/modules/views.views.inc b/sites/all/modules/views/modules/views.views.inc index 527607e03..6aa8a0902 100644 --- a/sites/all/modules/views/modules/views.views.inc +++ b/sites/all/modules/views/modules/views.views.inc @@ -68,6 +68,24 @@ function views_views_data() { ), ); + $data['views']['result'] = array( + 'title' => t('Result summary'), + 'help' => t('Shows result summary, for example the items per page.'), + 'area' => array( + 'handler' => 'views_handler_area_result', + ), + ); + + if (module_exists('contextual')) { + $data['views']['contextual_links'] = array( + 'title' => t('Contextual Links'), + 'help' => t('Display fields in a contextual links menu.'), + 'field' => array( + 'handler' => 'views_handler_field_contextual_links', + ), + ); + } + if (module_invoke('ctools', 'api_version', '1.7.1')) { $data['views']['expression'] = array( 'title' => t('Math expression'), diff --git a/sites/all/modules/views/plugins/export_ui/views_ui.class.php b/sites/all/modules/views/plugins/export_ui/views_ui.class.php index 39e182ce7..22b65cb02 100644 --- a/sites/all/modules/views/plugins/export_ui/views_ui.class.php +++ b/sites/all/modules/views/plugins/export_ui/views_ui.class.php @@ -425,8 +425,8 @@ function views_ui_clone_form($form, &$form_state) { '#title' => t('View name'), '#type' => 'machine_name', '#required' => TRUE, - '#maxlength' => 32, - '#size' => 32, + '#maxlength' => 128, + '#size' => 128, '#machine_name' => array( 'exists' => 'ctools_export_ui_edit_name_exists', 'source' => array('human_name'), diff --git a/sites/all/modules/views/plugins/views_plugin_cache.inc b/sites/all/modules/views/plugins/views_plugin_cache.inc index dfd16e88a..9899d482b 100644 --- a/sites/all/modules/views/plugins/views_plugin_cache.inc +++ b/sites/all/modules/views/plugins/views_plugin_cache.inc @@ -251,16 +251,22 @@ class views_plugin_cache extends views_plugin { $build_info = $this->view->build_info; - foreach (array('query', 'count_query') as $index) { - $query = clone $build_info[$index]; - $query->preExecute(); - $build_info[$index] = (string)$query; + $query_plugin = $this->view->display_handler->get_plugin('query'); + + foreach (array('query','count_query') as $index) { + // If the default query back-end is used generate SQL query strings from + // the query objects. + if ($build_info[$index] instanceof SelectQueryInterface) { + $query = clone $build_info[$index]; + $query->preExecute(); + $build_info[$index] = (string)$query; + } } $key_data = array( 'build_info' => $build_info, 'roles' => array_keys($user->roles), 'super-user' => $user->uid == 1, // special caching for super user. - 'language' => $GLOBALS['language'], + 'language' => $GLOBALS['language']->language, ); foreach (array('exposed_info', 'page', 'sort', 'order') as $key) { if (isset($_GET[$key])) { @@ -282,7 +288,7 @@ class views_plugin_cache extends views_plugin { 'roles' => array_keys($user->roles), 'super-user' => $user->uid == 1, // special caching for super user. 'theme' => $GLOBALS['theme'], - 'language' => $GLOBALS['language'], + 'language' => $GLOBALS['language']->language, ); $this->_output_key = $this->view->name . ':' . $this->display->id . ':output:' . md5(serialize($key_data)); diff --git a/sites/all/modules/views/plugins/views_plugin_display.inc b/sites/all/modules/views/plugins/views_plugin_display.inc index 2fdd789f5..b33804318 100644 --- a/sites/all/modules/views/plugins/views_plugin_display.inc +++ b/sites/all/modules/views/plugins/views_plugin_display.inc @@ -42,6 +42,9 @@ class views_plugin_display extends views_plugin { $this->view = &$view; $this->display = &$display; + // Track changes that the user should know about. + $changed = FALSE; + // Make some modifications: if (!isset($options) && isset($display->display_options)) { $options = $display->display_options; @@ -123,6 +126,7 @@ class views_plugin_display extends views_plugin { $this->set_option('offset', NULL); $this->set_option('use_pager', NULL); $this->set_option('pager', $pager); + $changed = TRUE; } @@ -152,6 +156,7 @@ class views_plugin_display extends views_plugin { } $this->set_option($area, array('text' => $options)); $converted = TRUE; + $changed = TRUE; } } // Ensure that options are at least an empty array @@ -169,6 +174,7 @@ class views_plugin_display extends views_plugin { $this->set_option('query', $query_settings); // Clear the values $this->set_option('distinct', NULL); + $changed = TRUE; } // Convert field language settings. @@ -176,12 +182,40 @@ class views_plugin_display extends views_plugin { if (isset($query_options['options']['field_language'])) { $this->set_option('field_language', $query_options['options']['field_language']); unset($query_options['options']['field_language']); + $changed = TRUE; } if (isset($query_options['options']['field_language_add_to_query'])) { $this->set_option('field_language_add_to_query', $query_options['options']['field_language_add_to_query']); unset($query_options['options']['field_language_add_to_query']); + $changed = TRUE; } $this->set_option('query', $query_options); + + // Convert filter groups. + $filter_groups = $this->get_option('filter_groups'); + // Only convert if it wasn't converted yet, which is the case if there is a 0 group. + if (isset($filter_groups['groups'][0])) { + // Update filter groups. + $filter_groups ['groups'] = views_array_key_plus($filter_groups['groups']); + $this->set_option('filter_groups', $filter_groups); + // Update the filter group on each filter. + $filters = $this->get_option('filters'); + foreach ($filters as &$filter) { + if (isset($filter['group'])) { + $filter['group']++; + } + else { + $filter['group'] = 1; + } + } + $this->set_option('filters', $filters); + $changed = TRUE; + } + + // Mark the view as changed so the user has a chance to save it. + if ($changed) { + $this->view->changed = TRUE; + } } function construct() { @@ -629,7 +663,7 @@ class views_plugin_display extends views_plugin { 'filter_groups' => array( 'contains' => array( 'operator' => array('default' => 'AND'), - 'groups' => array('default' => array(0 => 'AND')), + 'groups' => array('default' => array(1 => 'AND')), ), ), 'filters' => array( @@ -768,7 +802,14 @@ class views_plugin_display extends views_plugin { } /** - * Get the display or row plugin, if it exists. + * Get the instance of a plugin, for example style or row. + * + * @param string $type + * The type of the plugin. + * @param string $name + * The name of the plugin defined in hook_views_plugins. + * + * @return views_plugin|FALSE */ function get_plugin($type = 'style', $name = NULL) { static $cache = array(); @@ -1061,7 +1102,7 @@ class views_plugin_display extends views_plugin { ); } - $display_comment = drupal_substr($this->get_option('display_comment'), 0, 10); + $display_comment = check_plain(drupal_substr($this->get_option('display_comment'), 0, 10)); $options['display_comment'] = array( 'category' => 'other', 'title' => t('Comment'), @@ -1682,6 +1723,7 @@ class views_plugin_display extends views_plugin { // Default text. // We have some options, so make a list. + $output = ''; if (!empty($options)) { $output = t('<p>The following tokens are available for this link.</p>'); foreach (array_keys($options) as $type) { diff --git a/sites/all/modules/views/plugins/views_plugin_display_page.inc b/sites/all/modules/views/plugins/views_plugin_display_page.inc index ac89e0c2a..77f210053 100644 --- a/sites/all/modules/views/plugins/views_plugin_display_page.inc +++ b/sites/all/modules/views/plugins/views_plugin_display_page.inc @@ -28,6 +28,7 @@ class views_plugin_display_page extends views_plugin_display { 'description' => array('default' => '', 'translatable' => FALSE), 'weight' => array('default' => 0), 'name' => array('default' => variable_get('menu_default_node_menu', 'navigation')), + 'context' => array('default' => ''), ), ); $options['tab_options'] = array( @@ -148,6 +149,12 @@ class views_plugin_display_page extends views_plugin_display { break; } + // Add context for contextual links. + // @see menu_contextual_links() + if (!empty($menu['context'])) { + $items[$path]['context'] = MENU_CONTEXT_INLINE; + } + // If this is a 'default' tab, check to see if we have to create teh // parent menu item. if ($menu['type'] == 'default tab') { @@ -371,6 +378,13 @@ class views_plugin_display_page extends views_plugin_display { '#description' => t('The lower the weight the higher/further left it will appear.'), '#dependency' => array('radio:menu[type]' => array('normal', 'tab', 'default tab')), ); + $form['menu']['context'] = array( + '#title' => t('Context'), + '#type' => 'checkbox', + '#default_value' => !empty($menu['context']), + '#description' => t('Displays the link in contextual links'), + '#dependency' => array('radio:menu[type]' => array('tab')), + ); break; case 'tab_options': $form['#title'] .= t('Default tab options'); diff --git a/sites/all/modules/views/plugins/views_plugin_pager.inc b/sites/all/modules/views/plugins/views_plugin_pager.inc index f39e2d391..57a987d36 100644 --- a/sites/all/modules/views/plugins/views_plugin_pager.inc +++ b/sites/all/modules/views/plugins/views_plugin_pager.inc @@ -174,6 +174,11 @@ class views_plugin_pager extends views_plugin { */ function post_execute(&$result) { } + /** + * Perform any needed actions just before rendering. + */ + function pre_render(&$result) { } + /** * Render the pager. * diff --git a/sites/all/modules/views/plugins/views_plugin_pager_full.inc b/sites/all/modules/views/plugins/views_plugin_pager_full.inc index 6c7b09649..3884ac1a9 100644 --- a/sites/all/modules/views/plugins/views_plugin_pager_full.inc +++ b/sites/all/modules/views/plugins/views_plugin_pager_full.inc @@ -165,6 +165,16 @@ class views_plugin_pager_full extends views_plugin_pager { if ($error) { form_set_error('pager_options][expose][items_per_page_options', t('Please insert a list of integer numeric values separated by commas: e.g: 10, 20, 50, 100')); } + + // Take sure that the items_per_page is part of the expose settings. + if (!empty($form_state['values']['pager_options']['expose']['items_per_page']) && !empty($form_state['values']['pager_options']['items_per_page'])) { + $items_per_page = $form_state['values']['pager_options']['items_per_page']; + if (array_search($items_per_page, $options) === FALSE) { + form_set_error('pager_options][expose][items_per_page_options', t('Please insert the items per page (@items_per_page) from above.', + array('@items_per_page' => $items_per_page)) + ); + } + } } function query() { diff --git a/sites/all/modules/views/plugins/views_plugin_query.inc b/sites/all/modules/views/plugins/views_plugin_query.inc index f2003840a..55c0b2af5 100644 --- a/sites/all/modules/views/plugins/views_plugin_query.inc +++ b/sites/all/modules/views/plugins/views_plugin_query.inc @@ -33,11 +33,17 @@ class views_plugin_query extends views_plugin { /** * Let modules modify the query just prior to finalizing it. + * + * @param view $view + * The view which is executed. */ function alter(&$view) { } /** * Builds the necessary info to execute the query. + * + * @param view $view + * The view which is executed. */ function build(&$view) { } @@ -49,6 +55,9 @@ class views_plugin_query extends views_plugin { * $view->pager['current_page']. * * $view->result should contain an array of objects. + * + * @param view $view + * The view which is executed. */ function execute(&$view) { } @@ -57,6 +66,9 @@ class views_plugin_query extends views_plugin { * * This signature is something that can be used when perusing query logs to * discern where particular queries might be coming from. + * + * @param view $view + * The view which is executed. */ function add_signature(&$view) { } diff --git a/sites/all/modules/views/plugins/views_plugin_query_default.inc b/sites/all/modules/views/plugins/views_plugin_query_default.inc index 082ff337b..39e01743d 100644 --- a/sites/all/modules/views/plugins/views_plugin_query_default.inc +++ b/sites/all/modules/views/plugins/views_plugin_query_default.inc @@ -205,7 +205,7 @@ class views_plugin_query_default extends views_plugin_query { '#description' => t('Disabling SQL rewriting will disable node_access checks as well as other modules that implement hook_query_alter().'), '#type' => 'checkbox', '#default_value' => !empty($this->options['disable_sql_rewrite']), - '#prefix' => '<div class="messages warning">' . t('WARNING: Disabling SQL rewriting means that node access security is disabled. This may allow users to see data they should not be able to see if your view is misconfigured. Please use this option only if you understand and accept this security risk.') . '</div>', + '#suffix' => '<div class="messages warning sql-rewrite-warning js-hide">' . t('WARNING: Disabling SQL rewriting means that node access security is disabled. This may allow users to see data they should not be able to see if your view is misconfigured. Please use this option only if you understand and accept this security risk.') . '</div>', ); $form['distinct'] = array( '#type' => 'checkbox', @@ -934,7 +934,7 @@ class views_plugin_query_default extends views_plugin_query { * * @param $table * The table this field is part of. If a formula, enter NULL. - * If you want to orderby random use "rand" as table and + * If you want to orderby random use "rand" as table and nothing else. * @param $field * The field or formula to sort on. If already a field, enter NULL * and put in the alias. @@ -949,7 +949,9 @@ class views_plugin_query_default extends views_plugin_query { * Any params that should be passed through to the add_field. */ function add_orderby($table, $field = NULL, $order = 'ASC', $alias = '', $params = array()) { - if ($table) { + // Only ensure the table if it's not the special random key. + // @todo: Maybe it would make sense to just add a add_orderby_rand or something similar. + if ($table && $table != 'rand') { $this->ensure_table($table); } @@ -1030,13 +1032,24 @@ class views_plugin_query_default extends views_plugin_query { /** * Construct the "WHERE" or "HAVING" part of the query. * + * As views has to wrap the conditions from arguments with AND, a special + * group is wrapped around all conditions. This special group has the ID 0. + * There is other code in filters which makes sure that the group IDs are + * higher than zero. + * * @param $where * 'where' or 'having'. */ function build_condition($where = 'where') { $has_condition = FALSE; - $main_group = $this->group_operator == 'OR' ? db_or() : db_and(); + $has_arguments = FALSE; + $has_filter = FALSE; + + $main_group = db_and(); + $filter_group = $this->group_operator == 'OR' ? db_or() : db_and(); + foreach ($this->$where as $group => $info) { + if (!empty($info['conditions'])) { $sub_group = $info['type'] == 'OR' ? db_or() : db_and(); foreach ($info['conditions'] as $key => $clause) { @@ -1055,10 +1068,27 @@ class views_plugin_query_default extends views_plugin_query { $sub_group->condition($clause['field'], $clause['value'], $clause['operator']); } } - $main_group->condition($sub_group); + + // Add the item to the filter group. + if ($group != 0) { + $has_filter = TRUE; + $filter_group->condition($sub_group); + } + else { + $has_arguments = TRUE; + $main_group->condition($sub_group); + } } } - if ($has_condition) { + + if ($has_filter) { + $main_group->condition($filter_group); + } + + if (!$has_arguments && $has_condition) { + return $filter_group; + } + if ($has_arguments && $has_condition) { return $main_group; } } diff --git a/sites/all/modules/views/plugins/views_plugin_style.inc b/sites/all/modules/views/plugins/views_plugin_style.inc index 4e0946e63..421591a8b 100644 --- a/sites/all/modules/views/plugins/views_plugin_style.inc +++ b/sites/all/modules/views/plugins/views_plugin_style.inc @@ -43,8 +43,7 @@ class views_plugin_style extends views_plugin { } $this->options += array( - 'grouping' => '', - 'group_rendered' => TRUE, + 'grouping' => array(), ); $this->definition += array( @@ -152,8 +151,7 @@ class views_plugin_style extends views_plugin { function option_definition() { $options = parent::option_definition(); - $options['grouping'] = array('default' => ''); - $options['group_rendered'] = array('default' => TRUE); + $options['grouping'] = array('default' => array()); if ($this->uses_row_class()) { $options['row_class'] = array('default' => ''); } @@ -169,23 +167,52 @@ class views_plugin_style extends views_plugin { // @TODO: Document "uses grouping" in docs.php when docs.php is written. if ($this->uses_fields() && $this->definition['uses grouping']) { $options = array('' => t('- None -')); - $options += $this->display->handler->get_field_labels(); + $field_labels = $this->display->handler->get_field_labels(); + $options += $field_labels; // If there are no fields, we can't group on them. if (count($options) > 1) { - $form['grouping'] = array( - '#type' => 'select', - '#title' => t('Grouping field'), - '#options' => $options, - '#default_value' => $this->options['grouping'], - '#description' => t('You may optionally specify a field by which to group the records. Leave blank to not group.'), - ); - $form['group_rendered'] = array( - '#type' => 'checkbox', - '#title' => t('Use rendered output to group rows'), - '#default_value' => $this->options['group_rendered'], - '#description' => t('If enabled the rendered output of the grouping field is used to group the rows.'), - ); + // This is for backward compability, when there was just a single select form. + if (is_string($this->options['grouping'])) { + $grouping = $this->options['grouping']; + $this->options['grouping'] = array(); + $this->options['grouping'][0]['field'] = $grouping; + } + if (isset($this->options['group_rendered']) && is_string($this->options['group_rendered'])) { + $this->options['grouping'][0]['rendered'] = $this->options['group_rendered']; + unset($this->options['group_rendered']); + } + + $c = count($this->options['grouping']); + // Add a form for every grouping, plus one. + for ($i = 0; $i <= $c; $i++) { + $grouping = !empty($this->options['grouping'][$i]) ? $this->options['grouping'][$i] : array(); + $grouping += array('field' => '', 'rendered' => TRUE, 'rendered_strip' => FALSE); + $form['grouping'][$i]['field'] = array( + '#type' => 'select', + '#title' => t('Grouping field Nr.@number', array('@number' => $i + 1)), + '#options' => $options, + '#default_value' => $grouping['field'], + '#description' => t('You may optionally specify a field by which to group the records. Leave blank to not group.'), + ); + $form['grouping'][$i]['rendered'] = array( + '#type' => 'checkbox', + '#title' => t('Use rendered output to group rows'), + '#default_value' => $grouping['rendered'], + '#description' => t('If enabled the rendered output of the grouping field is used to group the rows.'), + '#dependency' => array( + 'edit-style-options-grouping-' . $i . '-field' => array_keys($field_labels), + ) + ); + $form['grouping'][$i]['rendered_strip'] = array( + '#type' => 'checkbox', + '#title' => t('Remove tags from rendered output'), + '#default_value' => $grouping['rendered_strip'], + '#dependency' => array( + 'edit-style-options-grouping-' . $i . '-field' => array_keys($field_labels), + ) + ); + } } } @@ -203,6 +230,18 @@ class views_plugin_style extends views_plugin { } } + function options_validate(&$form, &$form_state) { + // Don't run validation on style plugins without the grouping setting. + if (isset($form_state['values']['style_options']['grouping'])) { + // Don't save grouping if no field is specified. + foreach ($form_state['values']['style_options']['grouping'] as $index => $grouping) { + if (empty($grouping['field'])) { + unset($form_state['values']['style_options']['grouping'][$index]); + } + } + } + } + /** * Called by the view builder to see if this style handler wants to * interfere with the sorts. If so it should build; if it returns @@ -237,36 +276,63 @@ class views_plugin_style extends views_plugin { return; } - // Group the rows according to the grouping field, if specified. + // Group the rows according to the grouping instructions, if specified. $sets = $this->render_grouping( $this->view->result, $this->options['grouping'], - (bool) $this->options['group_rendered'] + TRUE ); - // Render each group separately and concatenate. Plugins may override this - // method if they wish some other way of handling grouping. + return $this->render_grouping_sets($sets); + } + + /** + * Render the grouping sets. + * + * Plugins may override this method if they wish some other way of handling + * grouping. + * + * @param $sets + * Array containing the grouping sets to render. + * @param $level + * Integer indicating the hierarchical level of the grouping. + * + * @return string + * Rendered output of given grouping sets. + */ + function render_grouping_sets($sets, $level = 0) { $output = ''; - foreach ($sets as $group) { - $title = $group['group']; - if ($this->uses_row_plugin()) { - $rows = array(); - foreach ($group['rows'] as $row_index => $row) { - $this->view->row_index = $row_index; - $rows[$row_index] = $this->row_plugin->render($row); - } + foreach ($sets as $set) { + $row = reset($set['rows']); + // Render as a grouping set. + if (is_array($row) && isset($row['group'])) { + $output .= theme(views_theme_functions('views_view_grouping', $this->view, $this->display), + array( + 'view' => $this->view, + 'grouping' => $this->options['grouping'][$level], + 'grouping_level' => $level, + 'rows' => $set['rows'], + 'title' => $set['group']) + ); } + // Render as a record set. else { - $rows = $group['rows']; - } + if ($this->uses_row_plugin()) { + foreach ($set['rows'] as $index => $row) { + $this->view->row_index = $index; + $set['rows'][$index] = $this->row_plugin->render($row); + } + } - $output .= theme($this->theme_functions(), - array( - 'view' => $this->view, - 'options' => $this->options, - 'rows' => $rows, - 'title' => $title) - ); + $output .= theme($this->theme_functions(), + array( + 'view' => $this->view, + 'options' => $this->options, + 'grouping_level' => $level, + 'rows' => $set['rows'], + 'title' => $set['group']) + ); + } } unset($this->view->row_index); return $output; @@ -277,42 +343,98 @@ class views_plugin_style extends views_plugin { * * @param $records * An array of records from the view to group. - * @param $grouping_field - * The field id on which to group. If empty, the result set will be given - * a single group with an empty string as a label. + * @param $groupings + * An array of grouping instructions on which fields to group. If empty, the + * result set will be given a single group with an empty string as a label. * @param $group_rendered - * Boolean value to switch whether to use the rendered or the raw field - * value for grouping. If set to NULL the return is structured as before - * Views 7.x-3.0-rc2. + * Boolean value whether to use the rendered or the raw field value for + * grouping. If set to NULL the return is structured as before + * Views 7.x-3.0-rc2. After Views 7.x-3.0 this boolean is only used if + * $groupings is an old-style string or if the rendered option is missing + * for a grouping instruction. * @return * The grouped record set. + * A nested set structure is generated if multiple grouping fields are used. + * + * @code + * array( + * 'grouping_field_1:grouping_1' => array( + * 'group' => 'grouping_field_1:content_1', + * 'rows' => array( + * 'grouping_field_2:grouping_a' => array( + * 'group' => 'grouping_field_2:content_a', + * 'rows' => array( + * $row_index_1 => $row_1, + * $row_index_2 => $row_2, + * // ... + * ) + * ), + * ), + * ), + * 'grouping_field_1:grouping_2' => array( + * // ... + * ), + * ) + * @endcode */ - function render_grouping($records, $grouping_field = '', $group_rendered = NULL) { + function render_grouping($records, $groupings = array(), $group_rendered = NULL) { + // This is for backward compability, when $groupings was a string containing + // the ID of a single field. + if (is_string($groupings)) { + $rendered = $group_rendered === NULL ? TRUE : $group_rendered; + $groupings = array(array('field' => $groupings, 'rendered' => $rendered)); + } + // Make sure fields are rendered $this->render_fields($this->view->result); $sets = array(); - if ($grouping_field) { + if ($groupings) { foreach ($records as $index => $row) { - $grouping = ''; - // Group on the rendered version of the field, not the raw. That way, - // we can control any special formatting of the grouping field through - // the admin or theme layer or anywhere else we'd like. - if (isset($this->view->field[$grouping_field])) { - $group_content = $this->get_field($index, $grouping_field); - if ($this->view->field[$grouping_field]->options['label']) { - $group_content = $this->view->field[$grouping_field]->options['label'] . ': ' . $group_content; + // Iterate through configured grouping fields to determine the + // hierarchically positioned set where the current row belongs to. + // While iterating, parent groups, that do not exist yet, are added. + $set = &$sets; + foreach ($groupings as $info) { + $field = $info['field']; + $rendered = isset($info['rendered']) ? $info['rendered'] : $group_rendered; + $rendered_strip = isset($info['rendered_strip']) ? $info['rendered_strip'] : FALSE; + $grouping = ''; + $group_content = ''; + // Group on the rendered version of the field, not the raw. That way, + // we can control any special formatting of the grouping field through + // the admin or theme layer or anywhere else we'd like. + if (isset($this->view->field[$field])) { + $group_content = $this->get_field($index, $field); + if ($this->view->field[$field]->options['label']) { + $group_content = $this->view->field[$field]->options['label'] . ': ' . $group_content; + } + if ($rendered) { + $grouping = $group_content; + if ($rendered_strip) { + $group_content = $grouping = strip_tags(htmlspecialchars_decode($group_content)); + } + } + else { + $grouping = $this->get_field_value($index, $field); + // Not all field handlers return a scalar value, + // e.g. views_handler_field_field. + if (!is_scalar($grouping)) { + $grouping = md5(serialize($grouping)); + } + } } - if ($group_rendered) { - $grouping = $group_content; - } - else { - $grouping = $this->get_field_value($index, $grouping_field); - } - if (empty($sets[$grouping]['group'])) { - $sets[$grouping]['group'] = $group_content; + + // Create the group if it does not exist yet. + if (empty($set[$grouping])) { + $set[$grouping]['group'] = $group_content; + $set[$grouping]['rows'] = array(); } + + // Move the set reference into the row set of the group we just determined. + $set = &$set[$grouping]['rows']; } - $sets[$grouping]['rows'][$index] = $row; + // Add the row to the hierarchically positioned row set we just determined. + $set[$index] = $row; } } else { diff --git a/sites/all/modules/views/plugins/views_plugin_style_rss.inc b/sites/all/modules/views/plugins/views_plugin_style_rss.inc index 9e1981928..a54eccc50 100644 --- a/sites/all/modules/views/plugins/views_plugin_style_rss.inc +++ b/sites/all/modules/views/plugins/views_plugin_style_rss.inc @@ -72,7 +72,7 @@ class views_plugin_style_rss extends views_plugin_style { function render() { if (empty($this->row_plugin)) { - debug('views_plugin_style_default: Missing row plugin'); + vpr('views_plugin_style_default: Missing row plugin'); return; } $rows = ''; diff --git a/sites/all/modules/views/plugins/views_plugin_style_summary.inc b/sites/all/modules/views/plugins/views_plugin_style_summary.inc index 304f024d3..1f705cef6 100644 --- a/sites/all/modules/views/plugins/views_plugin_style_summary.inc +++ b/sites/all/modules/views/plugins/views_plugin_style_summary.inc @@ -28,7 +28,6 @@ class views_plugin_style_summary extends views_plugin_style { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['base_path'] = array( '#type' => 'textfield', '#title' => t('Base path'), diff --git a/sites/all/modules/views/plugins/views_plugin_style_summary_jump_menu.inc b/sites/all/modules/views/plugins/views_plugin_style_summary_jump_menu.inc index bfa66833f..0bde6a686 100644 --- a/sites/all/modules/views/plugins/views_plugin_style_summary_jump_menu.inc +++ b/sites/all/modules/views/plugins/views_plugin_style_summary_jump_menu.inc @@ -33,7 +33,6 @@ class views_plugin_style_summary_jump_menu extends views_plugin_style { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['base_path'] = array( '#type' => 'textfield', '#title' => t('Base path'), diff --git a/sites/all/modules/views/plugins/views_plugin_style_table.inc b/sites/all/modules/views/plugins/views_plugin_style_table.inc index 2ad5f64bc..bd090e5a2 100644 --- a/sites/all/modules/views/plugins/views_plugin_style_table.inc +++ b/sites/all/modules/views/plugins/views_plugin_style_table.inc @@ -10,6 +10,19 @@ * @ingroup views_style_plugins */ class views_plugin_style_table extends views_plugin_style { + + /** + * Contains the current active sort column. + * @var string + */ + public $active; + + /** + * Contains the current active sort order, either desc or asc. + * @var string + */ + public $order; + function option_definition() { $options = parent::option_definition(); @@ -19,14 +32,16 @@ class views_plugin_style_table extends views_plugin_style { $options['override'] = array('default' => TRUE); $options['sticky'] = array('default' => FALSE); $options['order'] = array('default' => 'asc'); - $options['summary'] = array('default' => ''); + $options['summary'] = array('default' => '', 'translatable' => TRUE); $options['empty_table'] = array('default' => FALSE); return $options; } /** - * Determine if we should provide sorting based upon $_GET inputs. + * Determine if we should provide sorting based upon $_GET inputs + * + * @return bool */ function build_sort() { if (!isset($_GET['order']) && ($this->options['default'] == -1 || empty($this->view->field[$this->options['default']]))) { @@ -102,13 +117,15 @@ class views_plugin_style_table extends views_plugin_style { * be requested from the current display. The running render should * send the fields through, as they may be different than what the * display has listed due to access control or other changes. + * + * @return array + * An array of all the sanitized columns. */ function sanitize_columns($columns, $fields = NULL) { $sanitized = array(); if ($fields === NULL) { $fields = $this->display->handler->get_option('fields'); } - // Preconfigure the sanitized array so that the order is retained. foreach ($fields as $field => $info) { // Set to itself so that if it isn't touched, it gets column @@ -166,6 +183,7 @@ class views_plugin_style_table extends views_plugin_style { '#title' => t('Table summary'), '#description' => t('This value will be displayed as table-summary attribute in the html. Set this for better accessiblity of your site.'), '#default_value' => $this->options['summary'], + '#maxlength' => 255, ); // Note: views UI registers this theme handler on our behalf. Your module diff --git a/sites/all/modules/views/plugins/views_wizard/views_ui_base_views_wizard.class.php b/sites/all/modules/views/plugins/views_wizard/views_ui_base_views_wizard.class.php index c314befeb..09d9d3238 100644 --- a/sites/all/modules/views/plugins/views_wizard/views_ui_base_views_wizard.class.php +++ b/sites/all/modules/views/plugins/views_wizard/views_ui_base_views_wizard.class.php @@ -43,7 +43,7 @@ class ViewsUiBaseViewsWizard implements ViewsWizardInterface { protected $filter_defaults = array( 'id' => NULL, 'expose' => array('operator' => FALSE), - 'group' => 0, + 'group' => 1, ); function __construct($plugin) { diff --git a/sites/all/modules/views/tests/handlers/views_handler_area_text.test b/sites/all/modules/views/tests/handlers/views_handler_area_text.test index 983b37ddb..d9724a4a7 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_area_text.test +++ b/sites/all/modules/views/tests/handlers/views_handler_area_text.test @@ -1,5 +1,10 @@ <?php +/** + * Tests the text area handler. + * + * @see views_handler_area_text + */ class ViewsHandlerAreaTextTest extends ViewsSqlTest { public static function getInfo() { return array( @@ -13,7 +18,7 @@ class ViewsHandlerAreaTextTest extends ViewsSqlTest { $view = $this->getBasicView(); // add a text header - $string = $this->randomString(); + $string = $this->randomName(); $view->display['default']->handler->override_option('header', array( 'area' => array( 'id' => 'area', diff --git a/sites/all/modules/views/tests/handlers/views_handler_field.test b/sites/all/modules/views/tests/handlers/views_handler_field.test new file mode 100644 index 000000000..726857e2d --- /dev/null +++ b/sites/all/modules/views/tests/handlers/views_handler_field.test @@ -0,0 +1,115 @@ +<?php + +/** + * @file + * Contains tests for views_handler_field. + */ + +/** + * Tests the generic field handler + * + * @see views_handler_field + */ +class ViewsHandlerFieldTest extends ViewsSqlTest { + public static function getInfo() { + return array( + 'name' => 'Field', + 'description' => 'Test the core views_handler_field handler.', + 'group' => 'Views Handlers', + ); + } + + protected function setUp() { + parent::setUp(); + $this->column_map = array( + 'views_test_name' => 'name', + ); + } + + function testEmpty() { + $this->_testHideIfEmpty(); + $this->_testEmptyText(); + } + + /** + * Tests the hide if empty functionality. + * + * This tests alters the result to get easier and less coupled results. + */ + function _testHideIfEmpty() { + $view = $this->getBasicView(); + $view->init_display(); + $view->pre_execute(); + $view->execute(); + + $column_map_reversed = array_flip($this->column_map); + $view->row_index = 0; + + $view->field['name']->options['hide_empty'] = TRUE; + $view->result[0]->{$column_map_reversed['name']} = ""; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, "", 'If hide_empty is checked, "" should be treated as empty.'); + + $view->field['name']->options['empty_zero'] = FALSE; + $view->result[0]->{$column_map_reversed['name']} = "0"; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, "0", 'If hide_empty is checked, but not empty_zero, "0" should be treated as not empty.'); + + $view->field['name']->options['empty_zero'] = TRUE; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, "", 'If hide_empty and empty_zero are checked, "0" should be treated as empty.'); + + $view->field['name']->options['hide_alter_empty'] = FALSE; + $view->field['name']->options['alter']['alter_text'] = TRUE; + $view->result[0]->{$column_map_reversed['name']} = ""; + $random_name = $this->randomName(); + $view->field['name']->options['alter']['text'] = $random_name; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, $random_name, 'If hide_empty but not hide_alter_empty is checked, some rewrite should appear even if the value is empty.'); + + $view->field['name']->options['hide_alter_empty'] = TRUE; + $random_name = $this->randomName(); + $view->field['name']->options['alter']['text'] = $random_name; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, "", 'If hide_empty and hide_alter_empty are checked, rewrite should be empty all the time.'); + } + + /** + * Tests the usage of the empty text. + */ + function _testEmptyText() { + $view = $this->getBasicView(); + $view->init_display(); + $view->pre_execute(); + $view->execute(); + + $column_map_reversed = array_flip($this->column_map); + $view->row_index = 0; + + $empty_text = $view->field['name']->options['empty'] = $this->randomName(); + $view->result[0]->{$column_map_reversed['name']} = ""; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, $empty_text, 'If a field is empty, the empty text should be used for the output.'); + + $view->result[0]->{$column_map_reversed['name']} = "0"; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, "0", 'If a field is 0 and empty_zero is not checked, the empty text should not be used for the output.'); + + $view->result[0]->{$column_map_reversed['name']} = "0"; + $view->field['name']->options['empty_zero'] = TRUE; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, $empty_text, 'If a field is 0 and empty_zero is checked, the empty text should be used for the output.'); + + $view->result[0]->{$column_map_reversed['name']} = ""; + $view->field['name']->options['alter']['alter_text'] = TRUE; + $alter_text = $view->field['name']->options['alter']['text'] = $this->randomName(); + $view->field['name']->options['hide_alter_empty'] = FALSE; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, $alter_text, 'If a field is empty, some rewrite text exists, but hide_alter_empty is not checked, render the rewrite text.'); + + $view->field['name']->options['hide_alter_empty'] = TRUE; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, $empty_text, 'If a field is empty, some rewrite text exists, and hide_alter_empty is checked, use the empty text.'); + } + +} \ No newline at end of file diff --git a/sites/all/modules/views/tests/handlers/views_handler_field_boolean.test b/sites/all/modules/views/tests/handlers/views_handler_field_boolean.test index a6c95f931..54b4287c5 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_field_boolean.test +++ b/sites/all/modules/views/tests/handlers/views_handler_field_boolean.test @@ -53,6 +53,11 @@ class ViewsHandlerFieldBooleanTest extends ViewsSqlTest { $this->assertEqual(t('False'), $view->field['age']->advanced_render($view->result[0])); $this->assertEqual(t('True'), $view->field['age']->advanced_render($view->result[1])); + // test awesome unicode. + $view->field['age']->options['type'] = 'unicode-yes-no'; + $this->assertEqual('✖', $view->field['age']->advanced_render($view->result[0])); + $this->assertEqual('✔', $view->field['age']->advanced_render($view->result[1])); + // Set a custom output format. $view->field['age']->formats['test'] = array(t('Test-True'), t('Test-False')); $view->field['age']->options['type'] = 'test'; diff --git a/sites/all/modules/views/tests/handlers/views_handler_filter_string.test b/sites/all/modules/views/tests/handlers/views_handler_filter_string.test index 67b870d13..cd7831103 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_filter_string.test +++ b/sites/all/modules/views/tests/handlers/views_handler_filter_string.test @@ -156,12 +156,15 @@ class ViewsHandlerFilterStringTest extends ViewsSqlTest { 'field' => 'description', 'relationship' => 'none', 'operator' => 'word', - 'value' => 'musician producer', + 'value' => 'actor', ), )); $this->executeView($view); $resultset = array( + array( + 'name' => 'George', + ), array( 'name' => 'Ringo', ), @@ -191,6 +194,7 @@ class ViewsHandlerFilterStringTest extends ViewsSqlTest { ); $this->assertIdenticalResultset($view, $resultset, $this->column_map); } + function testFilterStringStarts() { $view = $this->getBasicView(); @@ -214,6 +218,7 @@ class ViewsHandlerFilterStringTest extends ViewsSqlTest { ); $this->assertIdenticalResultset($view, $resultset, $this->column_map); } + function testFilterStringNotStarts() { $view = $this->getBasicView(); diff --git a/sites/all/modules/views/tests/handlers/views_handler_sort_date.test b/sites/all/modules/views/tests/handlers/views_handler_sort_date.test index 08b60532e..528c85a35 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_sort_date.test +++ b/sites/all/modules/views/tests/handlers/views_handler_sort_date.test @@ -12,30 +12,126 @@ class ViewsHandlerSortDateTest extends ViewsSqlTest { ); } - protected function orderResultSetDate($result_set, $column, $granularity, $reverse = TRUE) { - // Build a technical sort column. - foreach ($result_set as &$result) { - $result['_sort'] = $this->orderResultSetDateHelper($result[$column], $granularity); + protected function expectedResultSet($granularity, $reverse = TRUE) { + $expected = array(); + if (!$reverse) { + switch ($granularity) { + case 'second': + $expected = array( + array('name' => 'John'), + array('name' => 'Paul'), + array('name' => 'Meredith'), + array('name' => 'Ringo'), + array('name' => 'George'), + ); + break; + case 'minute': + $expected = array( + array('name' => 'John'), + array('name' => 'Paul'), + array('name' => 'Ringo'), + array('name' => 'Meredith'), + array('name' => 'George'), + ); + break; + case 'hour': + $expected = array( + array('name' => 'John'), + array('name' => 'Ringo'), + array('name' => 'Paul'), + array('name' => 'Meredith'), + array('name' => 'George'), + ); + break; + case 'day': + $expected = array( + array('name' => 'John'), + array('name' => 'Ringo'), + array('name' => 'Paul'), + array('name' => 'Meredith'), + array('name' => 'George'), + ); + break; + case 'month': + $expected = array( + array('name' => 'John'), + array('name' => 'George'), + array('name' => 'Ringo'), + array('name' => 'Paul'), + array('name' => 'Meredith'), + ); + break; + case 'year': + $expected = array( + array('name' => 'John'), + array('name' => 'George'), + array('name' => 'Ringo'), + array('name' => 'Paul'), + array('name' => 'Meredith'), + ); + break; + } } - return $this->orderResultSet($result_set, '_sort', $reverse); - } - - protected function orderResultSetDateHelper($date, $granularity) { - switch ($granularity) { - case 'second': - default: - return $date; - case 'minute': - return date('YmdHi', $date); - case 'hour': - return date('YmdH', $date); - case 'day': - return date('Ymd', $date); - case 'month': - return date('Ym', $date); - case 'year': - return date('Y', $date); + else { + switch ($granularity) { + case 'second': + $expected = array( + array('name' => 'George'), + array('name' => 'Ringo'), + array('name' => 'Meredith'), + array('name' => 'Paul'), + array('name' => 'John'), + ); + break; + case 'minute': + $expected = array( + array('name' => 'George'), + array('name' => 'Ringo'), + array('name' => 'Meredith'), + array('name' => 'Paul'), + array('name' => 'John'), + ); + break; + case 'hour': + $expected = array( + array('name' => 'George'), + array('name' => 'Ringo'), + array('name' => 'Paul'), + array('name' => 'Meredith'), + array('name' => 'John'), + ); + break; + case 'day': + $expected = array( + array('name' => 'George'), + array('name' => 'John'), + array('name' => 'Ringo'), + array('name' => 'Paul'), + array('name' => 'Meredith'), + ); + break; + case 'month': + $expected = array( + array('name' => 'John'), + array('name' => 'George'), + array('name' => 'Ringo'), + array('name' => 'Paul'), + array('name' => 'Meredith'), + ); + break; + case 'year': + $expected = array( + array('name' => 'John'), + array('name' => 'George'), + array('name' => 'Ringo'), + array('name' => 'Paul'), + array('name' => 'Meredith'), + ); + break; + } } + + return $expected; } /** @@ -48,10 +144,10 @@ class ViewsHandlerSortDateTest extends ViewsSqlTest { // Change the fields. $view->display['default']->handler->override_option('fields', array( - 'id' => array( - 'id' => 'id', + 'name' => array( + 'id' => 'name', 'table' => 'views_test', - 'field' => 'id', + 'field' => 'name', 'relationship' => 'none', ), 'created' => array( @@ -69,9 +165,16 @@ class ViewsHandlerSortDateTest extends ViewsSqlTest { 'table' => 'views_test', 'field' => 'created', 'relationship' => 'none', - 'granularity' => 'second', + 'granularity' => $granularity, 'order' => $reverse ? 'DESC' : 'ASC', ), + 'id' => array( + 'id' => 'id', + 'table' => 'views_test', + 'field' => 'id', + 'relationship' => 'none', + 'order' => 'ASC', + ), )); // Execute the view. @@ -79,9 +182,11 @@ class ViewsHandlerSortDateTest extends ViewsSqlTest { // Verify the result. $this->assertEqual(count($this->dataSet()), count($view->result), t('The number of returned rows match.')); - $this->assertIdenticalResultset($view, $this->orderResultSetDate($this->dataSet(), 'created', $granularity, $reverse), array( - 'views_test_created' => 'created', + $this->assertIdenticalResultset($view, $this->expectedResultSet($granularity, $reverse), array( + 'views_test_name' => 'name', ), t('Result is returned correctly when ordering by granularity @granularity, @reverse.', array('@granularity' => $granularity, '@reverse' => $reverse ? t('reverse') : t('forward')))); + $view->destroy(); + unset($view); } } } diff --git a/sites/all/modules/views/tests/styles/views_plugin_style.test b/sites/all/modules/views/tests/styles/views_plugin_style.test index 5bad590b5..875fcf1a0 100644 --- a/sites/all/modules/views/tests/styles/views_plugin_style.test +++ b/sites/all/modules/views/tests/styles/views_plugin_style.test @@ -14,9 +14,9 @@ class ViewsPluginStyleTestCase extends ViewsSqlTest { } /** - * Tests the groupby features of styles. + * Tests the grouping legacy features of styles. */ - function testGroupBy() { + function testGroupingLegacy() { $view = $this->getBasicView(); // Setup grouping by the job. $view->init_display(); @@ -69,7 +69,7 @@ class ViewsPluginStyleTestCase extends ViewsSqlTest { $expected['Job: Drummer'][2]->views_test_job = 'Drummer'; $expected['Job: Drummer'][2]->views_test_id = '3'; - $this->assertEqual($sets, $expected, t('The style plugin should proper groupby the results')); + $this->assertEqual($sets, $expected, t('The style plugin should proper group the results with grouping by the rendered output.')); $expected = array(); $expected['Job: Singer'] = array(); @@ -93,7 +93,7 @@ class ViewsPluginStyleTestCase extends ViewsSqlTest { $sets_new_rendered = $view->style_plugin->render_grouping($view->result, $view->style_plugin->options['grouping'], TRUE); $sets_new_value = $view->style_plugin->render_grouping($view->result, $view->style_plugin->options['grouping'], FALSE); - $this->assertEqual($sets_new_rendered, $expected, t('The style plugins should proper groupby the results with grouped by the rendered output.')); + $this->assertEqual($sets_new_rendered, $expected, t('The style plugins should proper group the results with grouping by the rendered output.')); // Reorder the group structure to group by value. $expected['Singer'] = $expected['Job: Singer']; @@ -101,6 +101,130 @@ class ViewsPluginStyleTestCase extends ViewsSqlTest { unset($expected['Job: Singer']); unset($expected['Job: Drummer']); - $this->assertEqual($sets_new_value, $expected, t('The style plugins should proper groupby the results with grouped by the value.')); + $this->assertEqual($sets_new_value, $expected, t('The style plugins should proper group the results with grouping by the value.')); + } + + function testGrouping() { + $this->_testGrouping(FALSE); + $this->_testGrouping(TRUE); + } + + /** + * Tests the grouping features of styles. + */ + function _testGrouping($stripped = FALSE) { + $view = $this->getBasicView(); + // Setup grouping by the job and the age field. + $view->init_display(); + $view->init_style(); + $view->style_plugin->options['grouping'] = array( + array('field' => 'job'), + array('field' => 'age'), + ); + + // Reduce the amount of items to make the test a bit easier. + // Set up the pager. + $view->display['default']->handler->override_option('pager', array( + 'type' => 'some', + 'options' => array('items_per_page' => 3), + )); + + // Add the job and age field. + $view->display['default']->handler->override_option('fields', array( + 'name' => array( + 'id' => 'name', + 'table' => 'views_test', + 'field' => 'name', + 'relationship' => 'none', + ), + 'job' => array( + 'id' => 'job', + 'table' => 'views_test', + 'field' => 'job', + 'relationship' => 'none', + ), + 'age' => array( + 'id' => 'age', + 'table' => 'views_test', + 'field' => 'age', + 'relationship' => 'none', + ), + )); + + // Now run the query and groupby the result. + $this->executeView($view); + + $expected = array(); + $expected['Job: Singer'] = array(); + $expected['Job: Singer']['group'] = 'Job: Singer'; + $expected['Job: Singer']['rows']['Age: 25'] = array(); + $expected['Job: Singer']['rows']['Age: 25']['group'] = 'Age: 25'; + $expected['Job: Singer']['rows']['Age: 25']['rows'][0] = new StdClass(); + $expected['Job: Singer']['rows']['Age: 25']['rows'][0]->views_test_name = 'John'; + $expected['Job: Singer']['rows']['Age: 25']['rows'][0]->views_test_job = 'Singer'; + $expected['Job: Singer']['rows']['Age: 25']['rows'][0]->views_test_age = '25'; + $expected['Job: Singer']['rows']['Age: 25']['rows'][0]->views_test_id = '1'; + $expected['Job: Singer']['rows']['Age: 27'] = array(); + $expected['Job: Singer']['rows']['Age: 27']['group'] = 'Age: 27'; + $expected['Job: Singer']['rows']['Age: 27']['rows'][1] = new StdClass(); + $expected['Job: Singer']['rows']['Age: 27']['rows'][1]->views_test_name = 'George'; + $expected['Job: Singer']['rows']['Age: 27']['rows'][1]->views_test_job = 'Singer'; + $expected['Job: Singer']['rows']['Age: 27']['rows'][1]->views_test_age = '27'; + $expected['Job: Singer']['rows']['Age: 27']['rows'][1]->views_test_id = '2'; + $expected['Job: Drummer'] = array(); + $expected['Job: Drummer']['group'] = 'Job: Drummer'; + $expected['Job: Drummer']['rows']['Age: 28'] = array(); + $expected['Job: Drummer']['rows']['Age: 28']['group'] = 'Age: 28'; + $expected['Job: Drummer']['rows']['Age: 28']['rows'][2] = new StdClass(); + $expected['Job: Drummer']['rows']['Age: 28']['rows'][2]->views_test_name = 'Ringo'; + $expected['Job: Drummer']['rows']['Age: 28']['rows'][2]->views_test_job = 'Drummer'; + $expected['Job: Drummer']['rows']['Age: 28']['rows'][2]->views_test_age = '28'; + $expected['Job: Drummer']['rows']['Age: 28']['rows'][2]->views_test_id = '3'; + + + // Alter the results to support the stripped case. + if ($stripped) { + + // Add some html to the result and expected value. + $rand = '<a data="' . $this->randomName() . '" />'; + $view->result[0]->views_test_job .= $rand; + $expected['Job: Singer']['rows']['Age: 25']['rows'][0]->views_test_job = 'Singer' . $rand; + $expected['Job: Singer']['group'] = 'Job: Singer'; + $rand = '<a data="' . $this->randomName() . '" />'; + $view->result[1]->views_test_job .= $rand; + $expected['Job: Singer']['rows']['Age: 27']['rows'][1]->views_test_job = 'Singer' . $rand; + $rand = '<a data="' . $this->randomName() . '" />'; + $view->result[2]->views_test_job .= $rand; + $expected['Job: Drummer']['rows']['Age: 28']['rows'][2]->views_test_job = 'Drummer' . $rand; + $expected['Job: Drummer']['group'] = 'Job: Drummer'; + + $view->style_plugin->options['grouping'][0] = array('field' => 'job', 'rendered' => TRUE, 'rendered_strip' => TRUE); + $view->style_plugin->options['grouping'][1] = array('field' => 'age', 'rendered' => TRUE, 'rendered_strip' => TRUE); + } + + + // The newer api passes the value of the grouping as well. + $sets_new_rendered = $view->style_plugin->render_grouping($view->result, $view->style_plugin->options['grouping'], TRUE); + + $this->assertEqual($sets_new_rendered, $expected, t('The style plugins should proper group the results with grouping by the rendered output.')); + + // Don't test stripped case, because the actual value is not stripped. + if (!$stripped) { + $sets_new_value = $view->style_plugin->render_grouping($view->result, $view->style_plugin->options['grouping'], FALSE); + + // Reorder the group structure to grouping by value. + $expected['Singer'] = $expected['Job: Singer']; + $expected['Singer']['rows']['25'] = $expected['Job: Singer']['rows']['Age: 25']; + $expected['Singer']['rows']['27'] = $expected['Job: Singer']['rows']['Age: 27']; + $expected['Drummer'] = $expected['Job: Drummer']; + $expected['Drummer']['rows']['28'] = $expected['Job: Drummer']['rows']['Age: 28']; + unset($expected['Job: Singer']); + unset($expected['Singer']['rows']['Age: 25']); + unset($expected['Singer']['rows']['Age: 27']); + unset($expected['Job: Drummer']); + unset($expected['Drummer']['rows']['Age: 28']); + + $this->assertEqual($sets_new_value, $expected, t('The style plugins should proper group the results with grouping by the value.')); + } } } diff --git a/sites/all/modules/views/tests/user/views_handler_field_user_name.test b/sites/all/modules/views/tests/user/views_handler_field_user_name.test new file mode 100644 index 000000000..f627ea23c --- /dev/null +++ b/sites/all/modules/views/tests/user/views_handler_field_user_name.test @@ -0,0 +1,92 @@ +<?php + +/** + * Tests the field username handler. + * + * @see views_handler_field_user_name + */ +class viewsHandlerFieldUserNameTest extends ViewsSqlTest { + public static function getInfo() { + return array( + 'name' => 'Tests user: name field', + 'description' => 'Tests the handler of the user: name field', + 'group' => 'Views Modules', + ); + } + + function testUserName() { + $view = $this->view_user_name(); + $view->init_display(); + $view->pre_execute(); + $view->execute(); + + $view->row_index = 0; + + $view->field['name']->options['link_to_user'] = TRUE; + $username = $view->result[0]->users_name = $this->randomName(); + $view->result[0]->uid = 1; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertTrue(strpos($render, $username) !== FALSE, 'If link to user is checked the username should be part of the output.'); + $this->assertTrue(strpos($render, 'user/1') !== FALSE, 'If link to user is checked the link to the user should appear as well.'); + + $view->field['name']->options['link_to_user'] = FALSE; + $username = $view->result[0]->users_name = $this->randomName(); + $view->result[0]->uid = 1; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, $username, 'If the user is not linked the username should be printed out for a normal user.'); + + $view->result[0]->uid = 0; + $anon_name = variable_get('anonymous', t('Anonymous')); + $view->result[0]->users_name = ''; + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, $anon_name , 'For user0 it should use the default anonymous name by default.'); + + $view->field['name']->options['overwrite_anonymous'] = TRUE; + $anon_name = $view->field['name']->options['anonymous_text'] = $this->randomName(); + $render = $view->field['name']->advanced_render($view->result[0]); + $this->assertIdentical($render, $anon_name , 'For user0 it should use the configured anonymous text if overwrite_anonymous is checked.'); + + + } + function view_user_name() { + $view = new view; + $view->name = 'test_views_handler_field_user_name'; + $view->description = ''; + $view->tag = 'default'; + $view->base_table = 'users'; + $view->human_name = 'test_views_handler_field_user_name'; + $view->core = 7; + $view->api_version = '3.0'; + $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ + + /* Display: Master */ + $handler = $view->new_display('default', 'Master', 'default'); + $handler->display->display_options['access']['type'] = 'none'; + $handler->display->display_options['cache']['type'] = 'none'; + $handler->display->display_options['query']['type'] = 'views_query'; + $handler->display->display_options['query']['options']['query_comment'] = FALSE; + $handler->display->display_options['exposed_form']['type'] = 'basic'; + $handler->display->display_options['pager']['type'] = 'full'; + $handler->display->display_options['style_plugin'] = 'default'; + $handler->display->display_options['row_plugin'] = 'fields'; + /* Field: User: Name */ + $handler->display->display_options['fields']['name']['id'] = 'name'; + $handler->display->display_options['fields']['name']['table'] = 'users'; + $handler->display->display_options['fields']['name']['field'] = 'name'; + $handler->display->display_options['fields']['name']['label'] = ''; + $handler->display->display_options['fields']['name']['alter']['alter_text'] = 0; + $handler->display->display_options['fields']['name']['alter']['make_link'] = 0; + $handler->display->display_options['fields']['name']['alter']['absolute'] = 0; + $handler->display->display_options['fields']['name']['alter']['word_boundary'] = 0; + $handler->display->display_options['fields']['name']['alter']['ellipsis'] = 0; + $handler->display->display_options['fields']['name']['alter']['strip_tags'] = 0; + $handler->display->display_options['fields']['name']['alter']['trim'] = 0; + $handler->display->display_options['fields']['name']['alter']['html'] = 0; + $handler->display->display_options['fields']['name']['hide_empty'] = 0; + $handler->display->display_options['fields']['name']['empty_zero'] = 0; + $handler->display->display_options['fields']['name']['link_to_user'] = 1; + $handler->display->display_options['fields']['name']['overwrite_anonymous'] = 0; + + return $view; + } +} diff --git a/sites/all/modules/views/tests/user/views_user.test b/sites/all/modules/views/tests/user/views_user.test index 6800008b7..286e2df79 100644 --- a/sites/all/modules/views/tests/user/views_user.test +++ b/sites/all/modules/views/tests/user/views_user.test @@ -6,6 +6,9 @@ */ class ViewsUserTestCase extends ViewsSqlTest { + var $users = array(); + var $nodes = array(); + public static function getInfo() { return array( 'name' => 'Tests basic user integration', diff --git a/sites/all/modules/views/tests/user/views_user_argument_validate.test b/sites/all/modules/views/tests/user/views_user_argument_validate.test index 1d5678422..3c36b3a63 100644 --- a/sites/all/modules/views/tests/user/views_user_argument_validate.test +++ b/sites/all/modules/views/tests/user/views_user_argument_validate.test @@ -5,7 +5,6 @@ * Tests views user argument argument handler. */ -module_load_include('test', 'views', 'tests/views_query'); class ViewsUserArgumentValidate extends ViewsSqlTest { public static function getInfo() { diff --git a/sites/all/modules/views/tests/views_cache.test b/sites/all/modules/views/tests/views_cache.test index 458b578f1..c00411290 100644 --- a/sites/all/modules/views/tests/views_cache.test +++ b/sites/all/modules/views/tests/views_cache.test @@ -5,8 +5,6 @@ * Test cache system. */ -module_load_include('test', 'views', 'tests/views_query'); - /** * Basic test for pluggable caching. */ diff --git a/sites/all/modules/views/tests/views_groupby.test b/sites/all/modules/views/tests/views_groupby.test index de166425d..ed2759846 100644 --- a/sites/all/modules/views/tests/views_groupby.test +++ b/sites/all/modules/views/tests/views_groupby.test @@ -3,14 +3,15 @@ class ViewsQueryGroupByTest extends ViewsSqlTest { public static function getInfo() { return array( - 'name' => 'Groupby UI', - 'description' => 'Tests UI of aggregate functionality.', - 'group' => 'Views UI', + 'name' => 'Groupby', + 'description' => 'Tests aggregate functionality of views, for example count.', + 'group' => 'Views', ); + } /** - * Test aggregatate count feature. + * Test aggregate count feature. */ public function testAggregateCount() { // Create 2 nodes of type1 and 3 nodes of type2 @@ -276,16 +277,20 @@ class ViewsQueryGroupByTest extends ViewsSqlTest { } class viewsUiGroupbyTestCase extends DrupalWebTestCase { - public function setUp() { - parent::setUp('views', 'views_ui'); - module_enable(array('views_ui')); + function setUp() { + // Enable views_ui. + parent::setUp('views_ui', 'views_test'); + + // Create and log in a user with administer views permission. + $views_admin = $this->drupalCreateUser(array('administer views', 'administer blocks', 'bypass node access', 'access user profiles', 'view revisions')); + $this->drupalLogin($views_admin); } public static function getInfo() { return array( - 'name' => 'Groupby', - 'description' => 'Tests aggregate functionality of views, for example count.', - 'group' => 'Views', + 'name' => 'Groupby UI', + 'description' => 'Tests UI of aggregate functionality.', + 'group' => 'Views UI', ); } @@ -295,11 +300,6 @@ class viewsUiGroupbyTestCase extends DrupalWebTestCase { * @todo: this should check the change of the settings as well. */ function testGroupBySave() { - $admin_user = $this->drupalCreateUser(array('administer views', 'administer site configuration')); - $this->drupalLogin($admin_user); - views_invalidate_cache(); - menu_rebuild(); - $this->drupalGet('admin/structure/views/view/test_views_groupby_save/edit'); $edit = array( diff --git a/sites/all/modules/views/tests/views_handlers.test b/sites/all/modules/views/tests/views_handlers.test index 32a5747db..19126fadb 100644 --- a/sites/all/modules/views/tests/views_handlers.test +++ b/sites/all/modules/views/tests/views_handlers.test @@ -14,7 +14,7 @@ class ViewsHandlersTest extends ViewsSqlTest { ); } - function setUp() { + protected function setUp() { parent::setUp('views', 'views_ui'); module_enable(array('views_ui')); } @@ -113,14 +113,13 @@ class ViewsHandlersTest extends ViewsSqlTest { * * @param $first * The first value to check. - * @param $second - * The second value to check. - * @param $message + * @param views_handler $handler + * @param string $message * The message to display along with the assertion. - * @param $group + * @param string $group * The type of assertion - examples are "Browser", "PHP". * - * @return + * @return bool * TRUE if the assertion succeeded, FALSE otherwise. */ protected function assertEqualValue($first, $handler, $message = '', $group = 'Other') { diff --git a/sites/all/modules/views/tests/views_module.test b/sites/all/modules/views/tests/views_module.test index 6ce6a5a80..9804f576a 100644 --- a/sites/all/modules/views/tests/views_module.test +++ b/sites/all/modules/views/tests/views_module.test @@ -1,6 +1,5 @@ <?php -module_load_include('test', 'views', 'tests/views_query'); class ViewsModuleTest extends ViewsSqlTest { public static function getInfo() { @@ -13,6 +12,7 @@ class ViewsModuleTest extends ViewsSqlTest { public function setUp() { parent::setUp(); + drupal_theme_rebuild(); } public function viewsData() { @@ -87,7 +87,11 @@ class ViewsModuleTest extends ViewsSqlTest { $views_status['frontpage'] = FALSE; // false is enabled variable_set('views_defaults', $views_status); - $registry = theme_get_registry(); + $existing = array(); + $type = array(); + $theme = array(); + $path = array(); + $registry = views_theme($existing, $type, $theme, $path); $this->assertTrue(isset($registry['views_view__frontpage'])); } diff --git a/sites/all/modules/views/tests/views_pager.test b/sites/all/modules/views/tests/views_pager.test index 93c9de4c2..9c3cf3ec1 100644 --- a/sites/all/modules/views/tests/views_pager.test +++ b/sites/all/modules/views/tests/views_pager.test @@ -99,7 +99,7 @@ class ViewsPagerTest extends DrupalWebTestCase { $view->view_php = ''; $view->base_table = 'node'; $view->is_cacheable = FALSE; - $view->api_version = 2; + $view->api_version = 3; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ /* Display: Master */ @@ -160,7 +160,7 @@ class ViewsPagerTest extends DrupalWebTestCase { $view->view_php = ''; $view->base_table = 'node'; $view->is_cacheable = FALSE; - $view->api_version = 2; + $view->api_version =3; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ /* Display: Master */ @@ -218,7 +218,7 @@ class ViewsPagerTest extends DrupalWebTestCase { $view->view_php = ''; $view->base_table = 'node'; $view->is_cacheable = FALSE; - $view->api_version = 2; + $view->api_version = 3; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ /* Display: Master */ @@ -305,7 +305,7 @@ class ViewsPagerTest extends DrupalWebTestCase { $view->view_php = ''; $view->base_table = 'node'; $view->is_cacheable = FALSE; - $view->api_version = 2; + $view->api_version = 3; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ /* Display: Master */ @@ -345,7 +345,7 @@ class ViewsPagerTest extends DrupalWebTestCase { $view->view_php = ''; $view->base_table = 'node'; $view->is_cacheable = FALSE; - $view->api_version = 2; + $view->api_version = 3; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ /* Display: Master */ @@ -371,7 +371,7 @@ class ViewsPagerTest extends DrupalWebTestCase { $view->view_php = ''; $view->base_table = 'node'; $view->is_cacheable = FALSE; - $view->api_version = 2; + $view->api_version = 3; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ /* Display: Master */ diff --git a/sites/all/modules/views/tests/views_query.test b/sites/all/modules/views/tests/views_query.test index 7f38e505c..ea4e2bcff 100644 --- a/sites/all/modules/views/tests/views_query.test +++ b/sites/all/modules/views/tests/views_query.test @@ -111,6 +111,9 @@ abstract class ViewsTestCase extends DrupalWebTestCase { /** * Helper function to execute a view with debugging. + * + * @param view $view + * @param array $args */ protected function executeView($view, $args = array()) { $view->set_display(); @@ -356,6 +359,8 @@ abstract class ViewsSqlTest extends ViewsTestCase { /** * Build and return a basic view of the views_test table. + * + * @return view */ protected function getBasicView() { views_include('view'); diff --git a/sites/all/modules/views/tests/views_test.info b/sites/all/modules/views/tests/views_test.info index 3f7120d78..c3278f730 100644 --- a/sites/all/modules/views/tests/views_test.info +++ b/sites/all/modules/views/tests/views_test.info @@ -5,9 +5,9 @@ core = 7.x dependencies[] = views hidden = TRUE -; Information added by drupal.org packaging script on 2011-12-18 -version = "7.x-3.0" +; Information added by drupal.org packaging script on 2012-02-22 +version = "7.x-3.3" core = "7.x" project = "views" -datestamp = "1324170450" +datestamp = "1329946249" diff --git a/sites/all/modules/views/tests/views_test.module b/sites/all/modules/views/tests/views_test.module index b51769022..18536b95a 100644 --- a/sites/all/modules/views/tests/views_test.module +++ b/sites/all/modules/views/tests/views_test.module @@ -17,7 +17,7 @@ function views_test_permission() { */ function views_test_views_api() { return array( - 'api' => '3.0-alpha1', + 'api' => 3.0, 'template path' => drupal_get_path('module', 'views_test') . '/templates', ); } diff --git a/sites/all/modules/views/tests/views_translatable.test b/sites/all/modules/views/tests/views_translatable.test index 18445c9f8..515a33d38 100644 --- a/sites/all/modules/views/tests/views_translatable.test +++ b/sites/all/modules/views/tests/views_translatable.test @@ -1,7 +1,5 @@ <?php -module_load_include('test', 'views', 'tests/views_query'); - class ViewsTranslatableTest extends ViewsSqlTest { var $strings; diff --git a/sites/all/modules/views/tests/views_ui.test b/sites/all/modules/views/tests/views_ui.test index 003eb855a..6301ac9af 100644 --- a/sites/all/modules/views/tests/views_ui.test +++ b/sites/all/modules/views/tests/views_ui.test @@ -662,8 +662,22 @@ class ViewsUIWizardJumpMenuTestCase extends ViewsUIWizardHelper { // Submit the jump menu form, and check that we are redirected to the // expected URL. + $edit = array(); $edit['jump'] = url($path, $options); + + // The urls are built with :: to be able to have a unique path all the time, + // so try to find out the real path of $edit. + $view_object = views_get_view($view['name']); + $view_object->preview('page'); + $form = $view_object->style_plugin->render(); + $jump_options = $form['jump']['#options']; + foreach ($jump_options as $key => $title) { + if (strpos($key, $edit['jump']) !== FALSE) { + $edit['jump'] = $key; + } + } + $this->drupalPost($view['page[path]'], $edit, t('Go')); $this->assertResponse(200); $this->assertUrl($path, $options); diff --git a/sites/all/modules/views/tests/views_upgrade.test b/sites/all/modules/views/tests/views_upgrade.test index 7205a10b3..0e8626baf 100644 --- a/sites/all/modules/views/tests/views_upgrade.test +++ b/sites/all/modules/views/tests/views_upgrade.test @@ -19,9 +19,9 @@ class ViewsUpgradeTestCase extends ViewsSqlTest { protected function setUp() { // // To import a view the user needs use PHP for settings rights, so enable php module. parent::setUp(); -// -// // $admin_user = $this->drupalCreateUser(array('administer views', 'administer site configuration', 'use PHP for settings')); -// // $this->drupalLogin($admin_user); + + module_enable(array('php')); + $this->resetAll(); } function viewsData() { @@ -53,6 +53,7 @@ class ViewsUpgradeTestCase extends ViewsSqlTest { public function testMovedTo() { // Test moving on field lavel. $view = $this->viewsMovedToField(); + $view->update(); $view->build(); // $this->assertEqual('old_field_1', $view->field['old_field_1']->options['id'], "Id shouldn't change during conversion"); @@ -63,6 +64,7 @@ class ViewsUpgradeTestCase extends ViewsSqlTest { // Test moving on handler lavel. $view = $this->viewsMovedToHandler(); + $view->update(); $view->build(); // $this->assertEqual('old_field_2', $view->field['old_field_2']->options['id']); @@ -75,6 +77,7 @@ class ViewsUpgradeTestCase extends ViewsSqlTest { // Test moving on table level. $view = $this->viewsMovedToTable(); + $view->update(); $view->build(); $this->assertEqual('views_test', $view->base_table, 'Make sure that view->base_table gets automatically converted.'); @@ -90,6 +93,8 @@ class ViewsUpgradeTestCase extends ViewsSqlTest { * is used. */ public function testUpgradeImport() { + $admin_user = $this->drupalCreateUser(array('administer views', 'administer site configuration', 'use PHP for settings')); + $this->drupalLogin($admin_user); $edit = array( 'view' => $this->viewUpgradeImport(), ); diff --git a/sites/all/modules/views/theme/theme.inc b/sites/all/modules/views/theme/theme.inc index 2adb7700e..eaf8d2d93 100644 --- a/sites/all/modules/views/theme/theme.inc +++ b/sites/all/modules/views/theme/theme.inc @@ -110,7 +110,7 @@ function template_preprocess_views_view(&$vars) { // It is true that the DIV wrapper has classes denoting the name of the view // and its display ID, but this is not enough to unequivocally match a view // with its HTML, because one view may appear several times on the page. So - // we set up a running counter, $dom_id, to issue a "unique" identifier for + // we set up a hash with the current time, $dom_id, to issue a "unique" identifier for // each view. This identifier is written to both Drupal.settings and the DIV // wrapper. $vars['dom_id'] = !empty($view->dom_id) ? $view->dom_id : md5($view->name . REQUEST_TIME . rand()); @@ -306,6 +306,29 @@ function template_preprocess_views_view_fields(&$vars) { } +/** + * Display a single views grouping. + */ +function theme_views_view_grouping($vars) { + $view = $vars['view']; + $title = $vars['title']; + $content = $vars['content']; + + $output = '<div class="view-grouping">'; + $output .= '<div class="view-grouping-header">' . $title . '</div>'; + $output .= '<div class="view-grouping-content">' . $content . '</div>' ; + $output .= '</div>'; + + return $output; +} + +/** + * Process a single grouping within a view. + */ +function template_preprocess_views_view_grouping(&$vars) { + $vars['content'] = $vars['view']->style_plugin->render_grouping_sets($vars['rows'], $vars['grouping_level']); +} + /** * Display a single views field. * @@ -442,6 +465,7 @@ function template_preprocess_views_view_table(&$vars) { $result = $vars['result'] = $vars['rows']; $vars['rows'] = array(); $vars['field_classes'] = array(); + $vars['header'] = array(); $options = $view->style_plugin->options; $handler = $view->style_plugin; @@ -457,8 +481,6 @@ function template_preprocess_views_view_table(&$vars) { $query += $view->exposed_raw_input; } - $header = array(); - // Fields must be rendered in order as of Views 2.3, so we will pre-render // everything. $renders = $handler->render_fields($result); @@ -881,7 +903,7 @@ function template_preprocess_views_exposed_form(&$vars) { // set up defaults so that there's always something there. $widget->label = $widget->operator = $widget->widget = NULL; - $widget->id = $form[$info['value']]['#id']; + $widget->id = isset($form[$info['value']]['#id']) ? $form[$info['value']]['#id'] : ''; if (!empty($info['label'])) { $widget->label = $info['label']; } @@ -897,6 +919,7 @@ function template_preprocess_views_exposed_form(&$vars) { $widget = new stdClass; // set up defaults so that there's always something there. $widget->label = $widget->operator = $widget->widget = NULL; + $widget->id = 'checkboxes'; $widget->widget = $checkboxes; $vars['widgets']['checkboxes'] = $widget; } @@ -968,31 +991,34 @@ function theme_views_mini_pager($vars) { // End of marker calculations. - $li_previous = theme('pager_previous', - array( - 'text' => (isset($tags[1]) ? $tags[1] : t('‹‹')), - 'element' => $element, - 'interval' => 1, - 'parameters' => $parameters, - ) - ); - if (empty($li_previous)) { - $li_previous = " "; - } - - $li_next = theme('pager_next', - array( - 'text' => (isset($tags[3]) ? $tags[3] : t('››')), - 'element' => $element, - 'interval' => 1, - 'parameters' => $parameters, - ) - ); - if (empty($li_next)) { - $li_next = " "; - } if ($pager_total[$element] > 1) { + + $li_previous = theme('pager_previous', + array( + 'text' => (isset($tags[1]) ? $tags[1] : t('‹‹')), + 'element' => $element, + 'interval' => 1, + 'parameters' => $parameters, + ) + ); + if (empty($li_previous)) { + $li_previous = " "; + } + + $li_next = theme('pager_next', + array( + 'text' => (isset($tags[3]) ? $tags[3] : t('››')), + 'element' => $element, + 'interval' => 1, + 'parameters' => $parameters, + ) + ); + + if (empty($li_next)) { + $li_next = " "; + } + $items[] = array( 'class' => array('pager-previous'), 'data' => $li_previous, diff --git a/sites/all/modules/views/theme/views-view-grouping.tpl.php b/sites/all/modules/views/theme/views-view-grouping.tpl.php new file mode 100644 index 000000000..caffc5f52 --- /dev/null +++ b/sites/all/modules/views/theme/views-view-grouping.tpl.php @@ -0,0 +1,22 @@ +<?php + /** + * This template is used to print a single grouping in a view. It is not + * actually used in default Views, as this is registered as a theme + * function which has better performance. For single overrides, the + * template is perfectly okay. + * + * Variables available: + * - $view: The view object + * - $grouping: The grouping instruction. + * - $grouping_level: Integer indicating the hierarchical level of the grouping. + * - $rows: The rows contained in this grouping. + * - $title: The title of this grouping. + * - $content: The processed content output that will normally be used. + */ +?> +<div class="view-grouping"> + <div class="view-grouping-header"><?php print $title; ?></div> + <div class="view-grouping-content"> + <?php print $content; ?> + </div> +</div> diff --git a/sites/all/modules/views/theme/views-view-table.tpl.php b/sites/all/modules/views/theme/views-view-table.tpl.php index 3ec5f5c3f..28138dbd0 100644 --- a/sites/all/modules/views/theme/views-view-table.tpl.php +++ b/sites/all/modules/views/theme/views-view-table.tpl.php @@ -21,15 +21,17 @@ <?php if (!empty($title)) : ?> <caption><?php print $title; ?></caption> <?php endif; ?> - <thead> - <tr> - <?php foreach ($header as $field => $label): ?> - <th <?php if ($header_classes[$field]) { print 'class="'. $header_classes[$field] . '" '; } ?>> - <?php print $label; ?> - </th> - <?php endforeach; ?> - </tr> - </thead> + <?php if (!empty($header)) : ?> + <thead> + <tr> + <?php foreach ($header as $field => $label): ?> + <th <?php if ($header_classes[$field]) { print 'class="'. $header_classes[$field] . '" '; } ?>> + <?php print $label; ?> + </th> + <?php endforeach; ?> + </tr> + </thead> + <?php endif; ?> <tbody> <?php foreach ($rows as $row_count => $row): ?> <tr class="<?php print implode(' ', $row_classes[$row_count]); ?>"> diff --git a/sites/all/modules/views/views.info b/sites/all/modules/views/views.info index a34b6544e..3fce29687 100644 --- a/sites/all/modules/views/views.info +++ b/sites/all/modules/views/views.info @@ -10,6 +10,7 @@ stylesheets[all][] = css/views.css dependencies[] = ctools ; Handlers files[] = handlers/views_handler_area.inc +files[] = handlers/views_handler_area_result.inc files[] = handlers/views_handler_area_text.inc files[] = handlers/views_handler_area_view.inc files[] = handlers/views_handler_argument.inc @@ -23,6 +24,7 @@ files[] = handlers/views_handler_argument_group_by_numeric.inc 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_custom.inc files[] = handlers/views_handler_field_date.inc files[] = handlers/views_handler_field_entity.inc @@ -32,6 +34,7 @@ files[] = handlers/views_handler_field_numeric.inc files[] = handlers/views_handler_field_prerender_list.inc files[] = handlers/views_handler_field_time_interval.inc files[] = handlers/views_handler_field_serialized.inc +files[] = handlers/views_handler_field_machine_name.inc files[] = handlers/views_handler_field_url.inc files[] = handlers/views_handler_filter.inc files[] = handlers/views_handler_filter_boolean_operator.inc @@ -92,6 +95,7 @@ files[] = modules/comment/views_plugin_row_comment_view.inc files[] = modules/contact/views_handler_field_contact_link.inc files[] = modules/field/views_handler_field_field.inc files[] = modules/field/views_handler_relationship_entity_reverse.inc +files[] = modules/field/views_handler_argument_field_list.inc files[] = modules/field/views_handler_filter_field_list.inc files[] = modules/filter/views_handler_field_filter_format_name.inc files[] = modules/locale/views_handler_argument_locale_group.inc @@ -191,6 +195,7 @@ files[] = modules/user/views_handler_filter_user_roles.inc files[] = modules/user/views_plugin_argument_default_current_user.inc files[] = modules/user/views_plugin_argument_default_user.inc files[] = modules/user/views_plugin_argument_validate_user.inc +files[] = modules/user/views_plugin_row_user_view.inc ; Plugins files[] = plugins/views_plugin_access.inc files[] = plugins/views_plugin_access_none.inc @@ -210,12 +215,13 @@ files[] = plugins/views_plugin_display.inc files[] = plugins/views_plugin_display_attachment.inc files[] = plugins/views_plugin_display_block.inc files[] = plugins/views_plugin_display_default.inc +files[] = plugins/views_plugin_display_embed.inc files[] = plugins/views_plugin_display_extender.inc files[] = plugins/views_plugin_display_feed.inc +files[] = plugins/views_plugin_display_page.inc files[] = plugins/views_plugin_exposed_form_basic.inc files[] = plugins/views_plugin_exposed_form.inc files[] = plugins/views_plugin_exposed_form_input_required.inc -files[] = plugins/views_plugin_display_page.inc files[] = plugins/views_plugin_localization_core.inc files[] = plugins/views_plugin_localization.inc files[] = plugins/views_plugin_localization_none.inc @@ -242,6 +248,7 @@ files[] = plugins/views_plugin_style_table.inc ; Tests files[] = tests/handlers/views_handler_area_text.test files[] = tests/handlers/views_handler_argument_null.test +files[] = tests/handlers/views_handler_field.test files[] = tests/handlers/views_handler_field_boolean.test files[] = tests/handlers/views_handler_field_custom.test files[] = tests/handlers/views_handler_field_counter.test @@ -280,6 +287,7 @@ files[] = tests/views_upgrade.test files[] = tests/views_test.views_default.inc files[] = tests/comment/views_handler_argument_comment_user_uid.test files[] = tests/comment/views_handler_filter_comment_user_uid.test +files[] = tests/user/views_handler_field_user_name.test files[] = tests/user/views_user_argument_default.test files[] = tests/user/views_user_argument_validate.test files[] = tests/user/views_user.test @@ -287,9 +295,9 @@ files[] = tests/views_cache.test files[] = tests/views_view.test files[] = tests/views_ui.test -; Information added by drupal.org packaging script on 2011-12-18 -version = "7.x-3.0" +; Information added by drupal.org packaging script on 2012-02-22 +version = "7.x-3.3" core = "7.x" project = "views" -datestamp = "1324170450" +datestamp = "1329946249" diff --git a/sites/all/modules/views/views.install b/sites/all/modules/views/views.install index e590159e5..46b005f4b 100644 --- a/sites/all/modules/views/views.install +++ b/sites/all/modules/views/views.install @@ -275,7 +275,7 @@ function views_update_6000() { // views_schema_6000() rather than the default views_schema(). // This is important for processing subsequent table updates. $schema = views_schema_6000(); - _drupal_initialize_schema('views', $schema); + _drupal_schema_initialize($schema, 'views'); foreach ($schema as $name => $table) { db_create_table($name, $table); @@ -600,12 +600,32 @@ function views_schema_7300() { /** * Make sure the human_name field is added to the views_view table. * - * If you updated from 6.x-2.x-dev to 7.x-3.x you had already schema - * version 6014, so the update 6013 isn't runned, and never was. - * As a result the human_name field is missing in the database. + * If you updated from 6.x-2.x-dev to 7.x-3.x you already had schema + * version 6014, so update 6013 never was nor will be run. As a result, + * the human_name field is missing from the database. * - * Add the human_name field if it doesn't exists before. + * This will add the human_name field if it doesn't already exist. */ function views_update_7300() { views_update_6013(); } + +function views_schema_7301() { + $schema = views_schema(__FUNCTION__); + $schema['views_view']['fields']['name']['length'] = 128; + return $schema; +} + +/** + * Enlarge the name column + */ +function views_update_7301() { + $new_field = array( + 'type' => 'varchar', + 'length' => '128', + 'default' => '', + 'not null' => TRUE, + 'description' => 'The unique name of the view. This is the primary field views are loaded from, and is used so that views may be internal and not necessarily in the database. May only be alphanumeric characters plus underscores.', + ); + db_change_field('views_view', 'name', 'name', $new_field); +} diff --git a/sites/all/modules/views/views.module b/sites/all/modules/views/views.module index c9ef5cc5d..1b637e4a6 100644 --- a/sites/all/modules/views/views.module +++ b/sites/all/modules/views/views.module @@ -58,7 +58,7 @@ function views_api_minimum_version() { */ function views_theme($existing, $type, $theme, $path) { $path = drupal_get_path('module', 'views'); - include_once $path . '/theme/theme.inc'; + ctools_include('theme', 'views', 'theme'); // Some quasi clever array merging here. $base = array( @@ -91,6 +91,10 @@ function views_theme($existing, $type, $theme, $path) { 'pattern' => 'views_view_field__', 'variables' => array('view' => NULL, 'field' => NULL, 'row' => NULL), ); + $hooks['views_view_grouping'] = $base + array( + 'pattern' => 'views_view_grouping__', + 'variables' => array('view' => NULL, 'grouping' => NULL, 'grouping_level' => NULL, 'rows' => NULL, 'title' => NULL), + ); $plugins = views_fetch_plugin_data(); @@ -782,6 +786,7 @@ function views_add_contextual_links(&$render_element, $location, $view, $display $render_element['#contextual_links'][$module] = array($link['parent path'], $args); $render_element['#views_contextual_links_info'][$module] = array( 'location' => $location, + 'view' => $view, 'view_name' => $view->name, 'view_display_id' => $display_id, ); @@ -959,6 +964,8 @@ function &views_get_page_view() { /** * Set the current 'current view' that is being built/rendered so that it is * easy for other modules or items in drupal_eval to identify + * + * @return view */ function &views_set_current_view($view = NULL) { static $cache = NULL; @@ -973,6 +980,8 @@ function &views_set_current_view($view = NULL) { * Find out what, if any, current view is currently in use. Please note that * this returns a reference, so be careful! You can unintentionally modify the * $view object. + * + * @return view */ function &views_get_current_view() { return views_set_current_view(); @@ -1091,6 +1100,7 @@ function views_get_handler($table, $field, $key, $override = NULL) { $data = views_fetch_data($table, FALSE); $handler = NULL; + views_include('handlers'); // Support old views_data entries conversion. @@ -1422,7 +1432,7 @@ function views_get_views_as_options($views_only = FALSE, $filter = 'all', $exclu foreach ($views as $view) { // Return only views. if ($views_only && $view->name != $exclude_view_name) { - $options[$view->name] = $view->name; + $options[$view->name] = $view->get_human_name(); } // Return views with display ids. else { @@ -1591,16 +1601,13 @@ function views_debug($message, $placeholders = array()) { $output = $message; watchdog('views_logging', $output, $placeholders); } - else if ($devel_region == 'message') { - $output = empty($output) ? t($message, $placeholders) : $output; - dpm($output); - } else if ($devel_region == 'drupal_debug') { $output = empty($output) ? t($message, $placeholders) : $output; dd($output); } else { - drupal_add_region_content($devel_region, $output); + $output = empty($output) ? t($message, $placeholders) : $output; + dpm($output); } } elseif (isset($GLOBALS['drupal_test_info'])) { @@ -1739,6 +1746,15 @@ function views_form_views_form($form, &$form_state, $view, $output) { $substitutions = array(); foreach ($view->field as $field_name => $field) { + $form_element_name = $field_name; + if (method_exists($field, 'form_element_name')) { + $form_element_name = $field->form_element_name(); + } + $method_form_element_row_id_exists = FALSE; + if (method_exists($field, 'form_element_row_id')) { + $method_form_element_row_id_exists = TRUE; + } + // If the field provides a views form, allow it to modify the $form array. $has_form = FALSE; if (property_exists($field, 'views_form_callback')) { @@ -1754,10 +1770,17 @@ function views_form_views_form($form, &$form_state, $view, $output) { // Build the substitutions array for use in the theme function. if ($has_form) { foreach ($view->result as $row_id => $row) { + if ($method_form_element_row_id_exists) { + $form_element_row_id = $field->form_element_row_id($row_id); + } + else { + $form_element_row_id = $row_id; + } + $substitutions[] = array( - 'placeholder' => '<!--form-item-' . $field_name . '--' . $row_id . '-->', - 'field_name' => $field_name, - 'row_id' => $row_id, + 'placeholder' => '<!--form-item-' . $form_element_name . '--' . $form_element_row_id . '-->', + 'field_name' => $form_element_name, + 'row_id' => $form_element_row_id, ); } } @@ -2285,7 +2308,7 @@ function views_process_check_options($element, &$form_state) { * @param $alter * - max_length: Maximum lenght of the string, the rest gets truncated. * - word_boundary: Trim only on a word boundary. - * - ellipsis: 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. * * @param $value @@ -2322,6 +2345,22 @@ function views_trim_text($alter, $value) { return $value; } +/** + * Adds one to each key of the array. + * + * For example array(0 => 'foo') would be array(1 => 'foo'). + */ +function views_array_key_plus($array) { + $keys = array_keys($array); + rsort($keys); + foreach ($keys as $key) { + $array[$key+1] = $array[$key]; + unset($array[$key]); + } + asort($array); + return $array; +} + /** * Report to CTools that we use hook_views_api instead of hook_ctools_plugin_api() */ diff --git a/sites/all/modules/views/views_ui.info b/sites/all/modules/views/views_ui.info index 5e5b3da00..ec614466a 100644 --- a/sites/all/modules/views/views_ui.info +++ b/sites/all/modules/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 2011-12-18 -version = "7.x-3.0" +; Information added by drupal.org packaging script on 2012-02-22 +version = "7.x-3.3" core = "7.x" project = "views" -datestamp = "1324170450" +datestamp = "1329946249" -- GitLab