diff --git a/sites/all/modules/views/CHANGELOG.txt b/sites/all/modules/views/CHANGELOG.txt index 7a71a76c494a2a052597ecbc641c11d2049c9d72..744ea75370d41bd68ea1024efc299a3b715ade0b 100644 --- a/sites/all/modules/views/CHANGELOG.txt +++ b/sites/all/modules/views/CHANGELOG.txt @@ -1,5 +1,134 @@ CHANGELOG for Views 3 for Drupal 7 +Views 3.x-7.x-dev +================= +#1017128 by bojanz, dereine: Add support to render a single delta. +follow up by bojanz: Better description for the delta. +#1017254 by dereine: Fix undefined property error in argument_string handler. +#1007886 by dereine: Relationship-fields in field_field handler should use the table alias. +#1018766 by bojanz: Fix click_sort for fieldapi fields. +#1017128 by bojanz: Follow up: Hide field_field if field value is empty. +#1018802 by dereine: Convert 'formula' add_where to add_where_expression. +#1018766 by solotandem: Fix click_sort for fieldapi fields. +#960648 by dereine: Addjust comment link to d7 changes. +#997662 by das-peter: Saving a machine name of a display throws Notice "Undefined property new_id". +#955464 by davereid: Fix notice in views_many_to_one_helper when $operator = 'and'. +#1019438 by dereine: Fix "illegal choice" for unlimited fields. +#1019506 by dereine: Fix the remove items element on the rearrange filter_group form. +#1011004 by dereine: Add validation for query plugin option forms. +#991202 by helmo: Add option to turn linebreaks into br tags in field rewriting. +#1001302 by dagmar: Enable attachment displays to have more links. +#1021784 by tim.plunkett: Extra space added in some classes erroneously. +#862072 by jhedstrom: Allow argument validator to test if user has edit or delete access to a node. +Fix fieldsets in field handler. +#962564 by joshuajabbour: Allow link attributes to be rewritten (internally). +#672864 by dboulet: cols- class incorrect on table, grid. +#981872 by infojunkie: Option to hide attachments in summary views. +#839810 by marcp: Get UID from URL argument default plugin should accept uids from Views pages. +#1012584 by dereine: Allow filtering on term descriptions. +#895046 by bojanz, dereine, merlinofchaos: Implement proper multiple field api handling and improve field api rendering in general. +#1035168 by Ao: Fix strict warning in unread node filter. +#1044916 by dagmar: Fix improper use of set_current_page member variable. +#1016814 by eaton: string argument should support name_field. +#1007376 by dereine: Jump menu was not correctly supporting offsets. +#1018160 by zhangtaihao: unpack_translatable could infinitely recurse when options are arrays but not declared as such. +#776830: Attachments and other displays lost "Items to display" controls. +#747782 by dereine: Improve jump menu grouping. +#1026014 by dereine and alex_b: Use more always should not ask for the count query to see if we need to show the more link. +#1012596 by dereine: More inline documentation of class variables. +#988680 by mikeytown2: Fix Views memory leak with attachments. +#1023062 by mikejoconnor: Replace views_process_dependency with ctools_dependent_process again. +#1023558 by mariusz.slonina: Add a user cancel account link. +#1015960 by duellj: View js should use DOM element not jquery object. +#1027552 by david_Rothstein: Fix Node: Has new content fatal error. +#955464 by dereine: Fix many_to_one helper in the case of have no condition and operator = 'and'. +#696550: Taxonomy validator should always set title when it successfully validates. +#869172 by bendiy: Add an "external" parameter to field link rewriting so that external URLs can be formed properly even without a scheme. +#935176 by benoit.borrel: Add "system" table to Views data. +#839236: Fields named "buttons" would disappear from the rearrange UI due to conflict with the buttons on the form. +#783514 by dereine: Allow breaking of strings with + and , +#1000760 by dereine: Prevent htmlspecialchars() error with string arguments. +#1033494 by dereine: Fix filter by user picture: change used handler. +#895046 by bojanz: Follow up of the multiple field handler. Fixes an issue with group-by and rename entity_api_classes. +#1044250 by dereine: Fix notice in views_handler_filter_history_user_timestamp for disabled comment module. +#1018872 by dereine: field_field handler shouldn't force to set base field in relationship. +#1049586 by fgm: Fix strict error in field_field::init. +#1049276 by david_Rothstein: Commit the 6.11 patch to d7. +#1011226 by Chris Gillis, Sutharsan: Fix display of error messages in the views inteface. +#1050962 by Sutharsan: Convert #value to #markup in validate methods. +#1051034 by Manuel Garcia: Allow field wrapper class to take multiple classes. +#957284 by dereine: Fix search filter to work with d7 version of search.module's api. +#534452 by dereine: Remove non-functional "optional" setting on string filters. +#1019826 by penguin25: Respect contact page access overrides when displaying contact link. +#652684 by dereine: Search and replace error resulted in invalid function name in nid argument validator. +#1008358: Updated for translation plugin to work properly with i18nviews. +#1055378 by mfb: Fix rss_namespaces. +#957284: by dereine: Followup for filter_search fix. +#1063208 by dereine: Fix joins between some tables and file_usage. +#1024586 by merlinofchaos, dereine: Provide a way to move old fields in views data. Additional move field-api data to it. +#990554 by bojanz: Allow to show default values of fields. +#1039460 by robertgarrigos: Rename drupal_set_content to drupal_add_region_content +#1045908 by bfroehle: Fix type in api-upgrading.html +#646456 by xslim: Add a workaround to run update.php +#1055602 by dereine: Convert argument search to dbtng. +#1039584 by dereine: Fix path of taxonomy path, function from d6 +#1019746 by Ralf: Check_plain role names. +#1006482 by dereine: Fix filter: user posted or commented handler. +#870960 by bojanz, dereine: Field label should derive from field Label, not field name. +#1056824 by greggles: Rename the displayed permission from "access all views" to "bypass views access control". +#1022052 bojanz, dereine: Don't add the field_info into the views data array +#970162 by longwave: Add "time hence" options to date field format +#1069100 by paranojik: remove legacy code from views_plugin_row_comment_view:pre_render(). +#741234 by voxpelli: Arguments should check for NULL along with empty string to find empty values. +#1046170 by agentrickard, blackice2999, dereine: Execute preExecute before generate the countQuery to fix pagers with node_access. +#1046170 (follow up) by agentrickard: Provide a better documentation for the problem. +#1070112 by drunken_monkey: Fix notice in field_views_field_label. +#978824 by dereine: Don't execute validation on config_item remove button. +by dereine: Convert op_shorter/longer in filter_string to add_where_expression. +#1046650 by dereine, damz: Don't delete views in the simpletest. +#1022052 follow up by bojanz: Fix filter_list handler, by loading the field_info again. +#1023794 by turek: Fix notice in many_to_one_helper. +#1057810 by mariusz.slonina: Remove views_handler_field_user_link_delete and the views_data entry. +#1075598 by paranojik: small fix for the single argument case. +#1053164 by dereine: Support random sort for sqlite by using dbtng functionality. +#1073862 by solotandem: Title of columns from field revision tables shouldn't have the name delta. +#1042072 by das-peter: Fix notice in views_handler_field_field. +#1078570 by duellj: Search filter doesn't work for attachments. +#1068108 by boombatower: Allow row_class to contain multiple classes. +#1078738 by dereine: Add a serialized data field handler and set users.data to it. +#1051308 by dereine: Backport a test fix for views_handler_filter_date from d7v3ui. +#1079496 by dereine: Fix renamed field names for list fields. This caused an additional filter, which didn't worked. +#1080690 by dereine: Store the view object in the query object, so it can be used. +#1080690 by dereine: Fix target/key for querying against sql databases. Therefore don't use db_select anymore. +#1029534 by bojanz: Fix like for pgsql by using db_like correct. +#1051308 by bojanz: Fix date filter handler behaviour with offsets. +#1062506 by dereine: Misnamed parameter for creation of broken handlers. +#1049998 by dereine: Fix jump_menu summary and some possible notices. +#975400 by bojanz, dereine: Refactor field render() functions to accept $value. +#975400 follow up by bojanz: Give field::sanitize_value more power and fix some issues with get_value. +#1052896 by dereine: Fix summary css classes output. +#1046674 by dereine: Rename build_mode to view_mode in row_node_view. This fixes some bugs with code using $node->view_mode. +#1090682 by febbraro: view:load does not clear the cache correctly when reset. +#1090682 by dereine: Write a simpletest for the reset parameter of view::load. +#1054272 by dagmar: String filters are non optional anymore. +#1086158 by dereine: Fix filter handler of list fields. +#1079178 by Manuel Garcia: Provide a views revert drush command. +#1097602 by bojanz: Don't run validation for Cancel button on views wizard. +#1096292 by bojanz: Provide better default for exposed_sorts_label. +#1097964 by dereine: Don't show contextual links when the contextual module is disabled. +#1098006 by bojanz: Fix notice in summary style conversion code. +by dereine: Move get_value and sanitize_value into views_handler to support it for area handlers. +#1098334 by kannary, dereine: Remove merge leftover in views.help.ini. +by dereine: Allow to expose sorts again. +#1098168 by fubhy: HTML Wrapper checkboxes in style settings in default field handler showing weird behavior +#1096366 by jamsilver: Role access plugin: Replacing array_unshift() with reset() +#1096834 by dww: Allow importing views code that starts with '<?php'. +#557160 by joachim: Move docs/docs.php to views.api.php to match the drupal standard of hook documentation. +#1100052 by michielnugter: Fix strict warning of views_handler_argument::get_value. +#1023456 by dereine: Fix many_to_one_helper condition buidling. +#1100738 by bojanz: Extend upgrading docs to include info about argument changes and get_value/sanitize_value. +#1100776 by bojanz: Fix call for get_value in field_user_language handler. + Views 3.x-7.x-alpha1 (05-Jan-2011) ================================== diff --git a/sites/all/modules/views/README.txt b/sites/all/modules/views/README.txt index f6217bba1a08c2f6ad4fe08901a270797b23825a..af47ce0bd14c7862d36101523381041bad4a93e6 100644 --- a/sites/all/modules/views/README.txt +++ b/sites/all/modules/views/README.txt @@ -1,4 +1,3 @@ -// $Id: README.txt,v 1.26.6.1 2009/11/02 22:01:25 merlinofchaos Exp $ Welcome to Views 2. Please see the advanced help for more information. diff --git a/sites/all/modules/views/css/ie/views-admin.ie7.css b/sites/all/modules/views/css/ie/views-admin.ie7.css new file mode 100644 index 0000000000000000000000000000000000000000..346d6a1f47e58b252a0874b11786feba8946a9ce --- /dev/null +++ b/sites/all/modules/views/css/ie/views-admin.ie7.css @@ -0,0 +1,91 @@ +/** + * The query details collapsible divs are not visible in IE7 because has-layout + * is not being triggered. Trigger has-layout with height: 1%; + */ +.views-edit-view .collapsible > .fieldset-wrapper { + height: 1%; +} + +/** + * The column width for the bucket containers in the query details section + * is not being calculated to 32% correctly. Give IE7 a slightly smaller + * width so that the three columns line up next to each other + */ +.views-edit-view .views-display-column { + width: 31.95%; +} + +/** + * IE7 has no idea how large this container should be and it doesn't + * apply has-layout. Expand it's width to 100% and trigger has-layout. + */ +.views-edit-view .views-displays { + height: 1%; + width: 100%; +} + +/** + * IE7 isn't positioning the span correctly as a display-inline element + */ +.views-edit-view .views-displays .icon { + display: block; + float: left; +} + +.views-edit-view .views-displays .icon-add { + top: 2px; +} + +/** + * The add display query dropdown needs a lot of help + */ + +.views-edit-view .views-displays .tabs.secondary { + position: relative; + z-index: 100; +} + +.views-edit-view .views-displays .secondary .open > a { + border-bottom: 1px solid #f1f1f1; +} + +.views-edit-view .views-displays .secondary .action-list { + border-bottom: 1px solid #cbcbcb; + top: 30px; +} + +.views-edit-view .views-displays .secondary input { + text-align: left; +} + +/** + * IE7 does not interpret div > * correctly + */ +.page-admin-structure-views #content .views-ui-display-tab-bucket { + padding-left: 0; + padding-right: 0; + zoom: 1; +} + +.page-admin-structure-views #content .views-display-column + .views-display-column { + margin-top: 0; +} + +/** + * IE7 is interpreting a top margin of 18px from somewhere. remove it + */ + +.page-admin-structure-views #content .views-display-setting { + margin-top: 0; +} + +/** + * IE7 can't handle the + selector that indents form wrappers after a checkbox on the add page + * zoom is necessary to trigger has layout. !imporant is necessary because IE7 is precedent + * to the theme.css stylesheet, even though it is included before this file. + */ + +.page-admin-structure-views #content .form-type-checkbox + .form-wrapper { + margin-left: 27px !important; + zoom: 1; +} \ No newline at end of file diff --git a/sites/all/modules/views/css/views-admin-rtl.css b/sites/all/modules/views/css/views-admin-rtl.css new file mode 100644 index 0000000000000000000000000000000000000000..cb3edaa5aab4f260c73371ac828311ce82c5dbcf --- /dev/null +++ b/sites/all/modules/views/css/views-admin-rtl.css @@ -0,0 +1,102 @@ +/** + * The .css file is intended to only contain positioning and size declarations + * For example: display, position, float, clear, and overflow. + */ + +/* @group Inline lists */ + +.horizontal > * { + float: right; +} + +.horizontal.right { + float: left; +} + +/* @end */ + +/* @group Attachment details + * + * The attachment details section, its tabs for each section and the buttons + * to add a new section + */ + +.form-actions { + float: left; +} + +.views-displays { + float: right; +} + +/* @end */ + +/* @group Attachment details tabs + * + * The tabs that switch between sections + */ + +.views-displays .secondary > li { + float: right; +} + +/* @end */ + +/* @group Attachment details new section button */ + +.views-displays .secondary .action-list { + left: auto; + right: 0; +} + +/* @end */ + +/* @group Attachment details collapsible fieldset */ + +.views-display-tab .fieldset-legend { + left: auto; + right: -5px; +} + +/* @end */ + +/* @group Attachment details actions + * + * Display the "Delete" and "Duplicate" buttons to the right. + */ +.views-display-tab .fieldset-wrapper > .views-ui-display-tab-bucket .actions { + left: 0; + right: auto; +} + +/* @end */ + +/* @group Attachment configuration columns */ + +.views-display-columns > * { + float: right; + margin-left: 0; + margin-right: 1%; + padding-left: 0; + padding-right: 1%; +} + +.views-display-columns > *:first-child { + margin-right: 0; + padding-right: 0; +} + +/* @end */ + +/* @group Settings forms */ + +.views-dependent { + margin-right: 1.5em; +} + +.views-display-setting .label, +.views-display-setting .views-ajax-link { + float: right; +} + +/* @end */ diff --git a/sites/all/modules/views/css/views-admin.advanced_help.css b/sites/all/modules/views/css/views-admin.advanced_help.css new file mode 100644 index 0000000000000000000000000000000000000000..9e804d4ed7578c9dbde423035ca1547b7e87cf42 --- /dev/null +++ b/sites/all/modules/views/css/views-admin.advanced_help.css @@ -0,0 +1,24 @@ +/** + * The .advanced_help.css file is intended to contain styles that override declarations + * in the Advanced Help module. + */ + +/** + * Adjust the advanced help icons + */ +.views-ui-display-tab-bucket .advanced-help-link { + padding: 0; + margin: 5px 3px 0px 6px; /* LTR */ +} + +.views-ui-display-tab-bucket .icon-text { + padding-left: 25px; /* LTR */ +} + +.views-ui-display-tab-bucket .icon-linked { + background-position: 6px -151px; /* LTR */ +} + +.views-ui-display-tab-bucket .icon-unlinked { + background-position: 6px -193px; /* LTR */ +} diff --git a/sites/all/modules/views/css/views-admin.bartik-rtl.css b/sites/all/modules/views/css/views-admin.bartik-rtl.css new file mode 100644 index 0000000000000000000000000000000000000000..0402f26be58f3947994d264106af4c9ae1e277dd --- /dev/null +++ b/sites/all/modules/views/css/views-admin.bartik-rtl.css @@ -0,0 +1,5 @@ +/** + * The .bartik.css file is intended to contain styles that override declarations + * in the Bartik theme. + */ + \ No newline at end of file diff --git a/sites/all/modules/views/css/views-admin.bartik.css b/sites/all/modules/views/css/views-admin.bartik.css new file mode 100644 index 0000000000000000000000000000000000000000..9986830be698afadf534c6af2a2b98f15b25dea0 --- /dev/null +++ b/sites/all/modules/views/css/views-admin.bartik.css @@ -0,0 +1,214 @@ +/** + * The .bartik.css file is intended to contain styles that override declarations + * in the Bartik theme. + */ + +/* @group Attachment details tabs + * + * The tabs that switch between sections + */ + +.views-displays .region-content .secondary, +.views-displays .region-content .secondary { + padding-bottom: 0; + padding-left: 0; +} + +.views-displays .secondary a { + font-size: smaller; +} + +.views-displays .secondary > li a { + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; +} + +.views-displays .secondary > li.open a { + -moz-border-radius: 5px 5px 0 0; + -webkit-border-bottom-left-radius: 0; + -webkit-border-bottom-right-radius: 0; + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + border-radius: 5px 5px 0 0; +} + +.views-displays .secondary .open > a:hover { + color: #0071B3; +} + +.views-displays .secondary input.form-submit { + font-size: smaller; +} + +/* @end */ + +/* @group Modal dialog box + * + * The contents of the popup dialog on the views edit form. + */ + +.views-filterable-options .even .form-type-checkbox { + background-color: #F9F9F9; +} + +.views-ui-dialog .ui-dialog-titlebar-close, +.views-ui-dialog #views-ajax-title, +.views-ui-dialog .views-override, +.views-ui-dialog .form-buttons { + background-color: #f6f6f6; +} + +/* @end */ + +/* @group CTools */ + +/* @group Buttons */ + +.ctools-button { + background-image: + -moz-linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + background-image: + -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0.0, rgba(255, 255, 255, 1.0)), + color-stop(1.0, rgba(249, 249, 249, 1.0)) + ); + background-image: + -webkit-linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + background-image: + linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + padding-bottom: 1px; + padding-top: 1px; +} + +.ctools-button:hover { + background-image: + -moz-linear-gradient( + -90deg, + #ffffff 0px, + #f1f1f1 100%); + background-image: + -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0.0, rgba(255, 255, 255, 1.0)), + color-stop(1.0, rgba(241, 241, 241, 1.0)) + ); + background-image: + -webkit-linear-gradient( + -90deg, + #ffffff 0px, + #f1f1f1 100%); + background-image: + linear-gradient( + -90deg, + #ffffff 0px, + #f1f1f1 100%); +} + +.ctools-button li { + padding-left: 9px; + padding-right: 9px; +} + +.ctools-content ul.actions { + padding-bottom: 0; +} + +.ctools-dropbutton.open:hover { + background-image: + -moz-linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + background-image: + -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0.0, rgba(255, 255, 255, 1.0)), + color-stop(1.0, rgba(249, 249, 249, 1.0)) + ); + background-image: + -webkit-linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + background-image: + linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); +} + +.ctools-dropbutton.open { + -moz-box-shadow: 1px 1px 2px rgba(0,0,0,0.25); + -webkit-box-shadow: 1px 1px 2px rgba(0,0,0,0.25); + box-shadow: 1px 1px 2px rgba(0,0,0,0.25); +} + +.ctools-twisty { + top: 0.6667em; +} + +.ctools-dropbutton.open .ctools-twisty { + top: 0.3333em; +} + +.ctools-dropbutton li { + padding-right: 7px; +} + +.views-ui-display-tab-actions .ctools-button input.form-submit { + margin-right: 0; + margin-top: 0; +} + +/* @end */ + +/* @group Collapsible */ + +.ctools-toggle { + margin-top: 0.9em; +} + +.ctools-toggle.ctools-toggle-collapsed { + margin-top: 0.72em; +} + +.views-display-column > .ctools-toggle { + margin-top: 14px; +} + +.views-display-column > .ctools-toggle.ctools-toggle-collapsed { + margin-top: 12px; +} + +.views-ui-display-tab-actions .ctools-button input { + color: #0071B3; +} + +.views-ui-display-tab-actions .ctools-button input:hover, +.views-ui-display-tab-actions .ctools-button input:focus { + color: #018FE2; +} + +/* @end */ + +/* @end */ \ No newline at end of file diff --git a/sites/all/modules/views/css/views-admin.contextual.css b/sites/all/modules/views/css/views-admin.contextual.css new file mode 100644 index 0000000000000000000000000000000000000000..502e94947c45e478028b32f3eebb8f364f987d31 --- /dev/null +++ b/sites/all/modules/views/css/views-admin.contextual.css @@ -0,0 +1,63 @@ +/** + * The .contextual.css file is intended to contain styles that override declarations + * in the Contextual module. + */ + +/* @group Wrapper */ + +#views-live-preview .contextual-links-region-active { + outline: medium none; +} + +#views-live-preview div.contextual-links-wrapper { + right: auto; + top: auto; +} + +html.js #views-live-preview div.contextual-links-wrapper { + display: inline; +} + +/* @end */ + +/* @group Trigger */ + +#views-live-preview a.contextual-links-trigger { + display: block; +} + +/* @end */ + +/* @group List */ + +div.contextual-links-wrapper ul.contextual-links { + -moz-border-radius: 0 4px 4px 4px; + -webkit-border-radius: 0 4px 4px 4px; + border-radius: 0 4px 4px 4px; + min-width: 10em; + padding: 6px 6px 9px 6px; + right: auto; +} + +ul.contextual-links li a, +ul.contextual-links li span { + padding-bottom: 0.25em; + padding-right: 0.1667em; + padding-top: 0.25em; +} + +ul.contextual-links li span { + font-weight: bold; +} + +ul.contextual-links li a { + color: #666666 !important; + margin: 0.25em 0; + padding-left: 1em; +} + +ul.contextual-links li a:hover { + background-color: #badbec; +} + +/* @end */ diff --git a/sites/all/modules/views/css/views-admin.css b/sites/all/modules/views/css/views-admin.css index 8e29f2f1d66bfb6d0fc2e6e3934f6da48c22b341..064d63576c512cfec846803eb9d8fa8bf951208e 100644 --- a/sites/all/modules/views/css/views-admin.css +++ b/sites/all/modules/views/css/views-admin.css @@ -1,724 +1,374 @@ -/* $Id: views-admin.css,v 1.14.4.12 2010/12/24 13:42:00 dereine Exp $ */ - -/* - * Summary pad - */ -/* set up some defaults so weird themes don't override us too badly. */ -.views-tabset { - color: #494949; - background-color: white; -} - -.views-tabset a:visited, -.views-tabset a:hover, -.views-tabset a { - color: #027AC6; -} - -.views-tabset .views-tab fieldset { - margin-top: 0; -} - -/* - * First column: display drawers +/** + * The .css file is intended to only contain positioning and size declarations + * For example: display, position, float, clear, and overflow. */ -.views-tabset .views-tabs { - background: #F6F6F6; - border-top: #D6DBDE 1px solid; - border-bottom: #D6DBDE 1px solid; - border-left: #D6DBDE 1px solid; - float: left; - width: 117px; - margin-right: 0; -} - -* html .views-tabset .views-tabs { - width: 114px; - position: relative; - left: 4px; -} -.views-tabset .views-tabs ul { - list-style-type: none !important; - list-style-image: none !important; - padding: 0; - margin: 0; - position: relative; -} - -.views-tabset .views-tabs ul li { - background: #efefef; - list-style-type: none; - list-style-image: none; - line-height: 100%; - border-bottom: #D6DBDE 1px solid; - margin: 0; - padding: 0; - position: relative; -} +/* @group Resets */ -.views-tabset .views-tabs ul li.active { - background: #fff url(../images/arrow-active.png) no-repeat right; - position: relative; - width: 118px; - margin-right: -1px; +.views-admin ul, +.views-admin menu, +.views-admin dir { + padding-left: 0; /* LTR for IE */ + /* padding-start is used so that RTL works out of the box */ + -moz-padding-start: 0; + -webkit-padding-start: 0; + padding-start: 0; } -.views-tabset .views-tabs ul li a { - display: block; - font-size: 90%; - color: #777; - font-weight: normal; - padding: 0.5em; -} - -.views-tabset .views-tabs ul li a:hover { - background-color: #f6f6f6; - text-decoration: none; -} - -.views-tabset .views-tabs ul li.active a { - color: #000; - font-weight: bold; -} - -.views-tabset .views-tabs ul li.active a:hover { - color: #000; - background: #fff url(../images/arrow-active.png) no-repeat right; -} - -.views-tabset .extra { - text-align: center; - margin-right: 0; -} - -.views-tabset .extra input { +.views-admin pre { + margin-bottom: 0; margin-top: 0; - margin-right: 0; - font-size: 10px; - white-space: normal; -} - -/* - * Three columns with setting-summaries - */ -.views-tabset .views-display { - border: #D6DBDE 1px solid; - margin-left: 118px; /* 118 -1 causes borders to overlap */ - min-height: 302px; - _height: 300px; /*stupid IE hack */ + white-space: pre-wrap; } -* html .views-tabset .views-display { - margin-left: 114px; -} - -div.views-display-deleted, -div.views-display-deleted div.top, -div.views-display-deleted div.tab-section { - background-color: #eee; -} +/* @end */ -.views-display { - background: #fff; -} - -.views-display div { - font-size: 8pt; - line-height: 12pt; -} - -.views-display .top { - padding: 0.5em 0em 0em 1em; - background: #fff; -} - -.views-display .top .display-title { - font-weight: bold; -} -.views-display .top .display-description { - margin-left: 1em; - font-style: italic; - overflow: hide; - white-space: nowrap; - font-size: 90%; -} - -.views-display .tab-section { - width: 32.5%; - padding: 0; - margin: 0; - float: left; - min-height: 273px; - _height: 274px; -} +/* @group Inline lists */ -.views-display .tab-section .inside { - margin: 0.5em 0.5em 0.5em 1em; +.horizontal > * { + clear: none; + float: left; /* LTR */ } -.views-display .tab-section .inside .views-category { - margin-bottom: 1em; - background: #f6f6f6; - border: 1px #efefef solid; -} - -.views-display .tab-section .inside .views-category-content { - padding: 0em 0em 0.5em 1em; -} - -.views-display .tab-section .inside .views-category-title { - padding: .1em .1em .1em .3em; - margin: 0 0 .1em 0; - font-size: 9pt; - font-weight: bold; - background-color: #efefef; - border-bottom: 1px #efefef solid; -} - -.views-display .tab-section .links { +.horizontal.right { float: right; - font-size: 6pt; - position: relative; - display: inline; -} - -.views-display .tab-section .links a { - font-size: 6pt; - font-style: italic; -} - -.views-display .form-submit, -#views-ajax-pad .form-submit { - margin: 0; -} - -.views-display .middle { - width: 34%; -} - -.views-basic-info { - margin: 0.5em 0em 0 0; - padding: 0.5em; -} - -/* - * AJAX pad, the bottom part where settings are edited. - */ -#views-ajax-pad { - background: transparent; - margin-top: 0px; -} - -#views-ajax-pad > div.ajax-progress { - display: none; -} - -#views-ajax-title { - background: #f6f6f6; - color: #000; - border-left: #D6DBDE 1px solid; - border-right: #D6DBDE 1px solid; - margin: 0 0 0 118px; - padding: 1em 1em 0em 1em; - font-weight: bold; -} - -#views-ajax-pad .message { - background: #f6f6f6; - color: #000; - margin-left: 118px; - border: #D6DBDE 1px solid; - border-top: 0; - /* padding: 3em 0em; */ - text-align: center; - font-style: italic; } -#views-ajax-pad form { - background: #fff; - color: #000; - margin-left: 118px; - border: #D6DBDE 1px solid; - padding-top: 3px; - border-top: 0; - float: none; +.horizontal label { + position: absolute; } -#views-ajax-pad .views-messages { - background: transparent; - margin-left: 118px; - padding: 5px; - border: #D6DBDE 1px solid; - border-top: 0; +.horizontal .form-item > [class] { + margin-top: 25px; } -#views-ajax-pad .form-buttons { - margin: 0; - padding: 0.5em 1em; - background: #f6f6f6; - clear: left; -} - -#views-ajax-pad .clear { - clear: left; -} - -#views-ajax-pad .form-buttons .form-submit { - font-size: 10px; -} - -#views-ajax-pad .form-item { - margin: 0.5em; - padding: 0em 0.5em; -} - -/* These put checkboxes closer together */ -#views-ajax-pad .form-checkboxes .form-item, -#views-ajax-pad .form-checkboxes .description, -#views-ajax-pad .form-checkboxes input, -#views-ajax-pad .form-radios .form-item, -#views-ajax-pad .form-radios label, -#views-ajax-pad .form-radios input { +.horizontal .form-item > [class] + [class] { margin-top: 0; - margin-bottom: 0; } -#views-ajax-pad .form-item .form-checkboxes, -#views-ajax-pad .form-checkboxes input, -#views-ajax-pad .form-checkboxes label, -#views-ajax-pad .form-item .form-checkboxes .form-item, -#views-ajax-pad .form-item .form-radios, -#views-ajax-pad .form-radios input, -#views-ajax-pad .form-radios label, -#views-ajax-pad .form-item .form-radios .form-item { - padding-left: 0; - margin-left: 0; -} +/* @end */ -#views-ajax-pad .form-checkboxes .description, -#views-ajax-pad .form-radios .description { - margin-left: 2em; -} +/* @group Columns */ -#views-ajax-pad { - display: none; -} - -html.js #views-ajax-pad { - display: block; -} - -.views-override, -.views-expose { - padding: 0.5em 1em 0em 1em; -} - -#views-ajax-pad .views-override .form-submit, -#views-ajax-pad .views-expose .form-submit { - float: right; - margin: 0 .5em 0 1em; -} - -#views-ajax-pad .views-expose .description, -#views-ajax-pad .views-override .description { - margin-bottom: .25em; -} - -/* - * Some column widths for use within the ajax pad - */ -#views-ajax-pad .views-left-10 { - float: left; - width: 10%; -} - -#views-ajax-pad .views-left-20 { - float: left; - width: 20%; -} - -#views-ajax-pad .views-left-25 { +.views-left-25 { float: left; width: 25%; } -#views-ajax-pad .views-left-30 { +.views-left-30 { float: left; width: 30%; } -#views-ajax-pad .views-left-40 { +.views-left-40 { float: left; width: 40%; } -#views-ajax-pad .views-left-50 { +.views-left-50 { + float: left; + width: 50%; +} + +.views-left-75 { float: left; - width: 49.5%; + width: 75%; } -#views-ajax-pad .views-right-50 { +.views-right-50 { float: right; width: 50%; } -#views-ajax-pad .views-right-60 { +.views-right-60 { float: right; width: 60%; } -#views-ajax-pad .views-right-70 { +.views-right-70 { float: right; width: 70%; } -#views-ajax-pad .views-left-75 { - float: left; - width: 75%; -} +/* @end */ -#views-ajax-pad .views-radio-box { - overflow: auto; - height: 22em; -} +/* @group Attachment details + * + * The attachment details section, its tabs for each section and the buttons + * to add a new section + */ -#views-ajax-pad fieldset { - margin: 0 .5em; +.form-actions { + float: right; /* LTR */ } -#views-ajax-pad table td .form-item, -#views-ajax-pad table td .form-item input, -#views-ajax-pad table td .form-item select { - padding: 0; - margin: 0; +.views-displays { + clear: both; + float:left; /* LTR */ } -#views-ajax-pad label.hidden-options { - background: transparent url(../images/arrow-active.png) no-repeat right; - height: 12px; - padding-right: 12px; -} +/* @end */ -#views-ajax-pad label.expanded-options { - background: transparent url(../images/expanded-options.png) no-repeat right; - height: 12px; - padding-right: 16px; -} +/* @group Attachment details tabs + * + * The tabs that switch between sections + */ -#views-ajax-pad .dependent-options { - padding-left: 30px; -} + .views-displays .secondary { + border-bottom: 0 none; + margin: 0; + overflow: visible; + padding: 0; + } -/* - * Add, Rearrange and Configure buttons using sprites - */ -a.views-button-configure, -a.views-button-add, -a.views-button-rearrange, -a.views-button-remove { - background:transparent url(../images/sprites.png); +.views-displays .secondary > li { + border-right: 0 none; display: inline-block; - float: right; - height: 12px; - width: 16px; - margin: 2px 0px 1px 0px; - border-bottom: #C2C9CE 1px solid; - border-right: #C2C9CE 1px solid; - padding: 0px; + float: left; /* LTR */ + padding: 0; } -a.views-button-remove { - background-position: 0px -72px; +.views-displays .secondary .open > a { position: relative; -} -a.views-button-remove:hover { - background-position: 0px -84px; + z-index: 51; } -a.views-button-configure { - background-position: 0px -48px; - margin: 0; -} -a.views-button-configure:hover { - background-position: 0px -60px; +.views-displays .views-display-deleted-link { + text-decoration: line-through; } -a.views-button-add { - background-position: 0px -24px; -} -a.views-button-add:hover { - background-position: 0px -36px; +.views-display-deleted > fieldset > legend, +.views-display-deleted .fieldset-wrapper > .views-ui-display-tab-bucket > *, +.views-display-deleted .views-display-columns { + opacity: 0.25; } -a.views-button-rearrange { - background-position: 0px 0px; -} -a.views-button-rearrange:hover { - background-position: 0px -12px; +.views-display-tab .fieldset-wrapper > .views-ui-display-tab-bucket .actions { + opacity: 1.0; } +/* @end */ -a.views-button-remove span, -a.views-button-rearrange span, -a.views-button-configure span, -a.views-button-add span { - display: none; -} +/* @group Attachment details new section button */ -html.js #arrange thead { - display: none; +.views-displays .secondary li.add { + position: relative; } -html.js #ungroupable_arrange .views-hide-label { - color: #D4E7F3; +.views-displays .secondary .action-list { + left: 0; /* LTR */ + margin: 0; + position: absolute; + top: 23px; + z-index: 50; } -#ungroupable_arrange thead tr { - /* this CSS mirrors what is found in core for blocks admin. */ - background-color: #D4E7F3; - border-bottom: 1px solid #B4D7F0; - border-top: 1.5em solid #FFFFFF; - color: #455067; - padding-top: 0; - padding-bottom: 0; +.views-displays .secondary .action-list li { + display: block; } -html.js .views-remove-checkbox { - display: none; -} +/* @end */ -a.views-button-remove { - display: none; -} +/* @group Attachment details collapsible fieldset */ -html.js a.views-button-remove { - display: inline; +.views-display-tab .fieldset-legend { + left: -5px; /* LTR */ + position: relative; } -.arrange tr.even, -.arrange tr.odd, -.arrange td { - padding-top: 0; - padding-bottom: 0; +.views-display-tab .fieldset-wrapper { + position: relative; } -.arrange .form-item { - padding: 0; -} +/* @end */ -div.changed { - background-color: #ffe; - font-weight: bold; +/* @group Attachment details actions + * + * Display the "Delete" and "Duplicate" buttons to the right. + */ +.views-display-tab .fieldset-wrapper > .views-ui-display-tab-bucket .actions { + position: absolute; + right: 0; /* LTR */ + top: -5px; } -div.view-changed { - display: none; - float: right; - font-style: italic; - color: #f93; - padding-left: 1em; -} +/* @end */ -div.views-tab div.changed a { +/* @group Attachment configuration columns */ +.views-display-columns > * { + float: left; /* LTR */ + margin-left: 1%; /* LTR */ + padding-left: 1%; /* LTR */ + width: 32%; } -div.changed div.view-changed { - display: block; +.views-display-columns > *:first-child { + margin-left: 0; /* LTR */ + padding-left: 0; /* LTR */ } -.views-display .tab-section .inside .overridden { - /* all this so we don't mess up background-color */ -/* background-image: url(../images/overridden.gif); - background-repeat: no-repeat; - background-position: left; - padding-left: 10px; */ -} +/* @end */ -.views-display .tab-section .views-category-content.overridden { - background-image: none; -} +/* @group Modal dialog box */ -.views-display .tab-section .inside .defaulted { - color: #aaa; - font-style: italic; +.views-ui-dialog { + /* We need this so the button is visible. */ + overflow: visible; + position: fixed; } -.views-display .tab-section .inside .defaulted a { - font-style: italic; +.views-ui-dialog .ui-dialog-titlebar-close { + border: 1px solid transparent; + display: block; + margin: 0; + padding: 0; + position: absolute; + right: 0; + top: 2px; + /* Make sure this is in front of the modal backdrop. */ + z-index: 1002; } -.hilited { - color: #000; - font-weight: bold; - background-color: #ffd; - padding-left: 10px; +.views-ui-dialog .ui-dialog-titlebar { + padding: 0; + margin: 0; } -#views-ajax-pad fieldset { - background: transparent; - padding-left: 10px; +.views-ui-dialog .ui-dialog-title { + display: none; } -#views-ajax-pad pre { - overflow: auto; - border: 1px solid #333; - background-color: #f0f0f0; - padding: .5em; +.views-ui-dialog #views-ajax-popup { + padding: 0; + overflow: hidden; } -form#views-ui-reorder-displays-button { - margin-bottom: 0em; - border-bottom: 1px solid #ccc; -} -form#views-ui-reorder-displays-button input.form-submit{ - margin-bottom: 2em; +.views-ui-dialog #views-ajax-title, +.views-ui-dialog #views-ajax-body { + margin: 0; + padding: 0; } -form#views-add-display-form { - margin-bottom: 0em; - border-bottom: 1px solid #ccc; +.views-ui-dialog #views-ajax-popup { + overflow: hidden; } -form#views-add-display-form select { - width: 8.5em; +.views-ui-dialog .scroll { + max-height: 400px; + overflow: auto; } -#views-ui-edit-view-form { - margin: 10px 0 0; - padding: 0; - clear: both; +#views-filterable-options-controls { + display: none; } -#views-live-preview { - padding-top: .5em; +.views-ui-dialog #views-filterable-options-controls { + display: block; } -#views-live-preview form, -#center #views-live-preview form { - border: 1px solid #D6DBDE; - margin: 0 0 .5em 0; - padding: .5em; +/* Don't let the messages overwhelm the modal */ +.views-ui-dialog .views-messages { + max-height: 200px; + overflow: auto; } -#views-live-preview form div.form-item { - float: left; - margin: 0; - padding: 0 1em 0 0; -} +/* @end */ -#views-live-preview form input#preview-submit { - margin: 1em 0 0 0; -} +/* @group Settings forms */ -.view-locked { - color: red; - border: 1px solid red; - padding: 1em; +.views-display-setting .label, +.views-display-setting .views-ajax-link { + display: inline-block; + float: left; /* LTR */ } -/* Hide by default only with js */ -html.js .views-hidden { - display: none; -} +/* @end */ -.views-query-info { -/* overflow: auto; */ -} +/* @group Filter Settings form */ -.views-query-info pre { - white-space: pre; /* CSS2 */ - white-space: -moz-pre-wrap; /* Mozilla */ - white-space: -hp-pre-wrap; /* HP printers */ - white-space: -o-pre-wrap; /* Opera 7 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: pre-wrap; /* CSS 2.1 */ - white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */ - word-wrap: break-word; /* IE */ - max-height: 200px; - overflow: scroll; +div.form-item-options-value-all { + display: none; } +/* @end */ -.views-quick-links { - float: right; -} +/* @group Drupal overrides */ -.views-quick-links ul.links li { - padding-left: 1em; +/* The .progress-disabled class added to the form on submit floats the element + * left and causes the form width to shrink-wrap to the content. Setting the + * width to 100% prevents this. + */ +#views-ajax-body form { + width: 100%; } -.views-quick-links li.last { -} +/* @end */ -.views-edit-view .advanced-help-link { - padding-right: 3px; -} +/* @group Clearfix + * + * @see http://perishablepress.com/press/2009/12/06/new-clearfix-hack + */ -#views-ajax-title .advanced-help-link { - position: relative; - top: 2px; - padding-right: 3px; + /* Reset the formatting context for all modern browsers */ +.views-display-tab .fieldset-wrapper:after, +ul.secondary:after { + clear: both; + content: " x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x "; + display: block; + font-size: xx-large; + height: 0 !important; + line-height: 0; + overflow: hidden; + visibility: hidden; } -#views-ajax-pad input, -#views-ajax-pad textarea { - max-width: 95%; +/* Reset the formatting context for IE */ +.views-display-tab .fieldset-wrapper, +ul.secondary { + zoom: 1; } -.clone-display, -.remove-display { - float: right; - margin: 0; - padding: .2em 1em 0 0; - position: relative; - top: .1em; -} +/* @end */ -.views-display .remove-display form, -.remove-display input, -.views-display .clone-display form, -.clone-display input { - margin: 0 !important; -} +/* @group Javascript dependent styling */ -.views-validator-options { - padding: 0 1em; - margin: 0 1em; - border: 1px solid; +.js-only { + display: none; } -div.views-category #page-title { - background: none; - padding-top: 0px; +html.js .js-only { + display: inherit; } -.group-populated { - display: none; +html.js span.js-only { + display: inline; } -td.group { - /* this CSS mirrors what is found in core for blocks admin. */ - background-color: #D4E7F3; - border-bottom: 1px solid #B4D7F0; - border-top: 1.5em solid #FFFFFF; - color: #455067; -} +/* @end */ -td.group-title { - font-weight: bold; -} +/* @group AJAX throbber */ -tr.group-message { - font-style: italic; - color:#999999; +/* Base Page */ +.views-admin .ajax-progress-throbber { + /* Can't do center:50% middle: 50%, so approximate it for a typical window size. */ + left: 49%; + position: fixed; + top: 48.5%; + z-index: 1000; } - -.group-message .form-submit, -#views-add-group { - float: right; - clear: both; +.views-admin .ajax-progress-throbber .message { + display: none; } -html.js .views-group-select { +/* Modal */ +#views-ajax-popup .ajax-progress-throbber { + /* Can't do center:50% middle: 50%, so approximate it for a typical window size. */ + left: 49%; + position: fixed; + top: 48.5%; + z-index: 1000; +} +#views-ajax-popup .ajax-progress-throbber .message { display: none; } + +/* @end */ diff --git a/sites/all/modules/views/css/views-admin.ctools.css b/sites/all/modules/views/css/views-admin.ctools.css new file mode 100644 index 0000000000000000000000000000000000000000..5aca45fff3f9773cf0b53e80e8fb3bbc4aed6fc5 --- /dev/null +++ b/sites/all/modules/views/css/views-admin.ctools.css @@ -0,0 +1,222 @@ +/* @group Buttons */ + +.ctools-button { + background-color: #ffffff; + border-color: #cccccc; + font-size: 11px; + padding-bottom: 2px; + padding-top: 2px; +} + +.ctools-button, +.ctools-button input { + text-transform: lowercase; +} + +.ctools-button:hover { + border-color: #b8b8b8; +} + +.ctools-button:active { + border-color: #a0a0a0; +} + +.ctools-button .ctools-content { + padding-bottom: 0; + padding-top: 0; +} + +.ctools-dropbutton .ctools-content { + border-right: 1px solid #e8e8e8; +} + +.ctools-dropbutton .ctools-content ul { + margin: 0; + padding: 0; +} + +.ctools-content ul.actions { + margin-top: 0; + margin-bottom: 0; + padding-left: 0; +} + +.ctools-button .ctools-content a { + background-image: none; + border: medium none; +} + +.ctools-dropbutton.open:hover { + border-color: #D0D0D0; +} + +.ctools-dropbutton.open { + z-index: 100; +} + +.ctools-dropbutton .ctools-link { + border-left: 1px solid #ffffff; +} + +.ctools-dropbutton.open .ctools-content { + padding-bottom: 4px; +} + +.ctools-dropbutton li { + padding-right: 9px; +} + +.ctools-dropbutton.open li + li { + border-top: 1px solid #efefef; + margin-top: 4px; + padding-bottom: 0; + padding-top: 4px; +} + +.ctools-twisty:focus { + outline: medium none; +} + +.views-display-top .ctools-button { + font-size: 12px; + position: absolute; + right: 12px; + top: 7px; +} + +.views-ui-display-tab-bucket .ctools-button { + position: absolute; +} + +.views-ui-display-tab-bucket .ctools-button { + right: 5px; + top: 4px; +} + +.views-ui-display-tab-actions .ctools-button input { + background: none; + border: medium; + font-family: inherit; + font-size: 12px; + padding: 0; + margin-bottom: 0; +} + +.views-ui-display-tab-actions .ctools-button input:hover { + background: none; +} + +/* @end */ + +/* @group Collapsible */ + +.ctools-toggle { + border-bottom-color: transparent; + border-left-color: transparent; + border-right-color: transparent; + border-style: solid; + border-width: 5px 5px 0; + display: inline-block; + float: left; + height: 0; + margin-right: 2px; + margin-top: 0.4545em; + width: 0; +} + +.ctools-toggle.ctools-toggle-collapsed { + border-bottom-color: transparent; + border-left: 4px solid; + border-right-color: transparent; + border-top-color: transparent; + border-width: 5px 0 5px 5px; + margin-left: 2px; + margin-right: 5px; + margin-top: 0.3333em; +} + +.ctools-toggle:hover, +.ctools-collapsible-handle:hover { + cursor: pointer; +} + +.ctools-export-ui-row { + margin-bottom: 0; + padding-top: 0; +} + +.ctools-export-ui-row label { + display: block; + float: left; + width: 55px; +} + +.views-display-settings .ctools-toggle { + color: #000000; +} + +.views-display-column > .ctools-toggle { + margin-left: 6px; + margin-right: 3px; + margin-top: 10px; +} +.views-display-column > .ctools-toggle.ctools-toggle-collapsed { + margin-left: 9px; + margin-right: 5px; + margin-top: 8px; +} + +.views-display-column > .ctools-collapsible-handle { + border-color: #F3F3F3; + border-style: solid; + border-width: 1px 1px 0; + font-size: 13px; + font-weight: normal; + margin: 0; + padding: 6px 3px; +} + +.views-display-column > .ctools-toggle.ctools-toggle-collapsed + .ctools-collapsible-handle { + border-width: 1px; +} + +.views-display-column > .ctools-collapsible-content > .views-ui-display-tab-bucket:first-child { + border-top: medium none; +} + +/* @end */ + +/* @group Dependent */ + +.dependent-options { + margin-left: 18px; /* LTR */ +} + +/* @end */ + +/* @group Export */ + +/* Override for filter button on the views list screen */ +#ctools-export-ui-list-form .form-submit { + margin-top: 0em !important; + margin-right: 0em; +} + +.ctools-export-ui-row + .ctools-export-ui-row { + margin-top: 1em; +} + +.ctools-export-ui-fourth-row input { + margin-top: 5px !important; +} + +/* @end */ + +/* @group Jump list */ + +#views-live-preview .ctools-jump-menu-select{ + max-width: 450px; +} + +/* @end */ + diff --git a/sites/all/modules/views/css/views-admin.garland-rtl.css b/sites/all/modules/views/css/views-admin.garland-rtl.css new file mode 100644 index 0000000000000000000000000000000000000000..b0fcc7a441991ecbed70b1998544dde760ed0ba9 --- /dev/null +++ b/sites/all/modules/views/css/views-admin.garland-rtl.css @@ -0,0 +1,5 @@ +/** + * The .garland.css file is intended to contain styles that override declarations + * in the Garland theme. + */ + \ No newline at end of file diff --git a/sites/all/modules/views/css/views-admin.garland.css b/sites/all/modules/views/css/views-admin.garland.css new file mode 100644 index 0000000000000000000000000000000000000000..fd4edf61e893342e9533f0f69210c40a8b750e8b --- /dev/null +++ b/sites/all/modules/views/css/views-admin.garland.css @@ -0,0 +1,259 @@ +/** + * The .garland.css file is intended to contain styles that override declarations + * in the Garland theme. + */ + +/* @group Attachment details tabs + * + * The tabs that switch between sections + */ + +.views-displays .region-content .secondary, +.views-displays .region-content .secondary { + padding-bottom: 0; + padding-left: 0; +} + +.views-displays .secondary .action-list { + left: 1px; + top: 20px; +} + +.views-displays .secondary .action-list li, +.views-displays .secondary a { + border-color: #e9e9e9; +} + +.views-displays .secondary a { + font-size: 12px; + padding: 2px 7px; +} + +.views-displays ul.secondary li a:hover, +.views-displays ul.secondary li.active a { + border: 1px solid transparent; + padding: 2px 7px; +} + +.views-displays .secondary > li a { + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; +} + +.views-displays .secondary > li.open a { + background-image: none; + -moz-border-radius: 5px 5px 0 0; + -webkit-border-bottom-left-radius: 0; + -webkit-border-bottom-right-radius: 0; + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + border-radius: 5px 5px 0 0; +} + +.views-displays .secondary .open > a:hover { + border-color: #e9e9e9 #e9e9e9 #f1f1f1 #e9e9e9; + border-width: 1px 1px 1px 1px; + color: #0071B3; +} + +.views-displays .secondary input.form-submit { + font-size: 11px; +} + +/* @end */ + +/* @group Attachment buckets + * + * These are the individual "buckets," or boxes, inside the display settings area + */ + +.views-ui-display-tab-bucket h3 { + font-weight: bold; +} + +/* @end */ + +/* @group Modal dialog box + * + * The contents of the popup dialog on the views edit form. + */ + +.views-filterable-options .form-type-checkbox { + margin: 0; +} + +.views-filterable-options .even .form-type-checkbox { + background-color: #F9F9F9; +} + +.views-ui-dialog .ui-dialog-titlebar-close, +.views-ui-dialog #views-ajax-title, +.views-ui-dialog .views-override, +.views-ui-dialog .form-buttons { + background-color: #f6f6f6; +} + +/* @end */ + +/* @group CTools */ + +/* @group Buttons */ + +.ctools-button { + background-image: + -moz-linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + background-image: + -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0.0, rgba(255, 255, 255, 1.0)), + color-stop(1.0, rgba(249, 249, 249, 1.0)) + ); + background-image: + -webkit-linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + background-image: + linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + padding-bottom: 1px; + padding-top: 1px; +} + +.ctools-button:hover { + background-image: + -moz-linear-gradient( + -90deg, + #ffffff 0px, + #f1f1f1 100%); + background-image: + -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0.0, rgba(255, 255, 255, 1.0)), + color-stop(1.0, rgba(241, 241, 241, 1.0)) + ); + background-image: + -webkit-linear-gradient( + -90deg, + #ffffff 0px, + #f1f1f1 100%); + background-image: + linear-gradient( + -90deg, + #ffffff 0px, + #f1f1f1 100%); +} + +.ctools-button ol li, +.ctools-button ul li { + margin: 0; + padding-bottom: 0; +} + +.ctools-content ul.actions { + padding-bottom: 0; +} + +.ctools-dropbutton.open:hover { + background-image: + -moz-linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + background-image: + -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0.0, rgba(255, 255, 255, 1.0)), + color-stop(1.0, rgba(249, 249, 249, 1.0)) + ); + background-image: + -webkit-linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + background-image: + linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); +} + +.ctools-dropbutton.open { + -moz-box-shadow: 1px 1px 2px rgba(0,0,0,0.25); + -webkit-box-shadow: 1px 1px 2px rgba(0,0,0,0.25); + box-shadow: 1px 1px 2px rgba(0,0,0,0.25); +} + +.ctools-twisty { + top: 0.6667em; +} + +.ctools-dropbutton.open .ctools-twisty { + top: 0.3333em; +} + +/* @end */ + +/* @group Dependent */ + +.dependent-options, +.form-checkboxes.dependent-options, +.form-radios.dependent-options, +.form-checkboxes .form-item.dependent-options, +.form-radios .form-item.dependent-options { + margin-left: 25px; +} + +/* @end */ + +/* @group Collapsible */ + +.ctools-toggle { + margin-top: 0.5em; +} + +.ctools-toggle, +.views-display-settings .ctools-toggle { + color: #494949; +} + +.ctools-toggle.ctools-toggle-collapsed { + margin-top: 0.25em; +} + +.views-display-column > .ctools-toggle { + margin-top: 14px; +} + +.views-display-column > .ctools-toggle.ctools-toggle-collapsed { + margin-top: 12px; +} + +.views-ui-display-tab-actions .ctools-button input { + color: #027AC6; + font-size: 12px; +} + +.views-ui-display-tab-actions .ctools-button input:hover, +.views-ui-display-tab-actions .ctools-button input:focus { + color: #0062A0; +} + +/* @end */ + +/* @end */ \ No newline at end of file diff --git a/sites/all/modules/views/css/views-admin.seven-rtl.css b/sites/all/modules/views/css/views-admin.seven-rtl.css new file mode 100644 index 0000000000000000000000000000000000000000..e01f83019ede7664a66ba8f15230d7d83f8f00bf --- /dev/null +++ b/sites/all/modules/views/css/views-admin.seven-rtl.css @@ -0,0 +1,29 @@ +/** + * The .seven.css file is intended to contain styles that override declarations + * in the Seven admin theme. + */ + +/* @group Forms */ + +.views-admin .form-submit, +.views-admin a.button { + margin-left: 0; +} + +/* @end */ + +/* @group Lists */ + +.views-admin .links li { + padding-left: 0; +} + +/* @end */ + +/* @group Attachments */ + +.views-displays .secondary { + text-align: right; +} + +/* @end */ diff --git a/sites/all/modules/views/css/views-admin.seven.css b/sites/all/modules/views/css/views-admin.seven.css new file mode 100644 index 0000000000000000000000000000000000000000..de912661d4a18c997fb56089ec2970b386138cc5 --- /dev/null +++ b/sites/all/modules/views/css/views-admin.seven.css @@ -0,0 +1,532 @@ +/** + * The .seven.css file is intended to contain styles that override declarations + * in the Seven admin theme. + */ + +/* @group Content */ + +.views-ui-display-tab-bucket h1, +.views-ui-display-tab-bucket h2, +.views-ui-display-tab-bucket h3, +.views-ui-display-tab-bucket h4, +.views-ui-display-tab-bucket h5 { + margin-bottom: 0; + margin-top: 0; +} + +/* @end */ + +/* @group Forms */ + +.views-ui-dialog fieldset { + padding-top: 2.5em; +} + +fieldset fieldset { + border: medium none; +} + +/** + * Seven positions the legend absolutely, but does not have a way to ignore + * fieldsets without a legend so we make one up. + */ +fieldset.fieldset-no-legend { + padding-top: 0; +} + +/** + * Being extra safe here and scoping this to the add view wizard form (where + * a layout problem occurs for the Display format fieldset if we don't fix its + * padding), but it's probably safe to just let it apply everywhere. + */ +#views-ui-add-form fieldset fieldset .fieldset-wrapper { + padding-left: 0; + padding-right: 0; +} + +.views-display-tab fieldset { + padding: 0 12px; +} + +.views-display-tab .fieldset-wrapper { + padding: 10px 12px 12px; +} + +.views-display-tab fieldset.box-padding .fieldset-wrapper { + padding: 0; +} + +.views-display-tab legend + .fieldset-wrapper { + padding-top: 2.5em; +} + +.views-admin .form-item label.option { + font-size: 1em; +} + +.views-admin input.form-submit, +.views-ui-dialog input.form-submit, +.views-admin a.button, +.views-ui-dialog a.button { + margin-bottom: 0; + margin-right: 0; /* LTR */ + margin-top: 0; +} + +/* Override for a button on the edit display screen */ +#edit-displays-preview-controls .form-submit { + display: inline-block; + margin-right: 1em; +} + +/* Override for filter button on the views list screen */ +#ctools-export-ui-list-form .form-submit { + margin-bottom: 0; +} + +#ctools-export-ui-list-form .ctools-export-ui-first-row .form-item { + margin-top: 3px; + margin-right: 5px; /* LTR */ +} + +.form-item, +.form-item .form-item { + margin-bottom: 0; + margin-top: 9px; + padding-bottom: 0; + padding-top: 0; +} + +.form-actions { + margin-bottom: 0; + margin-top: 0; +} + +.form-item .form-item { + padding-bottom: 0; + padding-top: 0; +} + +.form-radios > .form-item { + margin-top: 3px; +} + +/* @group Dependent options + * + * Dependent options are identified in CTools dependent.js + */ + +/* The .dependent-options.form-item is necessary to supercede the Seven .form-item + * reset declaration that sets the margin to zero. + */ +.dependent-options, +.dependent-options.form-item, +.form-item-options-expose-required, +.form-item-options-expose-label { + margin-left: 1.5em; +} + +.views-admin-dependent .form-item .form-item, +.views-admin-dependent .form-type-checkboxes, +.views-admin-dependent .form-type-radios, +.views-admin-dependent .dependent-options, +.views-admin-dependent .form-item .form-item, +.views-admin-dependent .dependent-options .form-type-select, +.views-admin-dependent .dependent-options .form-type-textfield, +.form-item-options-expose-required, +.form-item-options-expose-label { + margin-bottom: 6px; + margin-top: 6px; +} + +.views-admin-dependent .form-type-radio, +.views-admin-dependent .form-radios .form-item { + margin-bottom: 2px; + margin-top: 2px; +} + +/* @end */ + +/* @end */ + +/* @group Lists */ + +.views-admin ul.secondary, +.views-admin .item-list ul { + margin: 0; + padding: 0; +} + +.views-admin ul.secondary { + clear: none; +} + +.views-displays ul.secondary li a { + padding: 2px 7px 3px; +} + +.views-admin .links li { + padding-right: 0; /* LTR */ +} + +.views-admin .button .links li { + padding-right: 12px; /* LTR */ +} + +.page-admin-structure-views #content ul.action-links { + padding-left: 0; + padding-right: 0; +} + +.views-display-top ul.secondary { + background-color: transparent; +} + +/* @end */ + +/* @group Buttons */ + +.ctools-button ul { + margin: 0; +} + +/* Override for input elements that are themed like ctools-buttons */ +.ctools-button input.form-submit:hover { + background-image: none; + color: #0074BD; + text-shadow: none; +} + +.ctools-button input.form-submit:active { + background: none; + border: medium none; + color: #0074BD; + text-shadow: none; +} + +/* @end */ + +/* @group Tables */ + +table td, +table th { + vertical-align: top; +} + +/* @end */ + +/* @group Attachment details */ + +#edit-display-settings-title { + color: #008BCB; +} + +/* @end */ + +/* @group Attachment details tabs + * + * The tabs that switch between sections + */ + +.views-displays .secondary { + text-align: left; /* LTR */ +} + +.views-displays .secondary > li:first-child { + padding-left: 0; +} + +.views-admin .icon.add { + background-position: center 3px; +} + +.views-displays .secondary a { + background-color: #f1f1f1; + -moz-border-radius: 7px; + -webkit-border-radius: 7px; + border-radius: 7px; + color: #008BCB; +} + +.views-displays .secondary a:hover > .icon.add { + background-position: center -25px; +} + +.views-displays .secondary .open > a { + -moz-border-radius: 7px 7px 0 0; + -webkit-border-radius: 7px 7px 0 0; + border-radius: 7px 7px 0 0; +} + +.views-displays .secondary .open > a:hover { + background-color: #f1f1f1; + color: #008BCB; +} + +.views-displays .secondary .action-list li:first-child { + -moz-border-radius: 0 7px 0 0; + -webkit-border-radius: 0 7px 0 0; + border-radius: 0 7px 0 0; +} + +.views-displays .secondary .action-list li:last-child { + -moz-border-radius: 0 0 7px 7px; + -webkit-border-radius: 0 0 7px 7px; + border-radius: 0 0 7px 7px; +} + +.views-displays .secondary .action-list input.form-submit { + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + color: #008BCB; +} + +/* @end */ + +/* @group Attachment buckets + * + * These are the individual "buckets," or boxes, inside the display settings area + */ + +.views-ui-display-tab-bucket h3 { + font-size: 12px; + text-transform: uppercase; +} + +.views-ui-display-tab-bucket .links { + padding: 2px 6px 4px; +} + +.views-ui-display-tab-bucket .links li + li { + margin-left: 3px; +} + +/* @end */ + +/* @group Rearrange filter criteria */ + +#views-ui-rearrange-filter-form .action-links { + margin: 0; + padding: 0; +} + +#views-ui-rearrange-filter-form table { + border: medium none; +} + +#views-ui-rearrange-filter-form [id^="views-row"] { + border: medium none; +} + +#views-ui-rearrange-filter-form tr td:last-child { + border-right: medium none; +} + +#views-ui-rearrange-filter-form .filter-group-operator-row { + border-left: 1px solid transparent !important; + border-right: 1px solid transparent !important; +} + +#views-ui-rearrange-filter-form tr.drag td { + background-color: #FFEE77 !important; +} + +#views-ui-rearrange-filter-form tr.drag-previous td { + background-color: #FFFFBB !important; +} + +/* @end */ + +/* @group Live preview elements */ + +.views-query-info pre { + margin-bottom: 0; + margin-top: 0; +} + +/* @group Query info table */ + +.views-query-info table { + -moz-border-radius: 7px; + -webkit-border-radius: 7px; + border-radius: 7px; + -webkit-border-horizontal-spacing: 1px; + -webkit-border-vertical-spacing: 1px; +} + +.views-query-info table tr td:last-child { + /* Fixes a Seven style that bleeds down into this table unnecessarily */ + border-right: 0 none; +} + +/* @end */ + +/* @end */ + +/* @group Add view */ + +.form-item-page-create, +.form-item-block-create { + margin-top: 13px; +} + +/* @end */ + +/* @group Modal dialog box + * + * The contents of the popup dialog on the views edit form. + */ + +.views-ui-dialog .ui-dialog-titlebar-close { + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + border-color: #cccccc; + right: -27px; + top: -1px; +} + +.views-ui-dialog fieldset.collapsible { + padding-top: 1.5em; +} + +.views-ui-dialog fieldset.collapsed { + padding-top: 2.5em; +} + +.filterable-option .form-item.form-type-checkbox { + /* This selector is aggressive because Seven's reset for .form-items is aggressive. */ + padding-bottom: 4px; + padding-left: 4px; + padding-top: 4px; +} + +/* @end */ + +/* @group CTools */ + +/* @group Buttons */ + +.ctools-button { + background-image: + -moz-linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + background-image: + -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0.0, rgba(255, 255, 255, 1.0)), + color-stop(1.0, rgba(249, 249, 249, 1.0)) + ); + background-image: + -webkit-linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + background-image: + linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + -moz-border-radius: 11px 11px 11px 11px; + -webkit-border-radius: 11px 11px 11px 11px; + border-radius: 11px 11px 11px 11px; +} + +.ctools-button:hover { + background-image: + -moz-linear-gradient( + -90deg, + #ffffff 0px, + #f1f1f1 100%); + background-image: + -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0.0, rgba(255, 255, 255, 1.0)), + color-stop(1.0, rgba(241, 241, 241, 1.0)) + ); + background-image: + -webkit-linear-gradient( + -90deg, + #ffffff 0px, + #f1f1f1 100%); + background-image: + linear-gradient( + -90deg, + #ffffff 0px, + #f1f1f1 100%); +} + +.ctools-dropbutton.open:hover { + background-image: + -moz-linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + background-image: + -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0.0, rgba(255, 255, 255, 1.0)), + color-stop(1.0, rgba(249, 249, 249, 1.0)) + ); + background-image: + -webkit-linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); + background-image: + linear-gradient( + -90deg, + #ffffff 0px, + #f9f9f9 100%); +} + +.ctools-dropbutton.open { + -moz-box-shadow: 1px 1px 2px rgba(0,0,0,0.25); + -webkit-box-shadow: 1px 1px 2px rgba(0,0,0,0.25); + box-shadow: 1px 1px 2px rgba(0,0,0,0.25); +} + +/* @end */ + +/* @group Collapsible */ + +.ctools-toggle { + margin-top: 0.6667em; +} + +.ctools-toggle.ctools-toggle-collapsed { + margin-top: 0.5em; +} + +.views-display-settings .ctools-toggle { + color: #008BCB; +} + +.views-display-column > .ctools-toggle { + margin-top: 14px; +} + +.views-display-column > .ctools-toggle.ctools-toggle-collapsed { + margin-top: 12px; +} + +.views-display-column > .ctools-collapsible-handle { + color: #008BCB; +} + +.views-ui-display-tab-actions .ctools-button input { + color: #0074BD; +} + +/* @end */ + +/* @end */ diff --git a/sites/all/modules/views/css/views-admin.theme-rtl.css b/sites/all/modules/views/css/views-admin.theme-rtl.css new file mode 100644 index 0000000000000000000000000000000000000000..d1478b5d129ec1a594d013d979f2e83e94867ec1 --- /dev/null +++ b/sites/all/modules/views/css/views-admin.theme-rtl.css @@ -0,0 +1,212 @@ +/** + * The .theme.css file is intended to contain presentation declarations including + * images, borders, colors, and fonts. + */ + +/* @end */ + +/* @group Icons */ + +.actions a, +.views-admin .icon, +.views-admin .icon-text { + background-position: right top; +} + +/* Targets any element with an icon -> text combo */ +.views-admin .icon-text { + padding-right: 19px; +} + +.views-admin .icon-linked { + background-position: right -153px; +} + +.views-admin .icon-unlinked { + background-position: right -195px; +} + +.actions .views-button-add { + background-position: right -39px; +} + +.actions .views-button-rearrange { + background-position: right -96px; +} + +.actions .views-button-add:hover { + background-position: right -58px; +} + +.actions .views-button-rearrange:hover { + background-position: right -115px; +} + +.actions .views-button-add:active { + background-position: right -77px; +} + +.actions .views-button-rearrange:active { + background-position: right -134px; +} + +.views-displays .icon-add { + background-position: right -3px; +} + +.views-displays .secondary a:hover > .icon-add { + background-position: right -21px; +} + +.views-displays .secondary .open a:hover > .icon-add { + background-position: right -3px; +} + +/* @end */ + +/* @group Forms */ + +.form-submit + .form-submit, +.views-admin a.button + a.button { + margin-right: 1em; +} + +.container-inline > * + *, +.container-inline .fieldset-wrapper > * + * { + padding-left: 0; + padding-right: 4pt; +} + +.views-admin .form-type-checkbox + .form-wrapper { + margin-right: 16px; +} + +/* @end */ + +/* @group Lists */ + +.horizontal > * + * { + margin-right: 9px; + padding-right: 9px; +} + +/* @end */ + +/* @group Attachments */ + +.views-displays .secondary { + padding: 6px 8px 8px; +} + +.views-displays .views-display-top > ul > li + li { + margin-right: 3px; +} + +.views-displays .views-extra-actions { + left: 10px; +} + +/* @end */ + +/* @group Attachment details tabs + * + * The tabs that switch between sections + */ + +.views-displays .secondary .action-list li:first-child { + -moz-border-radius: 7px 0 0 0; + -webkit-border-top-left-radius: 7px; + -webkit-border-top-right-radius: 0; + border-radius: 7px 0 0 0; +} + +/* @end */ + +/* @group Attachment details collapsible fieldset + * + * The attachment details section is a collapsible fieldset, but should not + * have a border around it. + */ + +.views-display-tab .fieldset-legend { + left: auto; + right: -5px; +} + +/* @end */ + +/* @group Auto preview + * + * The auto-preview checkbox line. This may have more stuff added to it. + */ + +div.form-item-displays-live-preview { + text-align: left; +} + +/* @end */ + +/* @group Attachment buckets + * + * These are the individual "buckets," or boxes, inside the three columns in the + * attachment details section. + */ + +.views-ui-display-tab-bucket .icon-text { + padding-right: 25px; +} + +.views-ui-display-tab-bucket.overridden .views-display-setting { + margin-right: 15px; +} + +/* @end */ + +/* @group Attachment bucket rows + * + * This is each row within one of the "boxes." + */ + +.views-display-setting .label { + margin-left: 3pt; +} + +/* @end */ + +/* @group Modal dialog box + * + * The contents of the popup dialog on the views edit form. + */ + +#views-filterable-options-controls .form-item { + margin-left: 2%; +} + +.views-ui-dialog #views-progress-indicator { + left: 10px; + right: auto; +} + +/* @end */ + +/* @group Rearrange filters + * + * Styling for the form that allows views filters to be rearranged. + */ +.views-operator-label { + padding-right: 0.5em; +} + +/* @end */ + +/* @group Live preview elements */ + +/* @group HTML list */ + +#views-live-preview .view-content > .item-list > ul { + padding-right: 21px; +} + +/* @end */ + +/* @end */ diff --git a/sites/all/modules/views/css/views-admin.theme.css b/sites/all/modules/views/css/views-admin.theme.css new file mode 100644 index 0000000000000000000000000000000000000000..78c318c7043be3ad7e3df2278f26d750a0d364cb --- /dev/null +++ b/sites/all/modules/views/css/views-admin.theme.css @@ -0,0 +1,1053 @@ +/** + * The .theme.css file is intended to contain presentation declarations including + * images, borders, colors, and fonts. + */ + +/* @group Reset */ + +.views-admin .links { + list-style: none outside none; + margin: 0; +} + +.views-admin a:hover { + text-decoration: none; +} + +/* @end */ + +/* @group Layout */ + +.box-padding { + padding-left: 12px; + padding-right: 12px; +} + +.box-margin { + margin-left: 12px; + margin-right: 12px; +} + +/* @end */ + +/* @group Icons */ + +.views-admin .icon { + height: 16px; + width: 16px; +} + +.views-admin .icon, +.views-admin .icon-text { + background-attachment: scroll; + background-image: url("../images/sprites.png"); + background-position: left top; /* LTR */ + background-repeat: no-repeat; +} + +.views-admin a.icon { + background-image: + url("../images/sprites.png"), + -moz-linear-gradient( + -90deg, + #ffffff 0px, + #e8e8e8 100%); + background-image: + url("../images/sprites.png"), + -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0.0, rgba(255, 255, 255, 1.0)), + color-stop(1.0, rgba(232, 232, 232, 1.0)) + ); + background-image: + url("../images/sprites.png"), + -webkit-linear-gradient( + -90deg, + #ffffff 0px, + #e8e8e8 100%); + background-repeat: no-repeat, repeat-y; + border: 1px solid #dddddd; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: 0 0 0 rgba(0,0,0,0.3333) inset; + -webkit-box-shadow: 0 0 0 rgba(0,0,0,0.3333) inset; + box-shadow: 0 0 0 rgba(0,0,0,0.3333) inset; +} + +.views-admin a.icon:hover { + border-color: #d0d0d0; + -moz-box-shadow: 0 0 1px rgba(0,0,0,0.3333) inset; + -webkit-box-shadow: 0 0 1px rgba(0,0,0,0.3333) inset; + box-shadow: 0 0 1px rgba(0,0,0,0.3333) inset; +} + +.views-admin a.icon:active { + border-color: #c0c0c0; +} + +/** + * Targets a <span> element inside an <a> element. + * This assumes no visible text from the span. + */ +.views-admin span.icon { + display: inline-block; + float: left; + position: relative; +} + +.views-admin .icon.compact { + display: block; + overflow: hidden; + text-indent: -9999px; +} + +/* Targets any element with an icon -> text combo */ +.views-admin .icon-text { + padding-left: 19px; /* LTR */ +} + +.views-admin .icon.linked { + background-position: center -153px; +} + +.views-admin .icon.unlinked { + background-position: center -195px; +} + +.views-admin .icon.add { + background-position: center 3px; +} + +.views-admin a.icon.add { + background-position: center 3px, left top; +} + +.views-admin .icon.delete { + background-position: center -52px; +} + +.views-admin a.icon.delete { + background-position: center -52px, left top; +} + +.views-admin .icon.rearrange { + background-position: center -111px; +} + +.views-admin a.icon.rearrange { + background-position: center -111px, left top; +} + +.views-displays .secondary a:hover > .icon.add { + background-position: center -25px; +} + +.views-displays .secondary .open a:hover > .icon.add { + background-position: center 3px; +} + +/* @end */ + +/* @group Forms */ + +fieldset.box-padding { + border: none; +} + +.views-admin fieldset fieldset { + margin-bottom: 0; +} + +.form-item { + margin-top: 9px; + padding-bottom: 0; + padding-top: 0; +} + +.form-type-checkbox { + margin-top: 6px; +} + +input.form-checkbox, +input.form-radio { + vertical-align: baseline; +} + +.form-submit:not(.js-hide) + .form-submit, +.views-admin a.button:not(.js-hide) + a.button { + margin-left: 1em; /* LTR */ +} + +.container-inline { + padding-top: 15px; +} + +.container-inline > * + *, +.container-inline .fieldset-wrapper > * + * { + padding-left: 4pt; /* LTR */ +} + +.views-admin fieldset fieldset.container-inline { + margin-bottom: 1em; + margin-top: 1em; + padding-top: 0; +} + +.views-admin fieldset fieldset.container-inline > .fieldset-wrapper { + padding-bottom: 0; +} + +/* Indent form elements so they're directly underneath the label of the checkbox that reveals them */ +.views-admin .form-type-checkbox + .form-wrapper { + margin-left: 16px; /* LTR */ +} + +/* Hide 'remove' checkboxes. This might be scoped too widely. */ +[class*="form-type-checkbox"][class*="remove"] { + display: none; +} + +/* sizes the labels of checkboxes and radio button to the height of the text */ +.views-admin .form-type-checkbox label, +.views-admin .form-type-radio label { + line-height: 2; +} + +/* @group Dependent options */ + +.views-admin-dependent .form-item { + margin-bottom: 6px; + margin-top: 6px; +} + +/* @end */ + +/* @end */ + +/* @group Lists */ + +.horizontal > * + * { + margin-left: 9px; /* LTR */ + padding-left: 9px; /* LTR */ +} + +.views-ui-view-title { + font-weight: bold; +} + +/* @end */ + +/* @group Messages */ + +.view-changed { + margin-bottom: 21px; +} + +/* @end */ + +/* @group Headings */ + +/* Intentionally targeting h1 */ +.views-admin h1.unit-title { + font-size: 15px; + line-height: 1.6154; + margin-bottom: 0; + margin-top: 18px; +} + +/* @end */ + +/* @group Tables */ + +table td, +table th { + vertical-align: top; +} + +/* @end */ + +/* @group List views */ + +/* These header classes are ambiguous and should be scoped to th elements */ + +th.views-ui-name { + width: 18%; +} + +th.views-ui-description { + width: 26%; +} + +th.views-ui-tag { + width: 8%; +} + +th.views-ui-path { + width: auto; +} + +th.views-ui-operations { + width: 24%; +} + +/* @end */ + +/* @group Add view */ + +/** + * Drupal core forces AJAX triggering elements to float left when they are + * disabled due to AJAX processing. On the add view page, we have inline + * containers where we don't want that behavior; it causes the select dropdown + * which is triggered to jump to the left while the AJAX throbber is active. + * + * See also http://drupal.org/node/769936 (Drupal core issue); when that is + * fixed it may no longer be necessary to do this. + */ +.views-admin .container-inline .progress-disabled { + float: none; +} + +/** + * I wish this didn't have to be so specific + */ +.form-item-description-enable + .form-item-description { + margin-top: 0; +} + +.form-item-description-enable label { + font-weight: bold; +} + +.form-item-page-create, +.form-item-block-create { + margin-top: 13px; +} + +.form-item-page-create label, +.form-item-block-create label { + font-weight: bold; +} + +/* This makes the form elements after the "Display Format" label flow underneath the label */ +.form-item-page-style-style-plugin > label, +.form-item-block-style-style-plugin > label { + display: block; +} + +.views-attachment .options-set label { + font-weight: normal; +} + +/* @end */ + +/* @group Rearrange filters + * + * Styling for the form that allows views filters to be rearranged. + */ + +.group-populated { + display: none; +} + +td.group-title { + font-weight: bold; +} + +.views-ui-dialog td.group-title { + margin: 0; + padding: 0; +} + +.views-ui-dialog td.group-title span { + display: block; + height: 1px; + overflow: hidden; +} + +.group-message .form-submit, +.views-remove-group-link, +#views-add-group { + float: right; + clear: both; +} + +.views-operator-label { + font-style: italic; + font-weight: bold; + padding-left: 0.5em; /* LTR */ + text-transform: uppercase; +} + +.exposed-description { + float: left; + padding-top: 3px; + padding-right: 10px; +} + +/* This keeps the collapsible fieldsets of options from crashing into the bottom + * of the edit option columns. Because the edit option columns are floated, the collapsible + * fieldsets need to be floated as well so that the margin above the fieldset interacts with + * the float edit option columns. + */ +#edit-options .collapsible { + float: left; + width: 100%; +} + +#edit-options-more { + clear: both; +} + +/* @end */ + +/* @group Attachments */ + +.views-displays { + border: 1px solid #CCC; + margin-bottom: 36px; + padding-bottom: 36px; +} + +.views-display-top { + background-color: #F9F9F9; + border-bottom: 1px solid #CCCCCC; + margin-bottom: 14px; + padding: 8px 8px 6px; /* LTR */ + position: relative; +} + +.views-display-top .secondary > li + li { + margin-left: 6px; + padding-left: 0; +} + +#views-display-extra-actions li { + padding: 3px 9px; +} + +/* @end */ + +/* @group Attachment details tabs + * + * The tabs that switch between sections + */ + +.views-displays .secondary a { + border: 1px solid #cbcbcb; + display: inline-block; + font-size: small; + line-height: 1.3333; + padding: 3px 7px; +} + +.views-displays .secondary a:focus { + outline: none; +} + +.views-displays .secondary a:hover, +.views-displays .secondary .active a { + background-color: #666666; + color: #ffffff; + border-bottom-width: 1px; +} + +.views-displays .secondary .open > a { + background-color: #f1f1f1; + border-bottom: 1px solid transparent; + position: relative; +} + +.views-displays .secondary .open > a:hover { + background-color: #f1f1f1; +} + +.views-displays .secondary .action-list li { + background-color: #f1f1f1; + border-color: #cbcbcb; + border-style: solid; + border-width: 0 1px; + padding: 2px 9px; +} + +.views-displays .secondary .action-list li:first-child { + border-width: 1px 1px 0; +} + +.views-displays .secondary .action-list li.last { + border-width: 0 1px 1px; +} + +.views-displays .secondary .action-list li:last-child { + border-width: 0 1px 1px; +} + +.views-displays .secondary .action-list input.form-submit { + background: none repeat scroll 0 0 transparent; + border: medium none; + margin: 0; + padding: 0; +} + +.views-displays .secondary .action-list li:hover { + background-color: #dddddd; +} + +/* @end */ + +/* @group Attachment details */ + +#edit-display-settings { + border-bottom: 3px solid #CCC; + padding-bottom: 12px; +} + +#edit-display-settings-title { + font-size: 14px; + line-height: 1.5; + margin: 0; +} + +#edit-display-settings-top { + padding-bottom: 4px; +} + +#edit-display-settings-content { + margin-top: 12px; +} + +#edit-display-settings-main { + margin-top: 15px; +} + +/* @end */ + +/* @group Attachment columns + * + * The columns that contain the option buckets e.g. Format and Basic Settings + */ + +.views-display-column + .views-display-column { + margin-top: 0; + } + + /* @end */ + +/* @group Auto preview + * + * The auto-preview checkbox line. + */ + +#edit-display-preview-controls { + margin-top: 36px; +} + +#edit-display-preview-controls > div, +#edit-display-preview-controls > input { + float: left; +} + +#edit-display-preview-controls > .form-type-checkbox { + margin-top: 2px; +} + +#edit-display-preview-controls > .form-type-textfield { + margin-top: 5px; +} + +#edit-display-preview-controls .arguments-preview { + font-size: 1em; +} + +#edit-display-preview-controls .arguments-preview, +#edit-display-preview-controls .form-type-textfield { + margin-left: 14px; +} + +#edit-display-preview-controls .form-type-textfield label { + display: inline-block; + float: left; + font-weight: normal; + height: 6ex; + margin-right: 0.75em; +} + +#edit-display-preview-controls .form-type-textfield .description { + white-space: nowrap; +} + +/* @end */ + +/* @group Attachment buckets + * + * These are the individual "buckets," or boxes, inside the display settings area + */ + +.views-ui-display-tab-bucket { + border: 1px solid #f3f3f3; + line-height: 20px; + margin: 0; + padding-top: 4px; +} + +.views-ui-display-tab-bucket + .views-ui-display-tab-bucket { + border-top: medium none; +} + +.views-ui-display-tab-bucket > h3, +.views-ui-display-tab-bucket > .views-display-setting { + padding: 2px 6px 4px; +} + +.views-ui-display-tab-bucket h3 { + font-size: small; + margin: 0; +} + +.views-ui-display-tab-bucket .links.actions { + margin-top: 2px; +} + +.views-ui-display-tab-bucket.access { + padding-top: 0; +} + +.views-ui-display-tab-bucket.page-settings { + border-bottom: medium none; +} + +.views-display-setting .views-ajax-link { + margin-left: 0.2083em; + margin-right: 0.2083em; +} + +/* @end */ + +/* @group Attachment bucket overridden + * + * Applies a broken link icon to overridden buckets. + * The better way to implement this would be to add the overridden class + * to the bucket header when the bucket is overridden and style it as a + * generic icon classed element. For the moment, we'll style the bucket + * header specifically with the broken link icon. + */ + +.views-ui-display-tab-setting.overridden, +.views-ui-display-tab-bucket.overridden > h3 { + background-attachment: scroll; + background-image: url("../images/sprites.png"); + background-position: left -172px; /* LTR */ + background-repeat: no-repeat; + overflow: hidden; + padding-left: 21px; + zoom: 1; + margin-left: 4px; +} + +.views-ui-display-tab-bucket.overridden .views-display-setting { + margin-left: 15px; /* LTR */ +} + +/* @end */ + +/* @group Attachment bucket drop button */ + +.views-ui-display-tab-bucket { + position: relative; +} + +/* @end */ + +/* @group Attachment bucket rows + * + * This is each row within one of the "boxes." + */ + +.views-ui-display-tab-bucket .views-display-setting { + color: #666666; + font-size: 12px; + padding-bottom: 2px; +} + +.views-ui-display-tab-bucket .even { + background-color: #f9f9f9; +} + +.views-ui-display-tab-bucket .views-group-text { + margin-top: 6px; + margin-bottom: 6px; +} + +.views-display-setting .label { + margin-right: 3pt; /* LTR */ +} + +/* @end */ + +/* @group Preview + * + * The preview controls and the preview pane + */ + +#edit-displays-preview-controls .fieldset-wrapper > * { + float: left; +} + +#edit-displays-preview-controls .fieldset-wrapper > .form-item { + margin-top: 0.3333em; +} + +#edit-displays-preview-controls .form-submit { + display: inline-block; + margin-right: 1em; +} + +#edit-displays-preview-controls .form-type-textfield { + margin-left: 1em; + position: relative; +} + +#edit-displays-preview-controls .form-type-textfield label { + border-left: 1px solid #999; + padding-left: 1em; + position: absolute; +} + +#edit-displays-preview-controls .form-type-textfield label:after { + content: ":"; +} + +#edit-displays-preview-controls .form-type-textfield label ~ * { + margin-left: 105px; +} + +/* @end */ + +/* @group Modal dialog box + * + * The contents of the popup dialog on the views edit form. + */ + +.views-ui-dialog { + font-size: small; + padding: 0; +} + +.views-ui-dialog .ui-dialog-titlebar-close { + background: url("../images/close.png") no-repeat scroll 6px 3px #F3F4EE; + border-color: #aaaaaa; + -moz-border-radius: 0 10px 12px 0; + -webkit-border-radius: 0 10px 12px 0; + border-radius: 0 10px 12px 0; + border-style: solid; + border-width: 1px 1px 1px 0; + -moz-box-shadow: 0 -2px 0 rgba(0, 0, 0, 0.1); + -webkit-box-shadow: 0 -2px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 -2px 0 rgba(0, 0, 0, 0.1); + height: 22px; + right: -28px; + top: 0; + width: 26px; +} + +.views-ui-dialog .ui-dialog-titlebar-close span { + display: none; +} + +.views-filterable-options .form-type-checkbox { + border: 1px solid #CCC; + padding: 5px 8px; + border-top: none; +} + +.views-filterable-options { + border-top: 1px solid #CCC; +} + +.views-filterable-options .even .form-type-checkbox { + background-color: #F3F4EE; +} + +.filterable-option .form-item { + margin-bottom: 0; + margin-top: 0; +} + +.views-filterable-options .form-type-checkbox .description { + margin-top: 0; + margin-bottom: 0; +} + +#views-filterable-options-controls { + margin: 1em 0; +} + +#views-filterable-options-controls .form-item { + width: 45%; + margin-right: 2%; /* LTR */ +} + +#views-filterable-options-controls input, +#views-filterable-options-controls select { + width: 200px; +} + +.views-ui-dialog .views-filterable-options { + margin-bottom: 10px; +} + +.views-ui-dialog .views-add-form-selected.container-inline { + padding-top: 0; +} + +.views-ui-dialog .views-add-form-selected.container-inline > div { + display: block; +} + +.views-ui-dialog #edit-selected { + margin: 0; + padding: 6px 16px; +} + +.views-ui-dialog #views-ajax-title, +.views-ui-dialog .views-override { + background-color: #F3F4EE; +} + +.views-ui-dialog .views-override { + padding: 0 13px 8px; +} + +.views-ui-dialog .views-override > * { + margin: 0; +} + +.views-ui-dialog #views-ajax-title { + font-size: 15px; + padding: 8px 13px; +} + +.views-ui-dialog #views-progress-indicator { + font-size: 11px; + position: absolute; + right: 10px; /* LTR */ + top: 8px; +} + +.views-ui-dialog #views-progress-indicator:before { + content: "\003C\00A0"; +} + +.views-ui-dialog #views-progress-indicator:after { + content: "\00A0\003E"; +} + +.views-ui-dialog .scroll { + border: 1px solid #CCC; + border-width: 1px 0; + padding: 8px 13px; +} + +.views-ui-dialog fieldset .item-list { + padding-left: 2em; +} + +.views-ui-dialog .form-buttons { + background-color: #F3F4EE; + padding: 8px 13px; +} +.views-ui-dialog .form-buttons input { + margin-bottom: 0; + margin-right: 0; +} + +/* @end */ + +/* @group Configure filter criteria */ + +/* @todo the width and border info could be moved into a more generic class */ +/* @todo Make this a class to be used anywhere there's node types? */ +.form-type-checkboxes #edit-options-value, +.form-type-checkboxes #edit-options-validate-options-node-types { + border-color: #CCCCCC; + border-style: solid; + border-width: 1px; + max-height: 210px; + overflow: auto; + margin-top: 5px; + padding: 0 5px; + width: 190px; +} + +/* @end */ + +/* @group Rearrange filter criteria */ + +#views-ui-rearrange-filter-form table { + border-collapse: collapse; +} + +#views-ui-rearrange-filter-form tr td[rowspan] { + border-color: #CDCDCD; + border-style: solid; + border-width: 0 1px 1px 1px; +} + +#views-ui-rearrange-filter-form tr[id^="views-row"] { + border-right: 1px solid #CDCDCD; +} + +#views-ui-rearrange-filter-form tr[id^="views-row"].even td { + background-color: #F3F4ED; +} + +#views-ui-rearrange-filter-form .views-group-title { + border-top: 1px solid #CDCDCD; +} + +#views-ui-rearrange-filter-form .group-empty { + border-bottom: 1px solid #CDCDCD; +} + +/* @end */ + +/* @group Expose filter form items */ + +.form-item-options-expose-required, +.form-item-options-expose-label { + margin-bottom: 6px; + margin-left: 18px; + margin-top: 6px; +} + +/* @end */ + +/* @group Live preview elements */ + +/** + * Create a horizontal rule above the live preview area. + */ +#views-live-preview { + margin: 0 12px; +} + +/* Intentionally targeting h1 */ +#views-live-preview h1.section-title { + color: #818181; + display: inline-block; + font-size: 13px; + font-weight: normal; + line-height: 1.6154; + margin-bottom: 0; + margin-top: 0; +} + +#views-live-preview .view > * { + margin-top: 18px; +} + +#views-live-preview .preview-section { + border: 1px dashed #DEDEDE; + margin: 0 -5px; + padding: 3px 5px; +} + +#views-live-preview li.views-row + li.views-row { + margin-top: 18px; +} + +/* The div.views-row is intentional and excludes li.views-row, for example */ +#views-live-preview div.views-row + div.views-row { + margin-top: 36px; +} + +/* @group Query info table */ + +.views-query-info table { + border-collapse: separate; + border-color: #dddddd; + border-spacing: 0; + margin: 10px 0; +} + +.views-query-info table tr { + background-color: #f9f9f9; +} + +.views-query-info table th, +.views-query-info table td { + color: #666666; + padding: 4px 10px; +} + +/* @end */ + +/* @group Grid */ + +#views-live-preview .views-view-grid th, +#views-live-preview .views-view-grid td { + vertical-align: top; +} + +/* @end */ + +/* @group HTML list */ + +#views-live-preview .view-content > .item-list > ul { + list-style-position: outside; + padding-left: 21px; /* LTR */ +} + +/* @end */ + +/* @end */ + +/* @group Add/edit argument form */ + +#edit-options-default-action { + width: 300px; + float: left; +} + +#edit-options-exception.collapsible { + float: right; + width: 250px; + margin-top: -2px; +} + +/* @end */ + +/* @group AJAX */ + +/* Hide the drupal system throbber image */ +.ajax-progress .throbber { + display: none; +} + +.ajax-progress-throbber { + background-color: #232323; + background-image: url("../images/loading-small.gif"); + background-position: center center; + background-repeat: no-repeat; + -moz-border-radius: 7px; + -webkit-border-radius: 7px; + border-radius: 7px; + height: 24px; + opacity: .9; + padding: 4px; + width: 24px; +} + +/* @end */ + +/* @group Drupal + * + * Overrides to Drupal system CSS + */ +div.messages { + margin-bottom: 18px; +} + +/* @end */ diff --git a/sites/all/modules/views/css/views-list-rtl.css b/sites/all/modules/views/css/views-list-rtl.css index 132462138357ffe50446a2c3095505d9b28b30e5..1b62fc3fb33e47c3cfffd4908de4f7b886158de3 100644 --- a/sites/all/modules/views/css/views-list-rtl.css +++ b/sites/all/modules/views/css/views-list-rtl.css @@ -1,4 +1,3 @@ -/* $Id: views-list-rtl.css,v 1.1 2009/03/25 00:08:45 merlinofchaos Exp $ */ table.views-entry { clear: right; /* RTL */ diff --git a/sites/all/modules/views/css/views-list.css b/sites/all/modules/views/css/views-list.css index 29e4c60bf8d5ddae4f7b76fc1cc835b412d2b98b..73f0aa07cc887ac8af6c1fb714f9b801c6b6b6d3 100644 --- a/sites/all/modules/views/css/views-list.css +++ b/sites/all/modules/views/css/views-list.css @@ -1,4 +1,3 @@ -/* $Id: views-list.css,v 1.12.6.2 2009/11/18 20:04:07 merlinofchaos Exp $ */ table.views-entry { margin: 3px 0; diff --git a/sites/all/modules/views/css/views.css b/sites/all/modules/views/css/views.css index b909f0b2476697076d8a7982a7883c74225734d0..bf96f70bac525105bc3eadd37db7b8c325440232 100644 --- a/sites/all/modules/views/css/views.css +++ b/sites/all/modules/views/css/views.css @@ -1,4 +1,3 @@ -/* $Id: views.css,v 1.11.6.5 2010/07/04 10:04:50 dereine Exp $ */ .views-exposed-form .views-exposed-widget { float: left; /* LTR */ padding: .5em 1em 0 0; /* LTR */ @@ -33,25 +32,11 @@ text-align: center; } -div.view div.views-hide { - display: none; -} - -/** For IE we add the class via js; for other browsers we rely on :hover **/ -div.view div.views-hide-hover, -div.view:hover div.views-hide { - display: block; - position: absolute; - z-index: 200; -} - -/* don't do this one in IE */ -div.view:hover div.views-hide { - margin-top: -1.5em; -} - /* Remove the border on tbody that system puts in */ .views-view-grid tbody { border-top: none; } +.view .progress-disabled { + float: none; +} diff --git a/sites/all/modules/views/docs/views.api.php b/sites/all/modules/views/docs/views.api.php new file mode 100644 index 0000000000000000000000000000000000000000..1485148c029ea0f8afec1653fe612308f0b58006 --- /dev/null +++ b/sites/all/modules/views/docs/views.api.php @@ -0,0 +1,698 @@ +<?php +/** + * @file + * This file contains no working PHP code; it exists to provide additional documentation + * for doxygen as well as to document hooks in the standard Drupal manner. + */ + +/** + * @mainpage Views 2 API Manual + * + * Much of this information is actually stored in the advanced help; please + * check the API topic. This help will primarily be aimed at documenting + * classes and function calls. + * + * An online version of the advanced help API documentation is available from: + * @link http://views-help.doc.logrus.com/help/views/api @endlink + * + * Topics: + * - @ref view_lifetime + * - @ref views_hooks + * - @ref views_handlers + * - @ref views_plugins + * - @ref views_templates + */ + +/** + * @page view_lifetime The life of a view + * + * This page explains the basic cycle of a view and what processes happen. + */ + +/** + * @page views_handlers About Views' handlers + * + * This page explains what views handlers are, how they're written, and what + * the basic conventions are. + * + * - @ref views_field_handlers + * - @ref views_sort_handlers + * - @ref views_filter_handlers + * - @ref views_argument_handlers + * - @ref views_relationship_handlers + */ + +/** + * @page views_plugins About Views' plugins + * + * This page explains what views plugins are, how they're written, and what + * the basic conventions are. + * + * - @ref views_display_plugins + * - @ref views_style_plugins + * - @ref views_row_plugins + */ + +/** + * @defgroup views_hooks Views' hooks + * @{ + * Hooks that can be implemented by other modules in order to implement the + * Views API. + */ + +/** + * Describe table structure to Views. + * + * This hook should be placed in MODULENAME.views.inc and it will be auto-loaded. + * This must either be in the same directory as the .module file or in a subdirectory + * named 'includes'. + * + * The full documentation for this hook is in the advanced help. + * @link http://views-help.doc.logrus.com/help/views/api-tables @endlink + */ +function hook_views_data() { + // This example describes how to write hook_views_data() for the following + // table: + // + // CREATE TABLE example_table ( + // nid INT(11) NOT NULL COMMENT 'Primary key; refers to {node}.nid.', + // plain_text_field VARCHAR(32) COMMENT 'Just a plain text field.', + // numeric_field INT(11) COMMENT 'Just a numeric field.', + // boolean_field INT(1) COMMENT 'Just an on/off field.', + // timestamp_field INT(8) COMMENT 'Just a timestamp field.', + // PRIMARY KEY(nid) + // ); + + // The 'group' index will be used as a prefix in the UI for any of this + // table's fields, sort criteria, etc. so it's easy to tell where they came + // from. + $data['example_table']['table']['group'] = t('Example table'); + + // Define this as a base table. In reality this is not very useful for + // this table, as it isn't really a distinct object of its own, but + // it makes a good example. + $data['example_table']['table']['base'] = array( + 'field' => 'nid', + 'title' => t('Example table'), + 'help' => t("Example table contains example content and can be related to nodes."), + 'weight' => -10, + ); + + // This table references the {node} table. + // This creates an 'implicit' relationship to the node table, so that when 'Node' + // is the base table, the fields are automatically available. + $data['example_table']['table']['join'] = array( + // Index this array by the table name to which this table refers. + // 'left_field' is the primary key in the referenced table. + // 'field' is the foreign key in this table. + 'node' => array( + 'left_field' => 'nid', + 'field' => 'nid', + ), + ); + + // Next, describe each of the individual fields in this table to Views. For + // each field, you may define what field, sort, argument, and/or filter + // handlers it supports. This will determine where in the Views interface you + // may use the field. + + // Node ID field. + $data['example_table']['nid'] = array( + 'title' => t('Example content'), + 'help' => t('Some example content that references a node.'), + // Because this is a foreign key to the {node} table. This allows us to + // have, when the view is configured with this relationship, all the fields + // for the related node available. + 'relationship' => array( + 'base' => 'node', + 'field' => 'nid', + 'handler' => 'views_handler_relationship', + 'label' => t('Example node'), + ), + ); + + // Example plain text field. + $data['example_table']['plain_text_field'] = array( + 'title' => t('Plain text field'), + 'help' => t('Just a plain text field.'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + ); + + // Example numeric text field. + $data['example_table']['numeric_field'] = array( + 'title' => t('Numeric field'), + 'help' => t('Just a numeric field.'), + 'field' => array( + 'handler' => 'views_handler_field_numeric', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ); + + // Example boolean field. + $data['example_table']['boolean_field'] = array( + 'title' => t('Boolean field'), + 'help' => t('Just an on/off field.'), + 'field' => array( + 'handler' => 'views_handler_field_boolean', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_boolean_operator', + 'label' => t('Published'), + 'type' => 'yes-no', + // use boolean_field = 1 instead of boolean_field <> 0 in WHERE statment + 'use equal' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ); + + // Example timestamp field. + $data['example_table']['timestamp_field'] = array( + 'title' => t('Timestamp field'), + 'help' => t('Just a timestamp field.'), + 'field' => array( + 'handler' => 'views_handler_field_date', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort_date', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_date', + ), + ); + + return $data; +} + +/** + * Alter table structure. + * + * You can add/edit/remove to existing tables defined by hook_views_data(). + * + * This hook should be placed in MODULENAME.views.inc and it will be auto-loaded. + * This must either be in the same directory as the .module file or in a subdirectory + * named 'includes'. + * + * The full documentation for this hook is in the advanced help. + * @link http://views-help.doc.logrus.com/help/views/api-tables @endlink + */ +function hook_views_data_alter(&$data) { + // This example alters the title of the node: nid field for the admin. + $data['node']['nid']['title'] = t('Node-Nid'); + + // This example adds a example field to the users table + $data['users']['example_field'] = array( + 'title' => t('Example field'), + 'help' => t('Some examüple content that references a user'), + 'handler' => 'hook_handlers_field_example_field', + ); + + // This example changes the handler of the node title field. + // In this handler you could do stuff, like preview of the node, when clicking the node title. + + $data['node']['title']['handler'] = 'modulename_handlers_field_node_title'; +} + + +/** + * The full documentation for this hook is now in the advanced help. + * + * This hook should be placed in MODULENAME.views.inc and it will be auto-loaded. + * This must either be in the same directory as the .module file or in a subdirectory + * named 'includes'. + * + * This is a stub list as a reminder that this needs to be doc'd and is not used + * in views anywhere so might not be remembered when this is formally documented: + * - style: 'even empty' + */ +function hook_views_plugins() { + // example code here +} + +/** + * Alter existing plugins data, defined by modules. + */ +function hook_views_plugins_alter(&$plugins) { + // Add apachesolr to the base of the node row plugin. + $plugins['row']['node']['base'][] = 'apachesolr'; +} + +/** + * Register View API information. This is required for your module to have + * its include files loaded; for example, when implementing + * hook_views_default_views(). + * + * @return + * An array with the following possible keys: + * - api: (required) The version of the Views API the module implements. + * - path: (optional) If includes are stored somewhere other than within + * the root module directory or a subdirectory called includes, specify + * its path here. + * - template path: (optional) A path where the module has stored it's views template files. + * When you have specificed this key views automatically uses the template files for the views. + * You can use the same naming conventions like for normal views template files. + */ +function hook_views_api() { + return array( + 'api' => 2, + 'path' => drupal_get_path('module', 'example') . '/includes/views', + ); +} + +/** + * This hook allows modules to provide their own views which can either be used + * as-is or as a "starter" for users to build from. + * + * This hook should be placed in MODULENAME.views_default.inc and it will be + * auto-loaded. This must either be in the same directory as the .module file + * or in a subdirectory named 'includes'. + * + * The $view->disabled boolean flag indicates whether the View should be + * enabled or disabled by default. + * + * @return + * An associative array containing the structures of views, as generated from + * the Export tab, keyed by the view name. A best practice is to go through + * and add t() to all title and label strings, with the exception of menu + * strings. + */ +function hook_views_default_views() { + // Begin copy and paste of output from the Export tab of a view. + $view = new view; + $view->name = 'frontpage'; + $view->description = t('Emulates the default Drupal front page; you may set the default home page path to this view to make it your front page.'); + $view->tag = t('default'); + $view->base_table = 'node'; + $view->api_version = 2; + $view->disabled = FALSE; // Edit this to true to make a default view disabled initially + $view->display = array(); + $display = new views_display; + $display->id = 'default'; + $display->display_title = t('Master'); + $display->display_plugin = 'default'; + $display->position = '1'; + $display->display_options = array ( + 'style_plugin' => 'default', + 'style_options' => + array ( + ), + 'row_plugin' => 'node', + 'row_options' => + array ( + 'teaser' => 1, + 'links' => 1, + ), + 'relationships' => + array ( + ), + 'fields' => + array ( + ), + 'sorts' => + array ( + 'sticky' => + array ( + 'id' => 'sticky', + 'table' => 'node', + 'field' => 'sticky', + 'order' => 'ASC', + ), + 'created' => + array ( + 'id' => 'created', + 'table' => 'node', + 'field' => 'created', + 'order' => 'ASC', + 'relationship' => 'none', + 'granularity' => 'second', + ), + ), + 'arguments' => + array ( + ), + 'filters' => + array ( + 'promote' => + array ( + 'id' => 'promote', + 'table' => 'node', + 'field' => 'promote', + 'operator' => '=', + 'value' => '1', + 'group' => 0, + 'exposed' => false, + 'expose' => + array ( + 'operator' => false, + 'label' => '', + ), + ), + 'status' => + array ( + 'id' => 'status', + 'table' => 'node', + 'field' => 'status', + 'operator' => '=', + 'value' => '1', + 'group' => 0, + 'exposed' => false, + 'expose' => + array ( + 'operator' => false, + 'label' => '', + ), + ), + ), + 'items_per_page' => 10, + 'use_pager' => '1', + 'pager_element' => 0, + 'title' => '', + 'header' => '', + 'header_format' => '1', + 'footer' => '', + 'footer_format' => '1', + 'empty' => '', + 'empty_format' => '1', + ); + $view->display['default'] = $display; + $display = new views_display; + $display->id = 'page'; + $display->display_title = t('Page'); + $display->display_plugin = 'page'; + $display->position = '2'; + $display->display_options = array ( + 'defaults' => + array ( + 'access' => true, + 'title' => true, + 'header' => true, + 'header_format' => true, + 'header_empty' => true, + 'footer' => true, + 'footer_format' => true, + 'footer_empty' => true, + 'empty' => true, + 'empty_format' => true, + 'items_per_page' => true, + 'offset' => true, + 'use_pager' => true, + 'pager_element' => true, + 'link_display' => true, + 'php_arg_code' => true, + 'exposed_options' => true, + 'style_plugin' => true, + 'style_options' => true, + 'row_plugin' => true, + 'row_options' => true, + 'relationships' => true, + 'fields' => true, + 'sorts' => true, + 'arguments' => true, + 'filters' => true, + 'use_ajax' => true, + 'distinct' => true, + ), + 'relationships' => + array ( + ), + 'fields' => + array ( + ), + 'sorts' => + array ( + ), + 'arguments' => + array ( + ), + 'filters' => + array ( + ), + 'path' => 'frontpage', + ); + $view->display['page'] = $display; + $display = new views_display; + $display->id = 'feed'; + $display->display_title = t('Feed'); + $display->display_plugin = 'feed'; + $display->position = '3'; + $display->display_options = array ( + 'defaults' => + array ( + 'access' => true, + 'title' => false, + 'header' => true, + 'header_format' => true, + 'header_empty' => true, + 'footer' => true, + 'footer_format' => true, + 'footer_empty' => true, + 'empty' => true, + 'empty_format' => true, + 'use_ajax' => true, + 'items_per_page' => true, + 'offset' => true, + 'use_pager' => true, + 'pager_element' => true, + 'use_more' => true, + 'distinct' => true, + 'link_display' => true, + 'php_arg_code' => true, + 'exposed_options' => true, + 'style_plugin' => false, + 'style_options' => false, + 'row_plugin' => false, + 'row_options' => false, + 'relationships' => true, + 'fields' => true, + 'sorts' => true, + 'arguments' => true, + 'filters' => true, + ), + 'relationships' => + array ( + ), + 'fields' => + array ( + ), + 'sorts' => + array ( + ), + 'arguments' => + array ( + ), + 'filters' => + array ( + ), + 'displays' => + array ( + 'default' => 'default', + 'page' => 'page', + ), + 'style_plugin' => 'rss', + 'style_options' => + array ( + 'description' => '', + ), + 'row_plugin' => 'node_rss', + 'row_options' => + array ( + 'item_length' => 'default', + ), + 'path' => 'rss.xml', + 'title' => t('Front page feed'), + ); + $view->display['feed'] = $display; + // End copy and paste of Export tab output. + + // Add view to list of views to provide. + $views[$view->name] = $view; + + // ...Repeat all of the above for each view the module should provide. + + // At the end, return array of default views. + return $views; +} + +/** + * This hook is called right before all default views are cached to the + * database. It takes a keyed array of views by reference. + */ +function hook_views_default_views_alter(&$views) { + if (isset($views['taxonomy_term'])) { + $views['taxonomy_term']->display['default']->display_options['title'] = 'Categories'; + } +} + +/** + * Stub hook documentation + * + * This hook should be placed in MODULENAME.views_convert.inc and it will be auto-loaded. + * This must either be in the same directory as the .module file or in a subdirectory + * named 'includes'. + */ +function hook_views_convert() { + // example code here +} + +/** + * Stub hook documentation + */ +function hook_views_query_substitutions() { + // example code here +} + +/** + * This hook is called at the very beginning of views processing, + * before anything is done. + * + * Adding output to the view can be accomplished by placing text on + * $view->attachment_before and $view->attachment_after. + */ +function hook_views_pre_view(&$view, &$display_id, &$args) { + // example code here +} + +/** + * This hook is called right before the build process, but after displays + * are attached and the display performs its pre_execute phase. + * + * Adding output to the view can be accomplished by placing text on + * $view->attachment_before and $view->attachment_after. + */ +function hook_views_pre_build(&$view) { + // example code here +} + +/** + * This hook is called right after the build process. The query is + * now fully built, but it has not yet been run through db_rewrite_sql. + * + * Adding output to the view can be accomplished by placing text on + * $view->attachment_before and $view->attachment_after. + */ +function hook_views_post_build(&$view) { + // example code here +} + +/** + * This hook is called right before the execute process. The query is + * now fully built, but it has not yet been run through db_rewrite_sql. + * + * Adding output to the view can be accomplished by placing text on + * $view->attachment_before and $view->attachment_after. + */ +function hook_views_pre_execute(&$view) { + // example code here +} + +/** + * This hook is called right after the execute process. The query has + * been executed, but the pre_render() phase has not yet happened for + * handlers. + * + * Adding output to the view can be accomplished by placing text on + * $view->attachment_before and $view->attachment_after. Altering the + * content can be achieved by editing the items of $view->result. + */ +function hook_views_post_execute(&$view) { + // example code here +} + +/** + * This hook is called right before the render process. The query has + * been executed, and the pre_render() phase has already happened for + * handlers, so all data should be available. + * + * Adding output to the view can be accomplished by placing text on + * $view->attachment_before and $view->attachment_after. Altering the + * content can be achieved by editing the items of $view->result. + * + * This hook can be utilized by themes. + */ +function hook_views_pre_render(&$view) { + // example code here +} + +/** + * Post process any rendered data. + * + * This can be valuable to be able to cache a view and still have some level of + * dynamic output. In an ideal world, the actual output will include HTML + * comment based tokens, and then the post process can replace those tokens. + * + * Example usage. If it is known that the view is a node view and that the + * primary field will be a nid, you can do something like this: + * + * <!--post-FIELD-NID--> + * + * And then in the post render, create an array with the text that should + * go there: + * + * strtr($output, array('<!--post-FIELD-1-->', 'output for FIELD of nid 1'); + * + * All of the cached result data will be available in $view->result, as well, + * so all ids used in the query should be discoverable. + * + * This hook can be utilized by themes. + */ +function hook_views_post_render(&$view, &$output, &$cache) { + +} + +/** + * Stub hook documentation + * + * This hook should be placed in MODULENAME.views.inc and it will be auto-loaded. + * This must either be in the same directory as the .module file or in a subdirectory + * named 'includes'. + * + */ +function hook_views_query_alter(&$view, &$query) { + // example code here +} + +/** + * This hook should be placed in MODULENAME.views.inc and it will be auto-loaded. + * This must either be in the same directory as the .module file or in a subdirectory + * named 'includes'. + * + * Alter the rows that appear with a view preview, which include query and + * performance statistics. $rows is an associative array with two keys: + * - query: An array of rows suitable for theme('table'), containing information + * about the query and the display title and path. + * - statistics: An array of rows suitable for theme('table'), containing + * performance statistics. + * + * Warning: $view is not a reference in PHP4 and cannot be modified here. But it IS + * a reference in PHP5, and can be modified. Please be careful with it. + * + * @see theme_table + */ +function hook_views_preview_info_alter(&$rows, $view) { + // example code here +} + +/** + * @} + */ diff --git a/sites/all/modules/views/drush/views.drush.inc b/sites/all/modules/views/drush/views.drush.inc new file mode 100644 index 0000000000000000000000000000000000000000..4a4c7a335a92a700aa7447f953a7993268a84020 --- /dev/null +++ b/sites/all/modules/views/drush/views.drush.inc @@ -0,0 +1,13 @@ +<?php + +/** + * @file + * Drush integration of views. + */ + +/** + * Adds a cache clear option for views. + */ +function views_drush_cache_clear(&$types) { + $types['views'] = 'views_invalidate_cache'; +} \ No newline at end of file diff --git a/sites/all/modules/views/drush/views_revert.drush.inc b/sites/all/modules/views/drush/views_revert.drush.inc new file mode 100644 index 0000000000000000000000000000000000000000..b72fcc03fd18a016dceab1871f3416f7123e2743 --- /dev/null +++ b/sites/all/modules/views/drush/views_revert.drush.inc @@ -0,0 +1,154 @@ +<?php +/** + * @file + * views-revert - Drush command to revert views overridden in the system. + */ + +/** + * Implement hook_drush_help(). + */ +function views_revert_drush_help($section) { + switch ($section) { + case 'drush:revert-views': + return dt('Reverts all views in the drupal installation that have been overriden. Careful, use with care.'); + } +} + +/** + * Implement hook_drush_command(). + */ +function views_revert_drush_command() { + $items = array(); + + $items['views-revert'] = array( + 'callback' => 'views_revert_views', + 'drupal dependencies' => array('views'), + 'description' => dt('Revert overridden views to their default state. Make sure to backup first.'), + 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL, + 'aliases' => array('vr'), + ); + + return $items; +} + +/** + * Callback function for views-revert command. + */ +function views_revert_views() { + $views = views_get_all_views(); + $i = 0; + // The provided view names specified in the command. + $viewnames = _convert_csv_to_array(func_get_args()); + + // Find all overridden views. + foreach ($views as $view) { + if ($view->disabled) { + continue; + } + if ($view->type == dt('Overridden')) { + $overridden[$view->name] = $view->name; + } + } + + // Return early if there are no views overridden in the system. + if (empty($overridden)) { + return drush_set_error(dt('There are no overridden views in the system.')); + } + + // If the user specified in the command the views to be overridden. + if (!empty($viewnames)) { + foreach ($viewnames as $key => $viewname) { + $is_overridden = key_exists($viewname, $overridden); + // Check if the provided view name is in the system + if ($viewname && !key_exists($viewname, $views)) { + drush_set_error(dt("'@viewname' view is not present in the system.", array('@viewname' => $viewname))); + } + // Check if the provided view is overridden. + elseif (!$is_overridden) { + drush_set_error(dt("The view specified '@viewname' is not overridden.", array('@viewname' => $viewname))); + } + // If the view is overriden, revert it. + elseif ($is_overridden){ + views_revert_view($views[$viewname]); + $i++; + } + // We should never get here but well... + else { + drush_set_error(dt("The view specified '@viewname' is not provided in code, and thus cannot be reverted.", array('@viewname' => $viewname))); + } + } + } + + // The user did not specify any views in the command, prompt the user + else { + // list of choices for the user + $overridden['all'] = dt('Revert all overridden views'); // add a choice at the end + $choice = drush_choice($overridden, 'Enter a number to choose which view to revert.', '!key'); // prompt the user + + if ($choice !== FALSE) { + // revert all views option + if ($choice == 'all') { + $i = views_revert_allviews($views); + } + // else the user specified a single view + else { + views_revert_view($views[$choice]); + $i++; + } + } + + } + + // final results output + if ($i == 0) { + drush_log(dt('No views were reverted.'), 'ok'); + } + else { + drush_log(dt('Reverted a total of @count views.', array('@count' => $i)), 'ok'); + } +} + +/** + * Reverts all views + * @param $views + * All views in the system as provided by views_get_all_views(). + */ +function views_revert_allviews($views) { + $i = 0; + foreach ($views as $view) { + if ($view->disabled) { + continue; + } + + if ($view->type == t('Overridden')) { + views_revert_view($view); + $i++; + } + } + return $i; +} + +/** + * Revert a specified view + * @param $view + * The view object to be reverted + * + * Checks on wether or not the view is overridden is handled in views_revert_views_revert() + * We perform a check here anyway in case someone somehow calls this function on their own... + */ +function views_revert_view($view) { + // check anyway just in case + if ($view->type == t('Overridden')) { + // Revert the view. + $view->delete(); + // Clear its cache. + views_object_cache_clear('view', $view->name); + // Give feedback. + $message = dt("Reverted the view '@viewname'", array('@viewname' => $view->name)); + drush_log($message, 'success'); + // Reverted one more view. + } + else { + drush_set_error(dt("The view '@viewname' is not overridden.", array('@viewname' => $view->name))); + } +} diff --git a/sites/all/modules/views/handlers/views_handler_area.inc b/sites/all/modules/views/handlers/views_handler_area.inc index 85254605ad72a84b476e6a0ba0935bb68bfc83f4..fd82f46901f83112fe32a4f4b4b653a114873152 100644 --- a/sites/all/modules/views/handlers/views_handler_area.inc +++ b/sites/all/modules/views/handlers/views_handler_area.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_area.inc,v 1.1.4.3 2010/12/17 21:42:19 merlinofchaos Exp $ /** * @file * Views area handlers. @@ -86,7 +85,7 @@ class views_handler_area_broken extends views_handler_area { } function ensure_my_table() { /* No table to ensure! */ } - function query() { /* No query to run */ } + function query($group_by = FALSE) { /* No query to run */ } function render($empty = FALSE) { return ''; } function options_form(&$form, &$form_state) { $form['markup'] = array( 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 537de4a789c27d0a93818c51502270da677f0a46..b76c69de16d90e86a09418c9468ebab23b9e85b4 100644 --- a/sites/all/modules/views/handlers/views_handler_area_text.inc +++ b/sites/all/modules/views/handlers/views_handler_area_text.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_area_text.inc,v 1.1.4.7 2010/12/06 17:13:49 dereine Exp $ class views_handler_area_text extends views_handler_area { @@ -18,6 +17,7 @@ class views_handler_area_text extends views_handler_area { '#default_value' => $this->options['content'], '#rows' => 6, '#format' => $this->options['format'], + '#wysiwyg' => FALSE, ); } diff --git a/sites/all/modules/views/handlers/views_handler_area_view.inc b/sites/all/modules/views/handlers/views_handler_area_view.inc new file mode 100644 index 0000000000000000000000000000000000000000..51cc600ee50c2ae132a5cd241d0385d108ca9108 --- /dev/null +++ b/sites/all/modules/views/handlers/views_handler_area_view.inc @@ -0,0 +1,82 @@ +<?php + +/** + * @file + * Views area handlers. Insert a view inside of an area. + */ +class views_handler_area_view extends views_handler_area { + + function option_definition() { + $options = parent::option_definition(); + + $options['view_to_insert'] = array('default' => ''); + $options['inherit_arguments'] = array('default' => FALSE, 'boolean' => TRUE); + return $options; + } + + /** + * Default options form that provides the label widget that all fields + * should have. + */ + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $views = views_get_all_views(); + foreach ($views as $view->name => $view) { + // Exclude the current view + if ($view->name != $this->view->name) { + foreach ($view->display as $display_id => $display) { + $options[$view->name . ':' . $display->id] = t('View: @view Display: @display', array('@view' => $view->name, '@display' => $display->id)); + } + } + } + + $form['view_to_insert'] = array( + '#type' => 'select', + '#title' => t('View to insert'), + '#default_value' => $this->options['view_to_insert'], + '#description' => t('The view to insert into this area.'), + '#options' => $options + ); + + $form['inherit_arguments'] = array( + '#type' => 'checkbox', + '#title' => t('Inherit contextual filters'), + '#default_value' => $this->options['inherit_arguments'], + '#description' => t('If checked, this view will receive the same contextual filters as its parent.'), + ); + } + + /** + * Render the area + */ + function render($empty = FALSE) { + if (!empty($this->options['view_to_insert'])) { + list($view_name, $view_display) = explode(':', $this->options['view_to_insert']); + + $view = views_get_view($view_name); + if (empty($view)) { + return; + } + $view->set_display($view_display); + + // Avoid recursion + $view->parent_views += $this->view->parent_views; + $view->parent_views[] = "$view_name:$view_display"; + + // Check if the view is part of the parent views of this view + $search = "$view_name:$view_display"; + if (in_array($search, $this->view->parent_views)) { + drupal_set_message(t("Recursion detected in view @view display @display.", array('@view' => $view_name, '@display' => $view_display)), 'error'); + } + else { + if (!empty($this->options['inherit_arguments']) && !empty($this->view->args)) { + return $view->preview($view_display, $this->view->args); + } + else { + return $view->preview($view_display); + } + } + } + return ''; + } +} diff --git a/sites/all/modules/views/handlers/views_handler_argument.inc b/sites/all/modules/views/handlers/views_handler_argument.inc index 1438c57be43e5f9425619b926336e86a39476dff..56ee4cc2b9471fdcd5bcbd9ed03fc7dd91f0aa99 100644 --- a/sites/all/modules/views/handlers/views_handler_argument.inc +++ b/sites/all/modules/views/handlers/views_handler_argument.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument.inc,v 1.9.4.12 2010/12/17 21:42:19 merlinofchaos Exp $ /** * @defgroup views_argument_handlers Handlers for arguments @@ -48,6 +47,61 @@ class views_handler_argument extends views_handler { function init(&$view, &$options) { parent::init($view, $options); + + // Compatibility: The new UI changed several settings. + if (!empty($options['wildcard']) && !isset($options['exception']['value'])) { + $this->options['exception']['value'] = $options['wildcard']; + } + if (!empty($options['wildcard_substitution']) && !isset($options['exception']['title'])) { + // Enable the checkbox if the title is filled in. + $this->options['exception']['title_enable'] = 1; + $this->options['exception']['title'] = $options['wildcard_substitution']; + } + + if (!isset($options['summary']['format']) && !empty($options['style_plugin'])) { + $this->options['summary']['format'] = $options['style_plugin']; + } + + if (!isset($options['summary']['sort_order']) && !empty($options['default_action']) && $options['default_action'] == 'summary asc') { + $this->options['default_action'] = 'summary'; + $this->options['summary']['sort_order'] = 'asc'; + $this->options['summary']['number_of_records'] = 0; + $this->options['summary_options'] = $options['style_options']; + } + elseif (!isset($options['summary']['sort_order']) && !empty($options['default_action']) && $options['default_action'] == 'summary desc') { + $this->options['default_action'] = 'summary'; + $this->options['summary']['sort_order'] = 'desc'; + $this->options['summary']['number_of_records'] = 0; + $this->options['summary_options'] = $options['style_options']; + } + elseif (!isset($options['summary']['sort_order']) && !empty($options['default_action']) && $options['default_action'] == 'summary asc by count') { + $this->options['default_action'] = 'summary'; + $this->options['summary']['sort_order'] = 'asc'; + $this->options['summary']['number_of_records'] = 1; + $this->options['summary_options'] = $options['style_options']; + } + elseif (!isset($options['summary']['sort_order']) && !empty($options['default_action']) && $options['default_action'] == 'summary desc by count') { + $this->options['default_action'] = 'summary'; + $this->options['summary']['sort_order'] = 'desc'; + $this->options['summary']['number_of_records'] = 1; + $this->options['summary_options'] = $options['style_options']; + } + + if (!empty($options['title']) && !isset($options['title_enable'])) { + $this->options['title_enable'] = 1; + } + if (!empty($options['breadcrumb']) && !isset($options['breadcrumb_enable'])) { + $this->options['breadcrumb_enable'] = 1; + } + + if (!empty($options['validate_type']) && !isset($options['validate']['type'])) { + $this->options['validate']['type'] = $options['validate_type']; + $this->options['specify_validation'] = 1; + } + if (!empty($options['validate_fail']) && !isset($options['validate']['fail'])) { + $this->options['validate']['fail'] = $options['validate_fail']; + $this->options['specify_validation'] = 1; + } } /** @@ -69,16 +123,19 @@ class views_handler_argument extends views_handler { return !empty($info['breadcrumb']); } - function is_wildcard($arg = NULL) { + function is_exception($arg = NULL) { if (!isset($arg)) { - $arg = $this->argument; + $arg = isset($this->argument) ? $this->argument : NULL; } - - return !empty($this->options['wildcard']) && $this->options['wildcard'] === $arg; + return !empty($this->options['exception']['value']) && $this->options['exception']['value'] === $arg; } - function wildcard_title() { - return $this->options['wildcard_substitution']; + function exception_title() { + // If title overriding is off for the exception, return the normal title. + if (empty($this->options['exception']['title_enable'])) { + return $this->get_title(); + } + return $this->options['exception']['title']; } /** @@ -88,7 +145,7 @@ class views_handler_argument extends views_handler { */ function needs_style_plugin() { $info = $this->default_actions($this->options['default_action']); - $validate_info = $this->default_actions($this->options['validate_fail']); + $validate_info = $this->default_actions($this->options['validate']['fail']); return !empty($info['style plugin']) || !empty($validate_info['style plugin']); } @@ -96,85 +153,95 @@ class views_handler_argument extends views_handler { $options = parent::option_definition(); $options['default_action'] = array('default' => 'ignore'); - $options['style_plugin'] = array('default' => 'default_summary', 'export' => 'export_style'); - $options['style_options'] = array('default' => array(), 'export' => FALSE); - $options['wildcard'] = array('default' => 'all'); - $options['wildcard_substitution'] = array('default' => t('All'), 'translatable' => TRUE); + $options['exception'] = array( + 'contains' => array( + 'value' => array('default' => 'all'), + 'title_enable' => array('default' => 0), + 'title' => array('default' => t('All'), 'translatable' => TRUE), + ), + ); + $options['title_enable'] = array('default' => 0); $options['title'] = array('default' => '', 'translatable' => TRUE); + $options['breadcrumb_enable'] = array('default' => 0); $options['breadcrumb'] = array('default' => '', 'translatable' => TRUE); $options['default_argument_type'] = array('default' => 'fixed', 'export' => 'export_plugin'); $options['default_argument_options'] = array('default' => array(), 'export' => FALSE); - $options['validate_type'] = array('default' => 'none', 'export' => 'export_plugin'); + $options['default_argument_skip_url'] = array('default' => FALSE); + $options['summary_options'] = array('default' => array(), 'export' => FALSE); + $options['summary'] = array( + 'contains' => array( + 'sort_order' => array('default' => 'asc'), + 'number_of_records' => array('default' => 0), + 'format' => array('default' => 'default_summary', 'export' => 'export_summary'), + ), + ); + $options['specify_validation'] = array('default' => 0); + $options['validate'] = array( + 'contains' => array( + 'type' => array('default' => 'none', 'export' => 'export_validation'), + 'fail' => array('default' => 'not found'), + ), + ); $options['validate_options'] = array('default' => array(), 'export' => FALSE); - $options['validate_fail'] = array('default' => 'not found'); return $options; } function options_form(&$form, &$form_state) { parent::options_form($form, $form_state); - $defaults = $this->default_actions(); - - $form['title'] = array( - '#prefix' => '<div class="clearfix">', - '#suffix' => '</div>', - '#type' => 'textfield', - '#title' => t('Title'), - '#default_value' => $this->options['title'], - '#description' => t('The title to use when this argument is present. It will override the title of the view and titles from previous arguments. You can use percent substitution here to replace with argument titles. Use "%1" for the first argument, "%2" for the second, etc.'), - ); - $form['breadcrumb'] = array( - '#prefix' => '<div class="clearfix">', - '#suffix' => '</div>', - '#type' => 'textfield', - '#title' => t('Breadcrumb'), - '#default_value' => $this->options['breadcrumb'], - '#description' => t('The Breadcrumb title to use when this argument is present. If no breadcrumb is set here, default Title values will be used, see "Title" for percent substitutions.'), - ); + $form['#pre_render'][] = 'views_ui_pre_render_move_argument_options'; - $form['clear_start'] = array( - '#markup' => '<div class="clearfix">', + $form['no_argument'] = array( + '#type' => 'fieldset', + '#title' => t('When the filter value is <em>NOT</em> in the URL'), ); - - $form['defaults_start'] = array( - '#markup' => '<div class="views-left-50">', + // Everything in the fieldset is floated, so the last element needs to + // clear those floats. + $form['no_argument']['clearfix'] = array( + '#weight' => 1000, + '#markup' => '<div class="clearfix"></div>', ); - $form['default_action'] = array( '#type' => 'radios', - '#title' => t('Action to take if argument is not present'), + '#process' => array('views_ui_process_container_radios'), '#default_value' => $this->options['default_action'], + '#fieldset' => 'no_argument', ); - $form['defaults_stop'] = array( - '#markup' => '</div>', + $form['exception'] = array( + '#type' => 'fieldset', + '#title' => t('Exceptions'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#fieldset' => 'no_argument', ); - - $form['wildcard'] = array( - '#prefix' => '<div class="views-right-50">', - // prefix and no suffix means these two items will be grouped together. + $form['exception']['value'] = array( '#type' => 'textfield', - '#title' => t('Wildcard'), + '#title' => t('Exception value'), '#size' => 20, - '#default_value' => $this->options['wildcard'], - '#description' => t('If this value is received as an argument, the argument will be ignored; i.e, "all values"'), + '#default_value' => $this->options['exception']['value'], + '#description' => t('If this value is received, the filter will be ignored; i.e, "all values"'), ); - - $form['wildcard_substitution'] = array( - '#suffix' => '</div>', + $form['exception']['title_enable'] = array( + '#type' => 'checkbox', + '#title' => t('Override title'), + '#default_value' => $this->options['exception']['title_enable'], + ); + $form['exception']['title'] = array( '#type' => 'textfield', - '#title' => t('Wildcard title'), + '#title' => t('Override title'), + '#title_display' => 'invisible', '#size' => 20, - '#default_value' => $this->options['wildcard_substitution'], - '#description' => t('The title to use for the wildcard in substitutions elsewhere.'), - ); - - $form['clear_stop'] = array( - '#markup' => '</div>', + '#default_value' => $this->options['exception']['title'], + '#description' => t('Override the view and other argument titles. Use "%1" for the first argument, "%2" for the second, etc.'), + '#dependency' => array( + 'edit-options-exception-title-enable' => array('1'), + ), ); $options = array(); + $defaults = $this->default_actions(); $validate_options = array(); foreach ($defaults as $id => $info) { $options[$id] = $info['title']; @@ -185,18 +252,68 @@ class views_handler_argument extends views_handler { $this->{$info['form method']}($form, $form_state); } } - $form['default_action']['#options'] = $options; - $form['validate_options_div_prefix'] = array( - '#id' => 'views-validator-options', - '#markup' => '<fieldset id="views-validator-options"><legend>' . t('Validator options') . '</legend>', + $form['argument_present'] = array( + '#type' => 'fieldset', + '#title' => t('When the filter value <em>IS</em> in the URL or a default is provided'), + ); + $form['title_enable'] = array( + '#type' => 'checkbox', + '#title' => t('Override title'), + '#default_value' => $this->options['title_enable'], + '#fieldset' => 'argument_present', + ); + $form['title'] = array( + '#type' => 'textfield', + '#title' => t('Provide title'), + '#title_display' => 'invisible', + '#default_value' => $this->options['title'], + '#description' => t('Override the view and other argument titles. Use "%1" for the first argument, "%2" for the second, etc.'), + '#dependency' => array( + 'edit-options-title-enable' => array('1'), + ), + '#fieldset' => 'argument_present', + ); + + $form['breadcrumb_enable'] = array( + '#type' => 'checkbox', + '#title' => t('Override breadcrumb'), + '#default_value' => $this->options['breadcrumb_enable'], + '#fieldset' => 'argument_present', + ); + $form['breadcrumb'] = array( + '#type' => 'textfield', + '#title' => t('Provide breadcrumb'), + '#title_display' => 'invisible', + '#default_value' => $this->options['breadcrumb'], + '#description' => t('Enter a breadcrumb name you would like to use. See "Title" for percent substitutions.'), + '#dependency' => array( + 'edit-options-breadcrumb-enable' => array('1'), + ), + '#fieldset' => 'argument_present', + ); + + $form['specify_validation'] = array( + '#type' => 'checkbox', + '#title' => t('Specify validation criteria'), + '#default_value' => $this->options['specify_validation'], + '#fieldset' => 'argument_present', ); - $form['validate_type'] = array( + $form['validate'] = array( + '#type' => 'container', + '#fieldset' => 'argument_present', + ); + // @todo The mockup wanted to use "Validate using" here, but it doesn't + // work well with many options (they'd need to be changed as well) + $form['validate']['type'] = array( '#type' => 'select', '#title' => t('Validator'), - '#default_value' => $this->options['validate_type'], + '#default_value' => $this->options['validate']['type'], + '#dependency' => array( + 'edit-options-specify-validation' => array('1'), + ), ); $validate_types = array('none' => t('- Basic validation -')); @@ -224,19 +341,20 @@ class views_handler_argument extends views_handler { if ($valid) { $plugin = $this->get_plugin('argument validator', $id); if ($plugin) { - if ($plugin->access() || $this->options['validate_type'] == $id) { - $form['argument_validate'][$id] = array( + if ($plugin->access() || $this->options['validate']['type'] == $id) { + $form['validate']['options'][$id] = array( '#prefix' => '<div id="edit-options-validate-options-' . $id . '-wrapper">', '#suffix' => '</div>', '#type' => 'item', '#input' => TRUE, // trick it into checking input to make #process run - '#process' => array('ctools_dependent_process'), '#dependency' => array( - 'edit-options-validate-type' => array($id) + 'edit-options-specify-validation' => array('1'), + 'edit-options-validate-type' => array($id), ), + '#dependency_count' => 2, '#id' => 'edit-options-validate-options-' . $id, ); - $plugin->options_form($form['argument_validate'][$id], $form_state); + $plugin->options_form($form['validate']['options'][$id], $form_state); $validate_types[$id] = $info['title']; } } @@ -244,17 +362,17 @@ class views_handler_argument extends views_handler { } asort($validate_types); - $form['validate_type']['#options'] = $validate_types; + $form['validate']['type']['#options'] = $validate_types; - $form['validate_fail'] = array( + $form['validate']['fail'] = array( '#type' => 'select', - '#title' => t('Action to take if argument does not validate'), - '#default_value' => $this->options['validate_fail'], + '#title' => t('Action to take if filter value does not validate'), + '#default_value' => $this->options['validate']['fail'], '#options' => $validate_options, - ); - - $form['validate_options_div_suffix'] = array( - '#markup' => '</fieldset>', + '#dependency' => array( + 'edit-options-specify-validation' => array('1'), + ), + '#fieldset' => 'argument_present', ); } @@ -270,10 +388,17 @@ class views_handler_argument extends views_handler { $plugin->options_validate($form['argument_default'][$default_id], $form_state, $form_state['values']['options']['argument_default'][$default_id]); } - $validate_id = $form_state['values']['options']['validate_type']; + // summary plugin + $summary_id = $form_state['values']['options']['summary']['format']; + $plugin = $this->get_plugin('style', $summary_id); + if ($plugin) { + $plugin->options_validate($form['summary']['options'][$summary_id], $form_state, $form_state['values']['options']['summary']['options'][$summary_id]); + } + + $validate_id = $form_state['values']['options']['validate']['type']; $plugin = $this->get_plugin('argument validator', $validate_id); if ($plugin) { - $plugin->options_validate($form['argument_validate'][$default_id], $form_state, $form_state['values']['options']['argument_validate'][$validate_id]); + $plugin->options_validate($form['validate']['options'][$default_id], $form_state, $form_state['values']['options']['validate']['options'][$validate_id]); } } @@ -293,11 +418,21 @@ class views_handler_argument extends views_handler { $form_state['values']['options']['default_argument_options'] = $options; } - $validate_id = $form_state['values']['options']['validate_type']; + // summary plugin + $summary_id = $form_state['values']['options']['summary']['format']; + $plugin = $this->get_plugin('style', $summary_id); + if ($plugin) { + $options = &$form_state['values']['options']['summary']['options'][$summary_id]; + $plugin->options_submit($form['summary']['options'][$summary_id], $form_state, $options); + // Copy the now submitted options to their final resting place so they get saved. + $form_state['values']['options']['summary_options'] = $options; + } + + $validate_id = $form_state['values']['options']['validate']['type']; $plugin = $this->get_plugin('argument validator', $validate_id); if ($plugin) { - $options = &$form_state['values']['options']['argument_validate'][$validate_id]; - $plugin->options_submit($form['argument_validate'][$validate_id], $form_state, $options); + $options = &$form_state['values']['options']['validate']['options'][$validate_id]; + $plugin->options_submit($form['validate']['options'][$validate_id], $form_state, $options); // Copy the now submitted options to their final resting place so they get saved. $form_state['values']['options']['validate_options'] = $options; } @@ -312,57 +447,40 @@ class views_handler_argument extends views_handler { function default_actions($which = NULL) { $defaults = array( 'ignore' => array( - 'title' => t('Display all values'), + 'title' => t('Display all results for the specified field'), 'method' => 'default_ignore', 'breadcrumb' => TRUE, // generate a breadcrumb to here ), + 'default' => array( + 'title' => t('Provide default value'), + 'method' => 'default_default', + 'form method' => 'default_argument_form', + 'has default argument' => TRUE, + 'default only' => TRUE, // this can only be used for missing argument, not validation failure + ), 'not found' => array( - 'title' => t('Hide view / Page not found (404)'), + 'title' => t('Hide view'), 'method' => 'default_not_found', 'hard fail' => TRUE, // This is a hard fail condition ), - 'empty' => array( - 'title' => t('Display empty text'), - 'method' => 'default_empty', - 'breadcrumb' => TRUE, // generate a breadcrumb to here - ), - 'summary asc' => array( - 'title' => t('Summary, sorted ascending'), - 'method' => 'default_summary', - 'method args' => array('asc'), - 'style plugin' => TRUE, - 'breadcrumb' => TRUE, // generate a breadcrumb to here - ), - 'summary desc' => array( - 'title' => t('Summary, sorted descending'), - 'method' => 'default_summary', - 'method args' => array('desc'), - 'style plugin' => TRUE, - 'breadcrumb' => TRUE, // generate a breadcrumb to here - ), - 'summary asc by count' => array( - 'title' => t('Summary, sorted by number of records ascending'), + 'summary' => array( + 'title' => t('Display a summary'), 'method' => 'default_summary', - 'method args' => array('asc', 'num_records'), + 'form method' => 'default_summary_form', 'style plugin' => TRUE, 'breadcrumb' => TRUE, // generate a breadcrumb to here ), - 'summary desc by count' => array( - 'title' => t('Summary, sorted by number of records descending'), - 'method' => 'default_summary', - 'method args' => array('desc', 'num_records'), - 'style plugin' => TRUE, + 'empty' => array( + 'title' => t('Display contents of "No results found"'), + 'method' => 'default_empty', 'breadcrumb' => TRUE, // generate a breadcrumb to here ), - 'default' => array( - 'title' => t('Provide default argument'), - 'method' => 'default_default', - 'form method' => 'default_argument_form', - 'has default argument' => TRUE, - 'default only' => TRUE, // this can only be used for missing argument, not validation failure - ), ); + if ($this->view->display_handler->has_path()) { + $defaults['not found']['title'] = t('Show "Page not found"'); + } + if ($which) { if (!empty($defaults[$which])) { return $defaults[$which]; @@ -381,25 +499,25 @@ class views_handler_argument extends views_handler { $plugins = views_fetch_plugin_data('argument default'); $options = array(); - // This construct uses 'hidden' and not markup because process doesn't - // run. It also has an extra div because the dependency wants to hide - // the parent in situations like this, so we need a second div to - // make this work. - $form['default_options_div_prefix'] = array( - '#type' => 'hidden', - '#id' => 'views-default-options', - '#prefix' => '<div id="views-default-options-wrapper"><fieldset id="views-default-options"><legend>' . t('Provide default argument options') . '</legend>', - '#process' => array('ctools_dependent_process'), - '#dependency' => array('radio:options[default_action]' => array('default')), + $form['default_argument_skip_url'] = array( + '#type' => 'checkbox', + '#title' => t('Skip default argument for view URL'), + '#default_value' => $this->options['default_argument_skip_url'], + '#description' => t('Select whether to include this default argument when constructing the URL for this view. Skipping default arguments is useful e.g. in the case of feeds.') ); $form['default_argument_type'] = array( '#prefix' => '<div id="edit-options-default-argument-type-wrapper">', '#suffix' => '</div>', - '#type' => 'radios', + '#type' => 'select', '#id' => 'edit-options-default-argument-type', - '#title' => t('Default argument type'), + '#title' => t('Type'), '#default_value' => $this->options['default_argument_type'], + + '#dependency' => array('radio:options[default_action]' => array('default')), + // Views custom key, moves this element to the appropriate container + // under the radio button. + '#argument_option' => 'default', ); foreach ($plugins as $id => $info) { @@ -409,16 +527,15 @@ class views_handler_argument extends views_handler { $plugin = $this->get_plugin('argument default', $id); if ($plugin) { if ($plugin->access() || $this->options['default_argument_type'] == $id) { + $form['argument_default']['#argument_option'] = 'default'; $form['argument_default'][$id] = array( '#prefix' => '<div id="edit-options-argument-default-options-' . $id . '-wrapper">', '#suffix' => '</div>', '#id' => 'edit-options-argument-default-options-' . $id, '#type' => 'item', - '#input' => TRUE, // trick it into checking input to make #process run - '#process' => array('ctools_dependent_process'), '#dependency' => array( 'radio:options[default_action]' => array('default'), - 'radio:options[default_argument_type]' => array($id) + 'edit-options-default-argument-type' => array($id) ), '#dependency_count' => 2, ); @@ -428,14 +545,80 @@ class views_handler_argument extends views_handler { } } - $form['default_options_div_suffix'] = array( - '#markup' => '</fieldset></div>', - ); - asort($options); $form['default_argument_type']['#options'] = $options; } + /** + * Provide a form for selecting further summary options when the + * default action is set to display one. + */ + function default_summary_form(&$form, &$form_state) { + $style_plugins = views_fetch_plugin_data('style'); + $summary_plugins = array(); + $format_options = array(); + foreach ($style_plugins as $key => $plugin) { + if ($plugin['type'] == 'summary') { + $summary_plugins[$key] = $plugin; + $format_options[$key] = $plugin['title']; + } + } + + $form['summary'] = array( + // Views custom key, moves this element to the appropriate container + // under the radio button. + '#argument_option' => 'summary', + ); + $form['summary']['sort_order'] = array( + '#type' => 'radios', + '#title' => t('Sort order'), + '#options' => array('asc' => t('Ascending'), 'desc' => t('Descending')), + '#default_value' => $this->options['summary']['sort_order'], + '#dependency' => array('radio:options[default_action]' => array('summary')), + ); + $form['summary']['number_of_records'] = array( + '#type' => 'radios', + '#title' => t('Sort by'), + '#default_value' => $this->options['summary']['number_of_records'], + '#options' => array( + 0 => $this->get_sort_name(), + 1 => t('Number of records') + ), + '#dependency' => array('radio:options[default_action]' => array('summary')), + ); + + $form['summary']['format'] = array( + '#type' => 'radios', + '#title' => t('Format'), + '#options' => $format_options, + '#default_value' => $this->options['summary']['format'], + '#dependency' => array('radio:options[default_action]' => array('summary')), + ); + + foreach ($summary_plugins as $id => $info) { + if (empty($info['uses options'])) { + continue; + } + $plugin = $this->get_plugin('style', $id); + if ($plugin) { + $form['summary']['options'][$id] = array( + '#prefix' => '<div id="edit-options-summary-options-' . $id . '-wrapper">', + '#suffix' => '</div>', + '#id' => 'edit-options-summary-options-' . $id, + '#type' => 'item', + '#input' => TRUE, // trick it into checking input to make #process run + '#dependency' => array( + 'radio:options[default_action]' => array('summary'), + 'radio:options[summary][format]' => array($id), + ), + '#dependency_count' => 2, + ); + $options[$id] = $info['title']; + $plugin->options_form($form['summary']['options'][$id], $form_state); + } + } + } + /** * Handle the default action, which means our argument wasn't present. * @@ -466,7 +649,7 @@ class views_handler_argument extends views_handler { * How to act if validation failes */ function validate_fail() { - $info = $this->default_actions($this->options['validate_fail']); + $info = $this->default_actions($this->options['validate']['fail']); return $this->default_action($info); } /** @@ -537,21 +720,22 @@ class views_handler_argument extends views_handler { * If an argument was expected and was not given, in this case, display * a summary query. */ - function default_summary($order, $by = NULL) { + function default_summary() { $this->view->build_info['summary'] = TRUE; $this->view->build_info['summary_level'] = $this->options['id']; // Change the display style to the summary style for this // argument. - $this->view->plugin_name = $this->options['style_plugin']; - $this->view->style_options = $this->options['style_options']; + $this->view->plugin_name = $this->options['summary']['format']; + $this->view->style_options = $this->options['summary_options']; // Clear out the normal primary field and whatever else may have // been added and let the summary do the work. $this->query->clear_fields(); $this->summary_query(); - $this->summary_sort($order, $by); + $by = $this->options['summary']['number_of_records'] ? 'num_records' : NULL; + $this->summary_sort($this->options['summary']['sort_order'], $by); // Summaries have their own sorting and fields, so tell the View not // to build these. @@ -591,7 +775,7 @@ class views_handler_argument extends views_handler { if (isset($this->name_table)) { // if the alias is different then we're probably added, not ensured, // so look up the join and add it instead. - if ($this->table_alias != $this->table) { + if ($this->table_alias != $this->name_table) { $j = views_get_table_join($this->name_table, $this->table); if ($j) { $join = clone $j; @@ -677,7 +861,7 @@ class views_handler_argument extends views_handler { * * The argument sent may be found at $this->argument. */ - function query() { + function query($group_by = FALSE) { $this->ensure_my_table(); $this->query->add_where(0, "$this->table_alias.$this->real_field", $this->argument); } @@ -714,11 +898,11 @@ class views_handler_argument extends views_handler { return $this->argument_validated; } - if ($this->is_wildcard($arg)) { + if ($this->is_exception($arg)) { return $this->argument_validated = TRUE; } - if ($this->options['validate_type'] == 'none') { + if ($this->options['validate']['type'] == 'none') { return $this->argument_validated = $this->validate_argument_basic($arg); } @@ -739,7 +923,7 @@ class views_handler_argument extends views_handler { * then validation cannot actually fail. */ function validate_argument($arg) { - $validate_info = $this->default_actions($this->options['validate_fail']); + $validate_info = $this->default_actions($this->options['validate']['fail']); if (empty($validate_info['hard fail'])) { return TRUE; } @@ -748,7 +932,7 @@ class views_handler_argument extends views_handler { // If the validator has changed the validate fail condition to a // soft fail, deal with that: - $validate_info = $this->default_actions($this->options['validate_fail']); + $validate_info = $this->default_actions($this->options['validate']['fail']); if (empty($validate_info['hard fail'])) { return TRUE; } @@ -788,7 +972,7 @@ class views_handler_argument extends views_handler { /** * Get the value of this argument. */ - function get_value() { + function get_value($values, $field = NULL) { // If we already processed this argument, we're done. if (isset($this->argument)) { return $this->argument; @@ -813,6 +997,9 @@ class views_handler_argument extends views_handler { $argument = clone $this; if (!isset($arg) && $argument->has_default_argument()) { $arg = $argument->get_default_argument(); + + // remember that this argument was computed, not passed on the URL. + $this->is_default = TRUE; } // Set the argument, which will also validate that the argument can be set. if ($argument->set_argument($arg)) { @@ -823,34 +1010,58 @@ class views_handler_argument extends views_handler { } /** - * Special handling for the style export. + * Export handler for summary export. * * Arguments can have styles for the summary view. This special export * handler makes sure this works properly. */ - function export_style($indent, $prefix, $storage, $option, $definition, $parents) { + function export_summary($indent, $prefix, $storage, $option, $definition, $parents) { $output = ''; - $name = $storage[$option]; - $options = $storage['style_options']; + $name = $this->options['summary'][$option]; + $options = $this->options['summary_options']; $plugin = views_get_plugin('style', $name); if ($plugin) { $plugin->init($this->view, $this->display, $options); // Write which plugin to use. - $output .= $indent . $prefix . "['$option'] = '$name';\n"; + $output .= $indent . $prefix . "['summary']['$option'] = '$name';\n"; // Pass off to the plugin to export itself. - $output .= $plugin->export_options($indent, $prefix . "['style_options']"); + $output .= $plugin->export_options($indent, $prefix . "['summary_options']"); } return $output; } /** - * Special handling for the style export. + * Export handler for validation export. * - * Arguments can have styles for the summary view. This special export - * handler makes sure this works properly. + * Arguments use validation plugins. This special export handler makes sure + * this works properly. + */ + function export_validation($indent, $prefix, $storage, $option, $definition, $parents) { + $output = ''; + $name = $this->options['validate'][$option]; + $options = $this->options['validate_options']; + + $plugin = views_get_plugin('argument validator', $name); + if ($plugin) { + $plugin->init($this->view, $this->display, $options); + // Write which plugin to use. + $output .= $indent . $prefix . "['validate']['$option'] = '$name';\n"; + + // Pass off to the plugin to export itself. + $output .= $plugin->export_options($indent, $prefix . "['validate_options']"); + } + + return $output; + } + + /** + * Generic plugin export handler. + * + * Since style and validation plugins have their own export handlers, this + * one is currently only used for default argument plugins. */ function export_plugin($indent, $prefix, $storage, $option, $definition, $parents) { $output = ''; @@ -858,10 +1069,7 @@ class views_handler_argument extends views_handler { $type = 'argument default'; $option_name = 'default_argument_options'; } - else { - $type = 'argument validator'; - $option_name = 'validate_options'; - } + $plugin = $this->get_plugin($type); $name = $this->options[$option]; @@ -883,21 +1091,25 @@ class views_handler_argument extends views_handler { $options = array(); switch ($type) { case 'argument default': - $plugin_name = 'default_argument_type'; + $plugin_name = $this->options['default_argument_type']; $options_name = 'default_argument_options'; break; case 'argument validator': - $plugin_name = 'validate_type'; + $plugin_name = $this->options['validate']['type']; $options_name = 'validate_options'; + break; + case 'style': + $plugin_name = $this->options['summary']['format']; + $options_name = 'summary_options'; } if (!$name) { - $name = $this->options[$plugin_name]; + $name = $plugin_name; } // we only fetch the options if we're fetching the plugin actually // in use. - if ($name == $this->options[$plugin_name]) { + if ($name == $plugin_name) { $options = $this->options[$options_name]; } @@ -907,6 +1119,16 @@ class views_handler_argument extends views_handler { return $plugin; } } + + /** + * Return a description of how the argument would normally be sorted. + * + * Subclasses should override this to specify what the default sort order of + * their argument is (e.g. alphabetical, numeric, date). + */ + function get_sort_name() { + return t('Default sort', array(), array('context' => 'Sort order')); + } } /** @@ -920,7 +1142,7 @@ class views_handler_argument_broken extends views_handler_argument { } function ensure_my_table() { /* No table to ensure! */ } - function query() { /* No query to run */ } + function query($group_by = FALSE) { /* No query to run */ } function options_form(&$form, &$form_state) { $form['markup'] = array( '#markup' => '<div class="form-item description">' . t('The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.') . '</div>', diff --git a/sites/all/modules/views/handlers/views_handler_argument_date.inc b/sites/all/modules/views/handlers/views_handler_argument_date.inc index d987c65e8af3ec1b39e6e6107287e9fe512657fe..fa6dc8b9fc4ebb32024af0ac2a1279e4135bee01 100644 --- a/sites/all/modules/views/handlers/views_handler_argument_date.inc +++ b/sites/all/modules/views/handlers/views_handler_argument_date.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_date.inc,v 1.3.6.3 2010/03/11 08:30:24 dereine Exp $ /** * Abstract argument handler for dates. * @@ -62,6 +61,9 @@ class views_handler_argument_date extends views_handler_argument_formula { } return parent::get_default_argument($raw); + } + function get_sort_name() { + return t('Date', array(), array('context' => 'Sort order')); } } diff --git a/sites/all/modules/views/handlers/views_handler_argument_formula.inc b/sites/all/modules/views/handlers/views_handler_argument_formula.inc index 18960f90adf44c2abdf08fb022be85e7d276caba..c4287be7f1f75024802202910b47b72f06c7650b 100644 --- a/sites/all/modules/views/handlers/views_handler_argument_formula.inc +++ b/sites/all/modules/views/handlers/views_handler_argument_formula.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_formula.inc,v 1.1.6.3 2011/01/03 17:46:33 dereine Exp $ /** * Abstract argument handler for simple formulae. * @@ -45,7 +44,7 @@ class views_handler_argument_formula extends views_handler_argument { /** * Build the query based upon the formula */ - function query() { + function query($group_by = FALSE) { $this->ensure_my_table(); // Now that our table is secure, get our formula. $placeholder = $this->placeholder(); 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 c5a7da6c5cc1fe33913c37063bd9dbc5c09c5bf8..d44af12454748fee7874a9af027e837e46fdd8a8 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_group_by_numeric.inc,v 1.1.4.2 2010/01/24 22:37:52 dereine Exp $ /** * Simple handler for arguments using group by. @@ -12,7 +11,11 @@ class views_handler_argument_group_by_numeric extends views_handler_argument { $this->query->add_having(0, $field, $this->argument); } - function ui_name() { - return $this->get_field(parent::ui_name()); + function ui_name($short = FALSE) { + return $this->get_field(parent::ui_name($short)); + } + + function get_sort_name() { + return t('Numerical', array(), array('context' => 'Sort order')); } } diff --git a/sites/all/modules/views/handlers/views_handler_argument_many_to_one.inc b/sites/all/modules/views/handlers/views_handler_argument_many_to_one.inc index e2346c4f378deb8fadd0c5f45124f1aa7ebe1c6f..c07bbb84a7d4ab39b2c1754839f7a86c0d3cf5f1 100644 --- a/sites/all/modules/views/handlers/views_handler_argument_many_to_one.inc +++ b/sites/all/modules/views/handlers/views_handler_argument_many_to_one.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_many_to_one.inc,v 1.1.6.3 2010/03/22 20:40:31 merlinofchaos Exp $ /** * An argument handler for use in fields that have a many to one relationship * with the table(s) to the left. This adds a bunch of options that are @@ -8,7 +7,7 @@ * - numeric: If true, the field will be considered numeric. Probably should * always be set TRUE as views_handler_argument_string has many to one * capabilities. - * - zero is null: If true, a 0 will be handled as empty, so for example + * - zero is null: If true, a 0 will be handled as empty, so for example * a default argument can be provided or a summary can be shown. * * @ingroup views_argument_handlers @@ -44,23 +43,26 @@ class views_handler_argument_many_to_one extends views_handler_argument { if (!empty($this->definition['numeric'])) { $form['break_phrase'] = array( '#type' => 'checkbox', - '#title' => t('Allow multiple terms per argument.'), - '#description' => t('If selected, users can enter multiple arguments in the form of 1+2+3 (for OR) or 1,2,3 (for AND).'), + '#title' => t('Allow multiple values.'), + '#description' => t('If selected, users can enter multiple values in the form of 1+2+3 (for OR) or 1,2,3 (for AND).'), '#default_value' => !empty($this->options['break_phrase']), + '#fieldset' => 'more', ); } $form['add_table'] = array( '#type' => 'checkbox', - '#title' => t('Allow multiple arguments to work together.'), - '#description' => t('If selected, multiple instances of this argument can work together, as though multiple terms were supplied to the same argument. This setting is not compatible with the "Reduce duplicates" setting.'), + '#title' => t('Allow multiple filter values to work together.'), + '#description' => t('If selected, multiple instances of this filter can work together, as though multiple values were supplied to the same filter. This setting is not compatible with the "Reduce duplicates" setting.'), '#default_value' => !empty($this->options['add_table']), + '#fieldset' => 'more', ); $form['require_value'] = array( '#type' => 'checkbox', '#title' => t('Do not display items with no value in summary'), '#default_value' => !empty($this->options['require_value']), + '#fieldset' => 'more', ); $this->helper->options_form($form, $form_state); @@ -74,7 +76,7 @@ class views_handler_argument_many_to_one extends views_handler_argument { $this->helper->ensure_my_table(); } - function query() { + function query($group_by = FALSE) { $empty = FALSE; if (isset($this->definition['zero is null']) && $this->definition['zero is null']) { if (empty($this->argument)) { @@ -168,4 +170,3 @@ class views_handler_argument_many_to_one extends views_handler_argument { return $this->value; } } - 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 884e5578cabccd39ede4903707f6f27ba9893c7c..5914031130c624024761051d769010568e56a7e7 100644 --- a/sites/all/modules/views/handlers/views_handler_argument_null.inc +++ b/sites/all/modules/views/handlers/views_handler_argument_null.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_null.inc,v 1.1 2008/09/03 19:21:28 merlinofchaos Exp $ /** * Argument handler that ignores the argument. */ @@ -21,10 +20,10 @@ class views_handler_argument_null extends views_handler_argument { '#title' => t('Fail basic validation if any argument is given'), '#default_value' => !empty($this->options['must_not_be']), '#description' => t('By checking this field, you can use this to make sure views with more arguments than necessary fail validation.'), + '#fieldset' => 'more', ); - unset($form['wildcard']); - unset($form['wildcard_substitution']); + unset($form['exception']); } /** @@ -56,5 +55,5 @@ class views_handler_argument_null extends views_handler_argument { * Override the behavior of query() to prevent the query * from being changed in any way. */ - function query() {} + function query($group_by = FALSE) {} } 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 6d5d7851c5007379598d85eafd520ea65b11e778..ba7ba4babeb158aceec5a524b7ddffc01553e415 100644 --- a/sites/all/modules/views/handlers/views_handler_argument_numeric.inc +++ b/sites/all/modules/views/handlers/views_handler_argument_numeric.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_numeric.inc,v 1.1.6.1 2009/11/02 22:01:25 merlinofchaos Exp $ /** * @file * Contains the numeric argument handler. @@ -27,16 +26,18 @@ class views_handler_argument_numeric extends views_handler_argument { // allow + for or, , for and $form['break_phrase'] = array( '#type' => 'checkbox', - '#title' => t('Allow multiple terms per argument.'), - '#description' => t('If selected, users can enter multiple arguments in the form of 1+2+3 or 1,2,3.'), + '#title' => t('Allow multiple values.'), + '#description' => t('If selected, users can enter multiple values in the form of 1+2+3 (for OR) or 1,2,3 (for AND).'), '#default_value' => !empty($this->options['break_phrase']), + '#fieldset' => 'more', ); $form['not'] = array( '#type' => 'checkbox', - '#title' => t('Exclude the argument'), - '#description' => t('If selected, the numbers entered in the argument will be excluded rather than limiting the view.'), + '#title' => t('Exclude'), + '#description' => t('If selected, the numbers entered for the filter will be excluded rather than limiting the view.'), '#default_value' => !empty($this->options['not']), + '#fieldset' => 'more', ); } @@ -71,7 +72,7 @@ class views_handler_argument_numeric extends views_handler_argument { return $this->value; } - function query() { + function query($group_by = FALSE) { $this->ensure_my_table(); if (!empty($this->options['break_phrase'])) { @@ -81,14 +82,20 @@ class views_handler_argument_numeric extends views_handler_argument { $this->value = array($this->argument); } + $placeholder = $this->placeholder(); + $null_check = empty($this->options['not']) ? '' : "OR $this->table_alias.$this->real_field IS NULL"; + if (count($this->value) > 1) { $operator = empty($this->options['not']) ? 'IN' : 'NOT IN'; - $placeholders = implode(', ', array_fill(0, sizeof($this->value), '%d')); - $this->query->add_where(0, "$this->table_alias.$this->real_field", $this->value, $operator); + $this->query->add_where_expression(0, "$this->table_alias.$this->real_field $operator($placeholder) $null_check", array($placeholder => $this->value)); } else { $operator = empty($this->options['not']) ? '=' : '!='; - $this->query->add_where(0, "$this->table_alias.$this->real_field", $this->argument, $operator); + $this->query->add_where_expression(0, "$this->table_alias.$this->real_field $operator $placeholder $null_check", array($placeholder => $this->argument)); } } + + function get_sort_name() { + return t('Numerical', array(), array('context' => 'Sort order')); + } } diff --git a/sites/all/modules/views/handlers/views_handler_argument_string.inc b/sites/all/modules/views/handlers/views_handler_argument_string.inc index ce95473ca35d767de822d55d60006ab49c314a02..a45ae4e39b4328b643608677359e9defb98f29c7 100644 --- a/sites/all/modules/views/handlers/views_handler_argument_string.inc +++ b/sites/all/modules/views/handlers/views_handler_argument_string.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_string.inc,v 1.5.4.7 2011/01/05 22:40:08 dereine Exp $ /** * Basic argument handler to implement string arguments that may have length @@ -27,6 +26,7 @@ class views_handler_argument_string extends views_handler_argument { $options['case'] = array('default' => 'none'); $options['path_case'] = array('default' => 'none'); $options['transform_dash'] = array('default' => FALSE); + $options['break_phrase'] = array('default' => FALSE); if (!empty($this->definition['many to one'])) { $options['add_table'] = array('default' => FALSE); @@ -42,23 +42,24 @@ class views_handler_argument_string extends views_handler_argument { $form['glossary'] = array( '#type' => 'checkbox', '#title' => t('Glossary mode'), - '#description' => t('Glossary mode applies a limit to the number of characters used in the argument, which allows the summary view to act as a glossary.'), + '#description' => t('Glossary mode applies a limit to the number of characters used in the filter value, which allows the summary view to act as a glossary.'), '#default_value' => $this->options['glossary'], + '#fieldset' => 'more', ); $form['limit'] = array( '#type' => 'textfield', '#title' => t('Character limit'), - '#description' => t('How many characters of the argument to filter against. If set to 1, all fields starting with the letter in the argument would be matched.'), + '#description' => t('How many characters of the filter value to filter against. If set to 1, all fields starting with the first letter in the filter value would be matched.'), '#default_value' => $this->options['limit'], - '#process' => array('ctools_dependent_process'), '#dependency' => array('edit-options-glossary' => array(TRUE)), + '#fieldset' => 'more', ); $form['case'] = array( '#type' => 'select', '#title' => t('Case'), - '#description' => t('When printing the argument result, how to transform the case.'), + '#description' => t('When printing the title and summary, how to transform the case of the filter value.'), '#options' => array( 'none' => t('No transform'), 'upper' => t('Upper case'), @@ -67,12 +68,13 @@ class views_handler_argument_string extends views_handler_argument { 'ucwords' => t('Capitalize each word'), ), '#default_value' => $this->options['case'], + '#fieldset' => 'more', ); $form['path_case'] = array( '#type' => 'select', '#title' => t('Case in path'), - '#description' => t('When printing url paths, how to transform the case of the argument. Do not use this unless with Postgres as it uses case sensitive comparisons.'), + '#description' => t('When printing url paths, how to transform the case of the filter value. Do not use this unless with Postgres as it uses case sensitive comparisons.'), '#options' => array( 'none' => t('No transform'), 'upper' => t('Upper case'), @@ -81,34 +83,48 @@ class views_handler_argument_string extends views_handler_argument { 'ucwords' => t('Capitalize each word'), ), '#default_value' => $this->options['path_case'], + '#fieldset' => 'more', ); $form['transform_dash'] = array( '#type' => 'checkbox', '#title' => t('Transform spaces to dashes in URL'), '#default_value' => $this->options['transform_dash'], + '#fieldset' => 'more', ); if (!empty($this->definition['many to one'])) { $form['add_table'] = array( '#type' => 'checkbox', - '#title' => t('Allow multiple arguments to work together.'), - '#description' => t('If selected, multiple instances of this argument can work together, as though multiple terms were supplied to the same argument. This setting is not compatible with the "Reduce duplicates" setting.'), + '#title' => t('Allow multiple filter values to work together.'), + '#description' => t('If selected, multiple instances of this filter can work together, as though multiple values were supplied to the same filter. This setting is not compatible with the "Reduce duplicates" setting.'), '#default_value' => !empty($this->options['add_table']), + '#fieldset' => 'more', ); $form['require_value'] = array( '#type' => 'checkbox', '#title' => t('Do not display items with no value in summary'), '#default_value' => !empty($this->options['require_value']), + '#fieldset' => 'more', ); } + + // allow + for or, , for and + $form['break_phrase'] = array( + '#type' => 'checkbox', + '#title' => t('Allow multiple values.'), + '#description' => t('If selected, users can enter multiple values in the form of 1+2+3 (for OR) or 1,2,3 (for AND).'), + '#default_value' => !empty($this->options['break_phrase']), + '#fieldset' => 'more', + ); } /** * Build the summary query based on a string */ function summary_query() { + $this->placeholder_length = $this->placeholder(); if (empty($this->definition['many to one'])) { $this->ensure_my_table(); } @@ -118,23 +134,23 @@ class views_handler_argument_string extends views_handler_argument { if (empty($this->options['glossary'])) { // Add the field. - $this->base_alias = $this->name_alias = $this->query->add_field($this->table_alias, $this->real_field); + $this->base_alias = $this->query->add_field($this->table_alias, $this->real_field); $this->query->set_count_field($this->table_alias, $this->real_field); } else { // Add the field. $formula = $this->get_formula(); - $placeholder_length = $this->placeholder_length; $params = array( 'placeholders' => array( - $placeholder_length => intval($this->options['limit']), + $this->placeholder_length => intval($this->options['limit']), ), ); - $this->base_alias = $this->name_alias = $this->query->add_field(NULL, $formula, $this->field . '_truncated', $params); + $this->base_alias = $this->query->add_field(NULL, $formula, $this->field . '_truncated', $params); $this->query->set_count_field(NULL, $formula, $this->field, $this->field . '_truncated'); } + $this->summary_name_field(); return $this->summary_basics(FALSE); } @@ -150,18 +166,25 @@ class views_handler_argument_string extends views_handler_argument { /** * Build the query based upon the formula */ - function query() { + function query($group_by = FALSE) { $argument = $this->argument; if (!empty($this->options['transform_dash'])) { $argument = strtr($argument, '-', ' '); } $this->placeholder_length = $this->placeholder(); + if (!empty($this->options['break_phrase'])) { + views_break_phrase_string($argument, $this); + } + else { + $this->value = array($argument); + $this->operator = 'or'; + } + if (!empty($this->definition['many to one'])) { if (!empty($this->options['glossary'])) { $this->helper->formula = TRUE; } - $this->value = array($argument); $this->helper->ensure_my_table(); $this->helper->placeholders = array($this->placeholder_length => intval($this->options['limit'])); @@ -179,10 +202,23 @@ class views_handler_argument_string extends views_handler_argument { $field = $this->get_formula(); } + if (count($this->value) > 1) { + $operator = 'IN'; + $argument = $this->value; + } + else { + $operator = '='; + } + if ($formula) { $placeholder = $this->placeholder(); $placeholder_length = $this->placeholder_length; - $field .= ' = ' . $placeholder; + if ($operator == 'IN') { + $field .= " IN($placeholder)"; + } + else { + $field .= ' = ' . $placeholder; + } $placeholders = array( $placeholder_length => intval($this->options['limit']), $placeholder => $argument, @@ -190,7 +226,7 @@ class views_handler_argument_string extends views_handler_argument { $this->query->add_where_expression(0, $field, $placeholders); } else { - $this->query->add_where(0, $field, $argument); + $this->query->add_where(0, $field, $argument, $operator); } } @@ -223,13 +259,40 @@ class views_handler_argument_string extends views_handler_argument { } } + function get_sort_name() { + return t('Alphabetical', array(), array('context' => 'Sort order')); + } + function title() { - $title = $this->case_transform($this->argument, 'case'); + $this->argument = $this->case_transform($this->argument, 'case'); if (!empty($this->options['transform_dash'])) { - $title = strtr($title, '-', ' '); + $this->argument = strtr($this->argument, '-', ' '); } - return check_plain($title); + if (!empty($this->options['break_phrase'])) { + views_break_phrase($this->argument, $this); + } + else { + $this->value = array($this->argument); + $this->operator = 'or'; + } + + if (empty($this->value)) { + return !empty($this->definition['empty field name']) ? $this->definition['empty field name'] : t('Uncategorized'); + } + + if ($this->value === array(-1)) { + return !empty($this->definition['invalid input']) ? $this->definition['invalid input'] : t('Invalid input'); + } + + return implode($this->operator == 'or' ? ' + ' : ', ', $this->title_query()); + } + + /** + * Override for specific title lookups. + */ + function title_query() { + return drupal_map_assoc($this->value, 'check_plain'); } function summary_name($data) { @@ -237,4 +300,3 @@ class views_handler_argument_string extends views_handler_argument { } } - diff --git a/sites/all/modules/views/handlers/views_handler_field.inc b/sites/all/modules/views/handlers/views_handler_field.inc index f514d94dbc74780b5bb4db7072e6cad538b5d85c..bae45fc9a324c9fc4aebd52cad3d5cfa64fe2e79 100644 --- a/sites/all/modules/views/handlers/views_handler_field.inc +++ b/sites/all/modules/views/handlers/views_handler_field.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field.inc,v 1.33.4.44 2010/12/23 22:38:54 dereine Exp $ /** * @defgroup views_field_handlers Views' field handlers * @{ @@ -215,21 +214,26 @@ class views_handler_field extends views_handler { * rare occurence. */ function get_elements() { - return array( - '' => t('- Use default -'), - '0' => t('- None -'), - 'div' => t('DIV'), - 'span' => t('SPAN'), - 'h1' => t('H1'), - 'h2' => t('H2'), - 'h3' => t('H3'), - 'h4' => t('H4'), - 'h5' => t('H5'), - 'h6' => t('H6'), - 'p' => t('P'), - 'strong' => t('STRONG'), - 'em' => t('EM'), - ); + static $elements = NULL; + if (!isset($elements)) { + $elements = variable_get('views_field_rewrite_elements', array( + '' => t('- Use default -'), + '0' => t('- None -'), + 'div' => t('DIV'), + 'span' => t('SPAN'), + 'h1' => t('H1'), + 'h2' => t('H2'), + 'h3' => t('H3'), + 'h4' => t('H4'), + 'h5' => t('H5'), + 'h6' => t('H6'), + 'p' => t('P'), + 'strong' => t('STRONG'), + 'em' => t('EM'), + )); + } + + return $elements; } /** @@ -279,7 +283,11 @@ class views_handler_field extends views_handler { * Return the class of the field's wrapper. */ function element_wrapper_classes() { - return drupal_clean_css_identifier($this->options['element_wrapper_class']); + $classes = explode(' ', $this->options['element_wrapper_class']); + foreach ($classes as $key => $class) { + $classes[$key] = drupal_clean_css_identifier($class); + } + return implode(' ', $classes); } function option_definition() { @@ -294,6 +302,8 @@ class views_handler_field extends views_handler { 'make_link' => array('default' => FALSE), 'path' => array('default' => '', 'translatable' => TRUE), 'absolute' => array('default' => '', 'translatable' => FALSE), + 'external' => array('default' => '', 'translatable' => FALSE), + 'replace_spaces' => array('default' => '', 'translatable' => FALSE), 'alt' => array('default' => '', 'translatable' => TRUE), 'rel' => array('default' => ''), 'link_class' => array('default' => ''), @@ -301,6 +311,7 @@ class views_handler_field extends views_handler { 'suffix' => array('default' => '', 'translatable' => TRUE), 'target' => array('default' => '', 'translatable' => TRUE), 'trim' => array('default' => FALSE), + 'nl2br' => array('default' => FALSE), 'max_length' => array('default' => ''), 'word_boundary' => array('default' => TRUE), 'ellipsis' => array('default' => TRUE), @@ -328,6 +339,27 @@ class views_handler_field extends views_handler { return $options; } + /** + * Performs some cleanup tasks on the options array before saving it. + */ + function options_submit(&$form, &$form_state) { + $options = &$form_state['values']['options']; + $types = array('element_type', 'element_label_type', 'element_wrapper_type'); + $classes = array_combine(array('element_class', 'element_label_class', 'element_wrapper_class'), $types); + + foreach ($types as $type) { + if (!$options[$type . '_enable']) { + $options[$type] = ''; + } + } + + foreach ($classes as $class => $type) { + if (!$options[$class . '_enable'] || !$options[$type . '_enable']) { + $options[$class] = ''; + } + } + } + /** * Default options form that provides the label widget that all fields * should have. @@ -335,75 +367,160 @@ class views_handler_field extends views_handler { function options_form(&$form, &$form_state) { parent::options_form($form, $form_state); - // Use prefix and suffix to fake a fieldset because we use #tree. - $form['style_prefix'] = array( - '#value' => '<fieldset id="views-validator-options"><legend>' . t('Style settings') . '</legend>', + $label = $this->label(); + $form['custom_label'] = array( + '#type' => 'checkbox', + '#title' => t('Create a label'), + '#description' => t('Enable to create a label for this field.'), + '#default_value' => $label !== '', + '#weight' => -103, + ); + $form['label'] = array( + '#type' => 'textfield', + '#title' => t('Label'), + '#default_value' => $label, + '#dependency' => array( + 'edit-options-custom-label' => array(1), + ), + '#weight' => -102, + ); + $form['element_label_colon'] = array( + '#type' => 'checkbox', + '#title' => t('Place a colon after the label'), + '#default_value' => $this->options['element_label_colon'], + '#dependency' => array( + 'edit-options-custom-label' => array(1), + ), + '#weight' => -101, ); $form['exclude'] = array( '#type' => 'checkbox', '#title' => t('Exclude from display'), '#default_value' => $this->options['exclude'], - '#description' => t('Check this box to not display this field, but still load it in the view. Use this option to not show a grouping field in each record, or when doing advanced theming, or when you want to use this field as a token in other fields.'), + '#description' => t('Enable to load this field as hidden. Often used to group fields, or to use as token in another field.'), + '#weight' => -100, + ); + + $form['style_settings'] = array( + '#type' => 'fieldset', + '#title' => t('Style settings'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#weight' => 99, ); + $form['element_type_enable'] = array( + '#type' => 'checkbox', + '#title' => t('Wrap field in HTML'), + '#default_value' => !empty($this->options['element_type']) || (string) $this->options['element_type'] == '0' || !empty($this->options['element_class']) || (string) $this->options['element_class'] == '0', + '#fieldset' => 'style_settings', + ); $form['element_type'] = array( '#title' => t('HTML element'), '#options' => $this->get_elements(), '#type' => 'select', '#default_value' => $this->options['element_type'], - '#description' => t('Most styles provide wrappers for fields. If the chosen style supports wrappers, wrap the field in this HTML element. The default will usually be either DIV or SPAN.'), + '#description' => t('Choose the HTML element to wrap around this field, e.g. H1, H2, etc.'), + '#dependency' => array( + 'edit-options-element-type-enable' => array(1), + ), + '#fieldset' => 'style_settings', ); + $form['element_class_enable'] = array( + '#type' => 'checkbox', + '#title' => t('Create a CSS class'), + '#dependency' => array( + 'edit-options-element-type-enable' => array(1), + ), + '#default_value' => !empty($this->options['element_class']) || (string) $this->options['element_class'] == '0', + '#fieldset' => 'style_settings', + ); $form['element_class'] = array( - '#title' => t('Element class'), - '#description' => t('The class to provide on the wrapper element. You may enter data from this view as per the "Replacement patterns" used in "Rewrite the output of this field".'), + '#title' => t('CSS class'), + '#description' => t('Provide a CSS class to...'), '#type' => 'textfield', '#default_value' => $this->options['element_class'], + '#dependency' => array( + 'edit-options-element-class-enable' => array(1), + ), + '#fieldset' => 'style_settings', ); - $form['label'] = array( - '#type' => 'textfield', - '#title' => t('Label'), - '#default_value' => isset($this->options['label']) ? $this->options['label'] : '', - '#description' => t('The label for this field that will be displayed to end users if the style requires it.'), + $form['element_label_type_enable'] = array( + '#type' => 'checkbox', + '#title' => t('Wrap label in HTML'), + '#default_value' => !empty($this->options['element_label_type']) || (string) $this->options['element_label_type'] == '0' || !empty($this->options['element_label_class']) || (string) $this->options['element_label_class'] == '0', + '#fieldset' => 'style_settings', ); - $form['element_label_type'] = array( '#title' => t('Label HTML element'), '#options' => $this->get_elements(FALSE), '#type' => 'select', '#default_value' => $this->options['element_label_type'], - '#description' => t('What HTML Element type to use to wrap the label.'), + '#description' => t('Choose the HTML element to wrap around this label, e.g. H1, H2, etc.'), + '#dependency' => array( + 'edit-options-element-label-type-enable' => array(1), + ), + '#fieldset' => 'style_settings', + ); + $form['element_label_class_enable'] = array( + '#type' => 'checkbox', + '#title' => t('Create a CSS class'), + '#dependency' => array( + 'edit-options-element-label-type-enable' => array(1) + ), + '#default_value' => !empty($this->options['element_label_class']) || (string) $this->options['element_label_class'] == '0', + '#fieldset' => 'style_settings', ); - $form['element_label_class'] = array( - '#title' => t('Label class'), - '#description' => t('The class to provide on the label wrapper element.'), + '#title' => t('CSS class'), + '#description' => t('Provide a CSS class to...'), '#type' => 'textfield', '#default_value' => $this->options['element_label_class'], + '#dependency' => array( + 'edit-options-element-label-class-enable' => array(1), + ), + '#fieldset' => 'style_settings', ); - $form['element_label_colon'] = array( + $form['element_wrapper_type_enable'] = array( '#type' => 'checkbox', - '#title' => t('Place a colon after the label'), - '#default_value' => $this->options['element_label_colon'], - '#description' => t('If the label is to be inline with the value, place a colon between them. Not valid for styles such as table where the label is not placed with the value.'), + '#title' => t('Wrap field and label in HTML'), + '#default_value' => !empty($this->options['element_wrapper_type']) || (string) $this->options['element_wrapper_type'] == '0' || !empty($this->options['element_wrapper_class']) || (string) $this->options['element_wrapper_class'] == '0', + '#fieldset' => 'style_settings', ); - $form['element_wrapper_type'] = array( '#title' => t('Wrapper HTML element'), '#options' => $this->get_elements(FALSE), '#type' => 'select', '#default_value' => $this->options['element_wrapper_type'], - '#description' => t('What HTML Element type to use to wrap the field (and the label). This is not supported by some styles such as tables.'), + '#description' => t('Choose the HTML element to wrap around this field and label, e.g. H1, H2, etc.'), + '#dependency' => array( + 'edit-options-element-wrapper-type-enable' => array(1), + ), + '#fieldset' => 'style_settings', ); + $form['element_wrapper_class_enable'] = array( + '#type' => 'checkbox', + '#title' => t('Create a CSS class'), + '#dependency' => array( + 'edit-options-element-wrapper-type-enable' => array(1), + ), + '#default_value' => !empty($this->options['element_wrapper_class']) || (string) $this->options['element_wrapper_class'] == '0', + '#fieldset' => 'style_settings', + ); $form['element_wrapper_class'] = array( - '#title' => t('Wrapper class'), - '#description' => t('The class to provide on the wrapper element.'), + '#title' => t('CSS class'), + '#description' => t('Provide a CSS class to...'), '#type' => 'textfield', '#default_value' => $this->options['element_wrapper_class'], + '#dependency' => array( + 'edit-options-element-wrapper-class-enable' => array(1), + ), + '#fieldset' => 'style_settings', ); $form['element_default_classes'] = array( @@ -411,15 +528,15 @@ class views_handler_field extends views_handler { '#title' => t('Add default classes'), '#default_value' => $this->options['element_default_classes'], '#description' => t('Use default Views classes to identify the field, field label and field content.'), - ); - - $form['style_suffix'] = array( - '#value' => '</fieldset>', + '#fieldset' => 'style_settings', ); $form['alter'] = array( - '#title' => t('Rewriting'), + '#title' => t('Rewrite results'), '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#weight' => 100, ); if ($this->allow_advanced_render()) { @@ -427,7 +544,7 @@ class views_handler_field extends views_handler { $form['alter']['alter_text'] = array( '#type' => 'checkbox', '#title' => t('Rewrite the output of this field'), - '#description' => t('If checked, you can alter the output of this field by specifying a string of text with replacement tokens that can use any existing field output.'), + '#description' => t('Enable to override the output of this field with custom text or replacement tokens.'), '#default_value' => $this->options['alter']['alter_text'], ); @@ -436,9 +553,8 @@ class views_handler_field extends views_handler { '#type' => 'textarea', '#default_value' => $this->options['alter']['text'], '#description' => t('The text to display for this field. You may include HTML. You may enter data from this view as per the "Replacement patterns" below.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array( - 'edit-options-alter-alter-text' => array(1) + 'edit-options-alter-alter-text' => array(1), ), ); @@ -453,30 +569,44 @@ class views_handler_field extends views_handler { '#type' => 'textfield', '#default_value' => $this->options['alter']['path'], '#description' => t('The Drupal path or absolute URL for this link. You may enter data from this view as per the "Replacement patterns" below.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array( - 'edit-options-alter-make-link' => array(1) + 'edit-options-alter-make-link' => array(1), ), '#maxlength' => 255, ); - $form['alter']['absolute'] = array( - '#type' => 'checkbox', - '#title' => t('Use absolute path'), - '#default_value' => $this->options['alter']['absolute'], - '#process' => array('form_process_checkbox', 'ctools_dependent_process'), - '#dependency' => array( - 'edit-options-alter-make-link' => array(1) - ), - ); + $form['alter']['absolute'] = array( + '#type' => 'checkbox', + '#title' => t('Use absolute path'), + '#default_value' => $this->options['alter']['absolute'], + '#dependency' => array( + 'edit-options-alter-make-link' => array(1), + ), + ); + $form['alter']['replace_spaces'] = array( + '#type' => 'checkbox', + '#title' => t('Replace spaces with dashes'), + '#default_value' => $this->options['alter']['replace_spaces'], + '#dependency' => array( + 'edit-options-alter-make-link' => array(1) + ), + ); + $form['alter']['external'] = array( + '#type' => 'checkbox', + '#title' => t('External server URL'), + '#default_value' => $this->options['alter']['external'], + '#description' => t("Links to an external server using a full URL: e.g. 'http://www.example.com' or 'www.example.com'."), + '#dependency' => array( + 'edit-options-alter-make-link' => array(1), + ), + ); $form['alter']['link_class'] = array( '#title' => t('Link class'), '#type' => 'textfield', '#default_value' => $this->options['alter']['link_class'], '#description' => t('The CSS class to apply to the link.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array( - 'edit-options-alter-make-link' => array(1) + 'edit-options-alter-make-link' => array(1), ), ); $form['alter']['alt'] = array( @@ -484,9 +614,8 @@ class views_handler_field extends views_handler { '#type' => 'textfield', '#default_value' => $this->options['alter']['alt'], '#description' => t('Text to place as "alt" text which most browsers display as a tooltip when hovering over the link.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array( - 'edit-options-alter-make-link' => array(1) + 'edit-options-alter-make-link' => array(1), ), ); $form['alter']['rel'] = array( @@ -494,9 +623,8 @@ class views_handler_field extends views_handler { '#type' => 'textfield', '#default_value' => $this->options['alter']['rel'], '#description' => t('Include Rel attribute for use in lightbox2 or other javascript utility.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array( - 'edit-options-alter-make-link' => array(1) + 'edit-options-alter-make-link' => array(1), ), ); $form['alter']['prefix'] = array( @@ -504,9 +632,8 @@ class views_handler_field extends views_handler { '#type' => 'textfield', '#default_value' => $this->options['alter']['prefix'], '#description' => t('Any text to display before this link. You may include HTML.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array( - 'edit-options-alter-make-link' => array(1) + 'edit-options-alter-make-link' => array(1), ), ); $form['alter']['suffix'] = array( @@ -514,9 +641,8 @@ class views_handler_field extends views_handler { '#type' => 'textfield', '#default_value' => $this->options['alter']['suffix'], '#description' => t('Any text to display after this link. You may include HTML.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array( - 'edit-options-alter-make-link' => array(1) + 'edit-options-alter-make-link' => array(1), ), ); $form['alter']['target'] = array( @@ -524,9 +650,8 @@ class views_handler_field extends views_handler { '#type' => 'textfield', '#default_value' => $this->options['alter']['target'], '#description' => t("Target of the link, such as _blank, _parent or an iframe's name. This field is rarely used."), - '#process' => array('ctools_dependent_process'), '#dependency' => array( - 'edit-options-alter-make-link' => array(1) + 'edit-options-alter-make-link' => array(1), ), ); @@ -576,7 +701,6 @@ If you would like to have the characters %5B and %5D please use the html entity '#type' => 'hidden', '#id' => 'views-tokens-help', '#prefix' => '<div><fieldset id="views-tokens-help"><legend>' . t('Replacement patterns') . '</legend>' . $output . '</fieldset></div>', - '#process' => array('ctools_dependent_process'), '#dependency' => array( 'edit-options-alter-make-link' => array(1), 'edit-options-alter-alter-text' => array(1), @@ -586,7 +710,7 @@ If you would like to have the characters %5B and %5D please use the html entity $form['alter']['trim'] = array( '#type' => 'checkbox', '#title' => t('Trim this field to a maximum length'), - '#description' => t('If checked, this field be trimmed to a maximum length in characters.'), + '#description' => t('Enable to trim the field to a maximum length of characters'), '#default_value' => $this->options['alter']['trim'], ); @@ -595,9 +719,8 @@ If you would like to have the characters %5B and %5D please use the html entity '#type' => 'textfield', '#default_value' => $this->options['alter']['max_length'], '#description' => t('The maximum number of characters this field can be.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array( - 'edit-options-alter-trim' => array(1) + 'edit-options-alter-trim' => array(1), ), ); @@ -606,9 +729,8 @@ If you would like to have the characters %5B and %5D please use the html entity '#title' => t('Trim only on a word boundary'), '#description' => t('If checked, this field be trimmed only on a word boundary. This is guaranteed to be the maximum characters stated or less. If there are no word boundaries this could trim a field to nothing.'), '#default_value' => $this->options['alter']['word_boundary'], - '#process' => array('form_process_checkbox', 'ctools_dependent_process'), '#dependency' => array( - 'edit-options-alter-trim' => array(1) + 'edit-options-alter-trim' => array(1), ), ); @@ -617,9 +739,8 @@ If you would like to have the characters %5B and %5D please use the html entity '#title' => t('Add an ellipsis'), '#description' => t('If checked, a "..." will be added if a field was trimmed.'), '#default_value' => $this->options['alter']['ellipsis'], - '#process' => array('form_process_checkbox', 'ctools_dependent_process'), '#dependency' => array( - 'edit-options-alter-trim' => array(1) + 'edit-options-alter-trim' => array(1), ), ); @@ -628,9 +749,8 @@ If you would like to have the characters %5B and %5D please use the html entity '#title' => t('Field can contain HTML'), '#description' => t('If checked, HTML corrector will be run to ensure tags are properly closed after trimming.'), '#default_value' => $this->options['alter']['html'], - '#process' => array('form_process_checkbox', 'ctools_dependent_process'), '#dependency' => array( - 'edit-options-alter-trim' => array(1) + 'edit-options-alter-trim' => array(1), ), ); @@ -639,7 +759,6 @@ If you would like to have the characters %5B and %5D please use the html entity '#title' => t('Strip HTML tags'), '#description' => t('If checked, all HTML tags will be stripped.'), '#default_value' => $this->options['alter']['strip_tags'], - '#process' => array('form_process_checkbox', 'ctools_dependent_process'), ); $form['alter']['preserve_tags'] = array( '#type' => 'textfield', @@ -649,40 +768,47 @@ If you would like to have the characters %5B and %5D please use the html entity '#dependency' => array( 'edit-options-alter-strip-tags' => array(1), ), - '#process' => array('ctools_dependent_process'), + ); + + $form['alter']['nl2br'] = array( + '#type' => 'checkbox', + '#title' => t('Convert newlines to HTML <br> tags'), + '#description' => t('If checked, all newlines chars (e.g. \n) are converted into HTML <br> tags.'), + '#default_value' => $this->options['alter']['nl2br'], ); } - // Use prefix and suffix to fake a fieldset because we use #tree. - $form['empty_prefix'] = array( - '#value' => '<fieldset id="views-validator-options"><legend>' . t('Empty field behavior') . '</legend>', + $form['empty_field_behavior'] = array( + '#type' => 'fieldset', + '#title' => t('No results behavior'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#weight' => 100, ); $form['empty'] = array( '#type' => 'textfield', - '#title' => t('Empty text'), + '#title' => t('No results text'), '#default_value' => $this->options['empty'], - '#description' => t('If the field is empty, display this text instead.'), + '#description' => t('Provide text to display if this field returns no results.'), + '#fieldset' => 'empty_field_behavior', ); $form['empty_zero'] = array( '#type' => 'checkbox', '#title' => t('Count the number 0 as empty'), '#default_value' => $this->options['empty_zero'], - '#description' => t('If the field contains the number zero, display the empty text instead'), + '#description' => t('Enable to display the "no results text" if the field contains the number 0.'), + '#fieldset' => 'empty_field_behavior', ); $form['hide_empty'] = array( '#type' => 'checkbox', '#title' => t('Hide if empty'), '#default_value' => $this->options['hide_empty'], - '#description' => t('Do not display anything for this field if it is empty. Note that the field label may still be displayed. Check style or row style settings to hide labels for empty fields.'), - ); - - $form['empty_suffix'] = array( - '#value' => '</fieldset>', + '#description' => t('Enable to hide this field if it is empty. Note that the field label may still be displayed. Check style or row style settings to hide labels for empty fields.'), + '#fieldset' => 'empty_field_behavior', ); - } /** @@ -710,8 +836,8 @@ If you would like to have the characters %5B and %5D please use the html entity * The values retrieved from the database. */ function render($values) { - $value = $values->{$this->field_alias}; - return check_plain($value); + $value = $this->get_value($values); + return $this->sanitize_value($value); } /** @@ -790,6 +916,10 @@ If you would like to have the characters %5B and %5D please use the html entity $value = $this->render_trim_text($alter, $value); } + if (!empty($alter['nl2br'])) { + $value = nl2br($value); + } + if (!empty($alter['make_link']) && !empty($alter['path'])) { if (!isset($tokens)) { $tokens = $this->get_render_tokens($alter); @@ -850,16 +980,39 @@ If you would like to have the characters %5B and %5D please use the html entity // However, we need to preserve special characters like " that // were removed by check_plain(). $path = strip_tags(html_entity_decode(strtr($path, $tokens))); + + if (!empty($alter['replace_spaces'])) { + $path = str_replace(' ', '-', $path); + } + } + + // Parse the URL and move any query and fragment parameters out of the path. + $url = parse_url($path); + + // Seriously malformed URLs may return FALSE or empty arrays. + if (empty($url)) { + return $text; } // If the path is empty do not build a link around the given text and return // it as is. - if (empty($path)) { + // http://www.example.com URLs will not have a $url['path'], so check host as well. + if (empty($url['path']) && empty($url['host'])) { return $text; } - // Parse the URL and move any query and fragment parameters out of the path. - $url = parse_url($path); + // If no scheme is provided in the $path, assign the default 'http://'. + // This allows a url of 'www.example.com' to be converted to 'http://www.example.com'. + // Only do this on for external URLs. + if ($alter['external']){ + if (!isset($url['scheme'])) { + // There is no scheme, add the default 'http://' to the $path. + $path = "http://$path"; + // Reset the $url array to include the new scheme. + $url = parse_url($path); + } + } + if (isset($url['query'])) { $path = strtr($path, array('?' . $url['query'] => '')); $options['query'] = drupal_get_query_array($url['query']); @@ -893,6 +1046,16 @@ If you would like to have the characters %5B and %5D please use the html entity $options['attributes']['target'] = $target; } + // Allow the addition of arbitrary attributes to links. Additional attributes + // currently can only be altered in preprocessors and not within the UI. + if (isset($alter['link_attributes']) && is_array($alter['link_attributes'])) { + foreach ($alter['link_attributes'] as $key => $attribute) { + if (!isset($options['attributes'][$key])) { + $options['attributes'][$key] = strtr($attribute, $tokens); + } + } + } + // If the query and fragment were programatically assigned overwrite any // parsed values. if (isset($alter['query'])) { @@ -1044,7 +1207,7 @@ class views_handler_field_broken extends views_handler_field { } function ensure_my_table() { /* No table to ensure! */ } - function query() { /* No query to run */ } + function query($group_by = FALSE) { /* No query to run */ } function options_form(&$form, &$form_state) { $form['markup'] = array( '#markup' => '<div class="form-item description">' . t('The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.') . '</div>', @@ -1082,13 +1245,14 @@ class views_handler_field_file_size extends views_handler_field { } function render($values) { - if ($values->{$this->field_alias}) { + $value = $this->get_value($values); + if ($value) { switch ($this->options['file_size_display']) { case 'bytes': - return $values->{$this->field_alias}; + return $value; case 'formatted': default: - return format_size($values->{$this->field_alias}); + return format_size($value); } } else { @@ -1102,8 +1266,8 @@ class views_handler_field_file_size extends views_handler_field { */ class views_handler_field_xss extends views_handler_field { function render($values) { - $value = $values->{$this->field_alias}; - return filter_xss($value); + $value = $this->get_value($values); + return $this->sanitize_value($value, 'xss'); } } 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 ad2ee71045e236225cb63704dd7a0b70f03be85c..aec5243beb691eff321703b7a1e2d76f5dc1fa61 100644 --- a/sites/all/modules/views/handlers/views_handler_field_boolean.inc +++ b/sites/all/modules/views/handlers/views_handler_field_boolean.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_boolean.inc,v 1.3.4.3 2010/08/26 09:41:55 dereine Exp $ /** * A handler to provide proper displays for booleans. @@ -39,7 +38,6 @@ class views_handler_field_boolean extends views_handler_field { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); foreach ($this->formats as $key => $item) { $options[$key] = implode('/', $item); } @@ -56,10 +54,11 @@ class views_handler_field_boolean extends views_handler_field { '#description' => t('If checked, true will be displayed as false.'), '#default_value' => $this->options['not'], ); + parent::options_form($form, $form_state); } function render($values) { - $value = $values->{$this->field_alias}; + $value = $this->get_value($values); if (!empty($this->options['not'])) { $value = !$value; } 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 4bf4c2ad149db48c2d08e6c7ebe325088977d7e7..bd0db1d8aa18e471397ae4ca27ff65db821bdfa2 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,4 @@ <?php -// $Id: views_handler_field_counter.inc,v 1.3.4.4 2010/11/05 07:20:54 dereine Exp $ class views_handler_field_counter extends views_handler_field { function option_definition() { @@ -9,16 +8,15 @@ class views_handler_field_counter extends views_handler_field { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); - $form['counter_start'] = array( '#type' => 'textfield', '#title' => t('Starting value'), '#default_value' => $this->options['counter_start'], '#description' => t('Specify the number the counter should start at.'), - //'#process' => array('ctools_dependent_process'), '#size' => 2, ); + + parent::options_form($form, $form_state); } function query() { diff --git a/sites/all/modules/views/handlers/views_handler_field_custom.inc b/sites/all/modules/views/handlers/views_handler_field_custom.inc index 8b3a6419136f3a4f7ecdcdca990b99faeab98674..93925f4afd2f4ea5632889605264720f72cb754a 100644 --- a/sites/all/modules/views/handlers/views_handler_field_custom.inc +++ b/sites/all/modules/views/handlers/views_handler_field_custom.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_custom.inc,v 1.1.6.2 2010/11/05 07:20:54 dereine Exp $ /** * A handler to provide a field that is completely custom by the administrator. @@ -26,6 +25,9 @@ class views_handler_field_custom extends views_handler_field { unset($form['alter']['alter_text']); unset($form['alter']['text']['#dependency']); unset($form['alter']['text']['#process']); + unset($form['alter']['help']['#dependency']); + unset($form['alter']['help']['#process']); + $form['#pre_render'][] = 'views_handler_field_custom_pre_render_move_text'; } function render($values) { @@ -33,3 +35,15 @@ class views_handler_field_custom extends views_handler_field { return ''; } } + +/** + * Prerender function to move the textarea to the top. + */ +function views_handler_field_custom_pre_render_move_text($form) { + $form['text'] = $form['alter']['text']; + $form['help'] = $form['alter']['help']; + unset($form['alter']['text']); + unset($form['alter']['help']); + + return $form; +} \ No newline at end of file diff --git a/sites/all/modules/views/handlers/views_handler_field_date.inc b/sites/all/modules/views/handlers/views_handler_field_date.inc index c69289a1e999f39bf62199a6a83ef1f7630c5f86..30e52e62762ba2b1ae74af2ec3f9481e592840e5 100644 --- a/sites/all/modules/views/handlers/views_handler_field_date.inc +++ b/sites/all/modules/views/handlers/views_handler_field_date.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_date.inc,v 1.3.4.6 2010/12/23 22:34:37 dereine Exp $ /** * A handler to provide proper displays for dates. * @@ -16,19 +15,24 @@ class views_handler_field_date extends views_handler_field { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); + + $date_formats = array(); + $date_types = system_get_date_types(); + foreach ($date_types as $key => $value) { + $date_formats[$value['type']] = check_plain(t($value['title'] . ' format')) . ': ' . format_date(REQUEST_TIME, $value['type']); + } $form['date_format'] = array( '#type' => 'select', '#title' => t('Date format'), - '#options' => array( - 'small' => t('Short date format') . ' ' . format_date(REQUEST_TIME, 'small'), - 'medium' => t('Medium date format') . ' ' . format_date(REQUEST_TIME, 'medium'), - 'large' => t('Long date format') . ' ' . format_date(REQUEST_TIME, 'large'), + '#options' => $date_formats + array( 'custom' => t('Custom'), 'raw time ago' => t('Time ago'), 'time ago' => t('Time ago (with "ago" appended)'), - 'raw time span' => t('Time span (future dates start with - )'), + 'raw time hence' => t('Time hence'), + 'time hence' => t('Time hence (with "hence" appended)'), + 'raw time span' => t('Time span (future dates have "-" prepended)'), + 'inverse time span' => t('Time span (past dates have "-" prepended)'), 'time span' => t('Time span (with "ago/hence" appended)'), ), '#default_value' => isset($this->options['date_format']) ? $this->options['date_format'] : 'small', @@ -38,15 +42,16 @@ class views_handler_field_date extends views_handler_field { '#title' => t('Custom date format'), '#description' => t('If "Custom", see <a href="http://us.php.net/manual/en/function.date.php" target="_blank">the PHP docs</a> for date formats. If "Time ago" this is the the number of different units to display, which defaults to two.'), '#default_value' => isset($this->options['custom_date_format']) ? $this->options['custom_date_format'] : '', - '#process' => array('ctools_dependent_process'), - '#dependency' => array('edit-options-date-format' => array('custom', 'raw time ago', 'time ago', 'raw time span', 'time span')), + '#dependency' => array('edit-options-date-format' => array('custom', 'raw time ago', 'time ago', 'raw time span', 'time span', 'raw time span', 'inverse time span', 'time span')), ); + + parent::options_form($form, $form_state); } function render($values) { - $value = $values->{$this->field_alias}; + $value = $this->get_value($values); $format = $this->options['date_format']; - if (in_array($format, array('custom', 'raw time ago', 'time ago', 'raw time span', 'time span'))) { + if (in_array($format, array('custom', 'raw time ago', 'time ago', 'raw time span', 'time span', 'raw time span', 'inverse time span', 'time span'))) { $custom_format = $this->options['custom_date_format']; } @@ -57,8 +62,14 @@ class views_handler_field_date extends views_handler_field { return format_interval($time_diff, is_numeric($custom_format) ? $custom_format : 2); case 'time ago': return t('%time ago', array('%time' => format_interval($time_diff, is_numeric($custom_format) ? $custom_format : 2))); + case 'raw time hence': + return format_interval(-$time_diff, is_numeric($custom_format) ? $custom_format : 2); + case 'time hence': + return t('%time hence', array('%time' => format_interval(-$time_diff, is_numeric($custom_format) ? $custom_format : 2))); case 'raw time span': return ($time_diff < 0 ? '-' : '') . format_interval(abs($time_diff), is_numeric($custom_format) ? $custom_format : 2); + case 'inverse time span': + return ($time_diff > 0 ? '-' : '') . format_interval(abs($time_diff), is_numeric($custom_format) ? $custom_format : 2); case 'time span': return t(($time_diff < 0 ? '%time hence' : '%time ago'), array('%time' => format_interval(abs($time_diff), is_numeric($custom_format) ? $custom_format : 2))); case 'custom': diff --git a/sites/all/modules/views/handlers/views_handler_field_group_by_numeric.inc b/sites/all/modules/views/handlers/views_handler_field_group_by_numeric.inc index 3e2c211fac7723a0fcbc05e0f1b00d1b7d233a56..5f330954420ecdfde695a37ecc3a16b7b37e3ab7 100644 --- a/sites/all/modules/views/handlers/views_handler_field_group_by_numeric.inc +++ b/sites/all/modules/views/handlers/views_handler_field_group_by_numeric.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_group_by_numeric.inc,v 1.1.4.6 2010/11/07 11:36:59 dereine Exp $ /** * Handler for GROUP BY on simple numeric fields. diff --git a/sites/all/modules/views/handlers/views_handler_field_markup.inc b/sites/all/modules/views/handlers/views_handler_field_markup.inc index 09ad254425fff6f78e6ad9787c0784f62a30ec18..791f24f778c22073b151238191ad26323fe8a203 100644 --- a/sites/all/modules/views/handlers/views_handler_field_markup.inc +++ b/sites/all/modules/views/handlers/views_handler_field_markup.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_markup.inc,v 1.3.6.5 2010/12/16 18:23:42 dereine Exp $ /** * A handler to run a field through check_markup, using a companion @@ -28,8 +27,9 @@ class views_handler_field_markup extends views_handler_field { } function render($values) { - $value = $values->{$this->field_alias}; - $format = is_array($this->format) ? $values->{$this->aliases['format']} : $this->format; + $value = $this->get_value($values); + $format = $this->get_value($values, 'format'); + $format = is_numeric($this->format) ? $this->format : $format; if ($value) { $value = str_replace('<!--break-->', '', $value); return check_markup($value, $format, ''); diff --git a/sites/all/modules/views/handlers/views_handler_field_math.inc b/sites/all/modules/views/handlers/views_handler_field_math.inc index d5200c3d8d7c44ff2d60ca912aba9f2d0b1de631..ffb044aa9e9dcde79fb7ad372324ec60bed244c8 100644 --- a/sites/all/modules/views/handlers/views_handler_field_math.inc +++ b/sites/all/modules/views/handlers/views_handler_field_math.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_math.inc,v 1.1.2.3 2010/11/05 07:20:54 dereine Exp $ /** * Render a mathematical expression as a numeric value * @@ -67,7 +66,7 @@ class views_handler_field_math extends views_handler_field_numeric { return ''; } - return check_plain($this->options['prefix'] . $value . $this->options['suffix']); + return $this->sanitize_value($this->options['prefix'] . $value . $this->options['suffix']); } function query() { } diff --git a/sites/all/modules/views/handlers/views_handler_field_numeric.inc b/sites/all/modules/views/handlers/views_handler_field_numeric.inc index a9ccb61f7f6e3629afe5db7ac39cbd8ef3de4737..5a990003e48337e7a8829f5e0ad8ab438803ac27 100644 --- a/sites/all/modules/views/handlers/views_handler_field_numeric.inc +++ b/sites/all/modules/views/handlers/views_handler_field_numeric.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_numeric.inc,v 1.6.4.4 2010/11/05 07:20:54 dereine Exp $ /** * Render a field as a numeric value * @@ -27,8 +26,6 @@ class views_handler_field_numeric extends views_handler_field { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); - if (!empty($this->definition['float'])) { $form['set_precision'] = array( '#type' => 'checkbox', @@ -41,7 +38,6 @@ class views_handler_field_numeric extends views_handler_field { '#title' => t('Precision'), '#default_value' => $this->options['precision'], '#description' => t('Specify how many digits to print after the decimal point.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array('edit-options-set-precision' => array(TRUE)), '#size' => 2, ); @@ -71,7 +67,6 @@ class views_handler_field_numeric extends views_handler_field { '#title' => t('Singular form'), '#default_value' => $this->options['format_plural_singular'], '#description' => t('Text to use for the singular form.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array('edit-options-format-plural' => array(TRUE)), ); $form['format_plural_plural'] = array( @@ -79,7 +74,6 @@ class views_handler_field_numeric extends views_handler_field { '#title' => t('Plural form'), '#default_value' => $this->options['format_plural_plural'], '#description' => t('Text to use for the plural form, @count will be replaced with the value.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array('edit-options-format-plural' => array(TRUE)), ); $form['prefix'] = array( @@ -94,10 +88,12 @@ class views_handler_field_numeric extends views_handler_field { '#default_value' => $this->options['suffix'], '#description' => t('Text to put after the number, such as currency symbol.'), ); + + parent::options_form($form, $form_state); } function render($values) { - $value = $values->{$this->field_alias}; + $value = $this->get_value($values); if (!empty($this->options['set_precision'])) { $value = number_format($value, $this->options['precision'], $this->options['decimal'], $this->options['separator']); } @@ -121,6 +117,6 @@ class views_handler_field_numeric extends views_handler_field { $value = format_plural($value, $this->options['format_plural_singular'], $this->options['format_plural_plural']); } - return check_plain($this->options['prefix'] . $value . $this->options['suffix']); + return $this->sanitize_value($this->options['prefix'] . $value . $this->options['suffix']); } } 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 a8869ad51b2922460132096935fea783b03aec91..9cc719c5ec91b96ef5516f89374757d556c79901 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_prerender_list.inc,v 1.3.4.4 2010/11/05 07:20:54 dereine Exp $ /** * Field handler to provide a list of items. @@ -22,7 +21,6 @@ class views_handler_field_prerender_list extends views_handler_field { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['type'] = array( '#type' => 'radios', '#title' => t('Display type'), @@ -38,9 +36,9 @@ class views_handler_field_prerender_list extends views_handler_field { '#type' => 'textfield', '#title' => t('Separator'), '#default_value' => $this->options['separator'], - '#process' => array('ctools_dependent_process'), '#dependency' => array('radio:options[type]' => array('separator')), ); + parent::options_form($form, $form_state); } /** @@ -51,10 +49,10 @@ class views_handler_field_prerender_list extends views_handler_field { * exists, this will not get used by advanced_render. */ function render($values) { - $field = $values->{$this->field_alias}; + $field = $this->get_value($values); if (!empty($this->items[$field])) { if ($this->options['type'] == 'separator') { - return implode(check_plain($this->options['separator']), $this->items[$field]); + return implode($this->sanitize_value($this->options['separator']), $this->items[$field]); } else { return theme('item_list', @@ -76,7 +74,7 @@ class views_handler_field_prerender_list extends views_handler_field { function render_items($items) { if (!empty($items)) { if ($this->options['type'] == 'separator') { - return implode(check_plain($this->options['separator']), $items); + return implode($this->sanitize_value($this->options['separator']), $items); } else { return theme('item_list', @@ -100,7 +98,7 @@ class views_handler_field_prerender_list extends views_handler_field { * should also be in this array. */ function get_items($values) { - $field = $values->{$this->field_alias}; + $field = $this->get_value($values); if (!empty($this->items[$field])) { return $this->items[$field]; } diff --git a/sites/all/modules/views/handlers/views_handler_field_serialized.inc b/sites/all/modules/views/handlers/views_handler_field_serialized.inc new file mode 100644 index 0000000000000000000000000000000000000000..e5daa6ede62e6cb198b2d0a227be2f14abfce82d --- /dev/null +++ b/sites/all/modules/views/handlers/views_handler_field_serialized.inc @@ -0,0 +1,55 @@ +<?php + +class views_handler_field_serialized extends views_handler_field { + + function option_definition() { + $options = parent::option_definition(); + $options['format'] = array('default' => 'unserialized'); + $options['key'] = array('default' => ''); + return $options; + } + + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + $form['format'] = array( + '#type' => 'select', + '#title' => t('Display format'), + '#description' => t('How should the serialized data be displayed. You can choose a custom array/object key or a print_r on the full output.'), + '#options' => array( + 'unserialized' => t('Full data (unserialized)'), + 'serialized' => t('Full data (serialized)'), + 'key' => t('A certain key'), + ), + '#default_value' => $this->options['format'], + ); + $form['key'] = array( + '#type' => 'textfield', + '#title' => t('Which key should be displayed'), + '#default_value' => $this->options['key'], + '#dependency' => array('edit-options-format' => array('key')), + ); + } + + function options_validate(&$form, &$form_state) { + // Require a key if the format is key. + if ($form_state['values']['options']['format'] == 'key' && $form_state['values']['options']['key'] == '') { + form_error($form['key'], t('You have to enter a key if you want to display a key of the data.')); + } + } + + function render($values) { + $value = $values->{$this->field_alias}; + + if ($this->options['format'] == 'unserialized') { + return check_plain(print_r(unserialize($value), TRUE)); + } + elseif ($this->options['format'] == 'key' && !empty($this->options['key'])) { + $value = (array) unserialize($value); + return check_plain($value[$this->options['key']]); + } + + return $value; + } +} \ No newline at end of file diff --git a/sites/all/modules/views/handlers/views_handler_field_time_interval.inc b/sites/all/modules/views/handlers/views_handler_field_time_interval.inc new file mode 100644 index 0000000000000000000000000000000000000000..ca50885d367467e76e7e1408cf53cb3b44197127 --- /dev/null +++ b/sites/all/modules/views/handlers/views_handler_field_time_interval.inc @@ -0,0 +1,31 @@ +<?php +/** + * A handler to provide proper displays for time intervals. + * + * @ingroup views_field_handlers + */ +class views_handler_field_time_interval extends views_handler_field { + function option_definition() { + $options = parent::option_definition(); + + $options['granularity'] = array('default' => 2); + + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + $form['granularity'] = array( + '#type' => 'textfield', + '#title' => t('Granularity'), + '#description' => t('How many different units to display in the string.'), + '#default_value' => $this->options['granularity'], + ); + } + + function render($values) { + $value = $values->{$this->field_alias}; + return format_interval($value, isset($this->options['granularity']) ? $this->options['granularity'] : 2); + } +} diff --git a/sites/all/modules/views/handlers/views_handler_field_url.inc b/sites/all/modules/views/handlers/views_handler_field_url.inc index dc3cd363cac8d6f4df672d4689b2130d0e9751a5..2491f354261f239815061480083b90797ada64b9 100644 --- a/sites/all/modules/views/handlers/views_handler_field_url.inc +++ b/sites/all/modules/views/handlers/views_handler_field_url.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_url.inc,v 1.1 2008/09/03 19:21:28 merlinofchaos Exp $ /** * Field handler to provide simple renderer that turns a URL into a clickable link. @@ -19,21 +18,21 @@ class views_handler_field_url extends views_handler_field { * Provide link to the page being visited. */ function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['display_as_link'] = array( '#title' => t('Display as link'), '#type' => 'checkbox', '#default_value' => !empty($this->options['display_as_link']), ); + parent::options_form($form, $form_state); } function render($values) { - $value = $values->{$this->field_alias}; + $value = $this->get_value($values); if (!empty($this->options['display_as_link'])) { - return l(check_plain($value), $value, array('html' => TRUE)); + return l($this->sanitize_value($value), $value, array('html' => TRUE)); } else { - return $value; + return $this->sanitize_value($value, 'url'); } } } diff --git a/sites/all/modules/views/handlers/views_handler_filter.inc b/sites/all/modules/views/handlers/views_handler_filter.inc index a67ac94fa202b94e3049134275b160e168fda497..1a1190ddddfdc6725873d36ab65610ddd258696f 100644 --- a/sites/all/modules/views/handlers/views_handler_filter.inc +++ b/sites/all/modules/views/handlers/views_handler_filter.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter.inc,v 1.10.4.15 2010/12/24 13:42:00 dereine Exp $ /** * @defgroup views_filter_handlers Views' filter handlers * @{ @@ -8,7 +7,17 @@ * Definition items: * - allow empty: If true, the 'IS NULL' and 'IS NOT NULL' operators become * available as standard operators. - * - + * + * Object flags: + * You can set some specific behavior by setting up the following flags on + * your custom class. + * + * - always_multiple: + * Disable the possibility to force a single value. + * - no_operator: + * Disable the possibility to use operators. + * - always_required: + * Disable the possibility to allow a exposed input to be optional. */ /** @@ -27,9 +36,20 @@ class views_handler_filter extends views_handler { $this->operator = $this->options['operator']; $this->value = $this->options['value']; + // Compatibility: The new UI changed several settings. + if (!empty($options['exposed']) && !empty($options['expose']['optional']) && !isset($options['expose']['required'])) { + $this->options['expose']['required'] = !$options['expose']['optional']; + } + if (!empty($options['exposed']) && !empty($options['expose']['single']) && !isset($options['expose']['multiple'])) { + $this->options['expose']['multiple'] = !$options['expose']['single']; + } + if (!empty($options['exposed']) && !empty($options['expose']['operator']) && !isset($options['expose']['operator_id'])) { + $this->options['expose']['operator_id'] = $options['expose']['operator_id'] = $options['expose']['operator']; + } + // Compatibility: Set use_operator to true if the old way of using // the operator is set and use_operator is NULL (was never set). - if (!empty($options['exposed']) && !empty($options['expose']['operator']) && !isset($options['expose']['use_operator'])) { + if (!empty($options['exposed']) && !empty($options['expose']['operator_id']) && !isset($options['expose']['use_operator'])) { $this->options['expose']['use_operator'] = TRUE; } @@ -50,14 +70,14 @@ class views_handler_filter extends views_handler { $options['exposed'] = array('default' => FALSE); $options['expose'] = array( 'contains' => array( - 'operator' => array('default' => FALSE), + 'operator_id' => array('default' => FALSE), 'label' => array('default' => '', 'translatable' => TRUE), 'use_operator' => array('default' => 0), 'operator' => array('default' => ''), 'identifier' => array('default' => ''), - 'optional' => array('default' => 1), + 'required' => array('default' => 0), 'remember' => array('default' => 0), - 'single' => array('default' => 1), + 'multiple' => array('default' => 0), ), ); @@ -87,10 +107,8 @@ class views_handler_filter extends views_handler { if ($this->can_expose()) { $this->show_expose_button($form, $form_state); } - $form['op_val_start'] = array('#markup' => '<div class="clearfix">'); $this->show_operator_form($form, $form_state); $this->show_value_form($form, $form_state); - $form['op_val_end'] = array('#markup' => '</div>'); if ($this->can_expose()) { $this->show_expose_form($form, $form_state); } @@ -105,7 +123,6 @@ class views_handler_filter extends views_handler { if (!empty($this->options['exposed'])) { $this->expose_validate($form, $form_state); } - } /** @@ -195,74 +212,132 @@ class views_handler_filter extends views_handler { function value_submit($form, &$form_state) { } /** - * Handle the 'left' side fo the exposed options form. + * Shortcut to display the expose/hide button. */ - function expose_form_left(&$form, &$form_state) { + function show_expose_button(&$form, &$form_state) { + $form['expose_button'] = array( + '#prefix' => '<div class="views-expose clearfix">', + '#suffix' => '</div>', + // Should always come after the description and the relationship. + '#weight' => -200, + ); + + // Add a checkbox for JS users, which will have behavior attached to it + // so it can replace the button. + $form['expose_button']['checkbox'] = array( + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('js-only')), + ); + $form['expose_button']['checkbox']['checkbox'] = array( + '#title' => t('Expose this filter to visitors, to allow them to change it.'), + '#type' => 'checkbox', + ); + + // Then add the button itself. + if (empty($this->options['exposed'])) { + $form['expose_button']['markup'] = array( + '#markup' => '<div class="description exposed-description">' . t('This filter is not exposed. Expose it to allow the users to change it.') . '</div>', + ); + $form['expose_button']['button'] = array( + '#limit_validation_errors' => array(), + '#type' => 'submit', + '#value' => t('Expose filter'), + '#submit' => array('views_ui_config_item_form_expose'), + ); + $form['expose_button']['checkbox']['checkbox']['#default_value'] = 0; + } + else { + $form['expose_button']['markup'] = array( + '#markup' => '<div class="description exposed-description">' . t('This filter is exposed. If you hide it, users will not be able to change it.') . '</div>', + ); + $form['expose_button']['button'] = array( + '#limit_validation_errors' => array(), + '#type' => 'submit', + '#value' => t('Hide filter'), + '#submit' => array('views_ui_config_item_form_expose'), + ); + $form['expose_button']['checkbox']['checkbox']['#default_value'] = 1; + } + } + + function expose_form(&$form, &$form_state) { + $form['#theme'] = 'views_ui_expose_filter_form'; + // #flatten will move everything from $form['expose'][$key] to $form[$key] + // prior to rendering. That's why the pre_render for it needs to run first, + // so that when the next pre_render (the one for fieldsets) runs, it gets + // the flattened data. + array_unshift($form['#pre_render'], 'views_ui_pre_render_flatten_data'); + $form['expose']['#flatten'] = TRUE; + + if (empty($this->always_required)) { + $form['expose']['required'] = array( + '#type' => 'checkbox', + '#title' => t('Required'), + '#default_value' => $this->options['expose']['required'], + ); + } + $form['expose']['label'] = array( + '#type' => 'textfield', + '#default_value' => $this->options['expose']['label'], + '#title' => t('Label'), + '#size' => 40, + ); + if (!empty($form['operator']['#type'])) { + // Increase the width of the left (operator) column. + $form['operator']['#prefix'] = '<div class="views-left-40">'; + $form['operator']['#suffix'] = '</div>'; + $form['value']['#prefix'] = '<div class="views-right-60">'; + $form['value']['#suffix'] = '</div>'; + $form['expose']['use_operator'] = array( '#type' => 'checkbox', - '#title' => t('Unlock operator'), - '#description' => t('When checked, the operator will be exposed to the user'), + '#title' => t('Expose operator'), + '#description' => t('Allow the user to choose the operator.'), '#default_value' => !empty($this->options['expose']['use_operator']), ); - $form['expose']['operator'] = array( + $form['expose']['operator_id'] = array( '#type' => 'textfield', - '#default_value' => $this->options['expose']['operator'], + '#default_value' => $this->options['expose']['operator_id'], '#title' => t('Operator identifier'), '#size' => 40, '#description' => t('This will appear in the URL after the ? to identify this operator.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array( 'edit-options-expose-use-operator' => array(1) ), + '#fieldset' => 'more', ); } else { - $form['expose']['operator'] = array( + $form['expose']['operator_id'] = array( '#type' => 'value', '#value' => '', ); } - $form['expose']['identifier'] = array( - '#type' => 'textfield', - '#default_value' => $this->options['expose']['identifier'], - '#title' => t('Filter identifier'), - '#size' => 40, - '#description' => t('This will appear in the URL after the ? to identify this filter. Cannot be blank.'), - ); - $form['expose']['label'] = array( - '#type' => 'textfield', - '#default_value' => $this->options['expose']['label'], - '#title' => t('Label'), - '#size' => 40, - ); - } - - /** - * Handle the 'right' side fo the exposed options form. - */ - function expose_form_right(&$form, &$form_state) { - $form['expose']['optional'] = array( - '#type' => 'checkbox', - '#title' => t('Optional'), - '#description' => t('This exposed filter is optional and will have added options to allow it not to be set.'), - '#default_value' => $this->options['expose']['optional'], - ); - if (empty($this->no_single)) { - $form['expose']['single'] = array( + if (empty($this->always_multiple)) { + $form['expose']['multiple'] = array( '#type' => 'checkbox', - '#title' => t('Force single'), - '#description' => t('Force this exposed filter to accept only one option.'), - '#default_value' => $this->options['expose']['single'], + '#title' => t('Allow multiple selections'), + '#description' => t('Enable to allow users to select multiple items.'), + '#default_value' => $this->options['expose']['multiple'], ); } $form['expose']['remember'] = array( '#type' => 'checkbox', - '#title' => t('Remember'), - '#description' => t('Remember the last setting the user gave this filter.'), + '#title' => t('Remember the last selection'), + '#description' => t('Enable to remember the last selection made by the user.'), '#default_value' => $this->options['expose']['remember'], ); + + $form['expose']['identifier'] = array( + '#type' => 'textfield', + '#default_value' => $this->options['expose']['identifier'], + '#title' => t('Filter identifier'), + '#size' => 40, + '#description' => t('This will appear in the URL after the ? to identify this filter. Cannot be blank.'), + '#fieldset' => 'more', + ); } /** @@ -292,8 +367,8 @@ class views_handler_filter extends views_handler { 'identifier' => $this->options['id'], 'label' => $this->ui_name(), 'remember' => FALSE, - 'single' => TRUE, - 'optional' => TRUE, + 'multiple' => FALSE, + 'required' => FALSE, ); } @@ -308,8 +383,8 @@ class views_handler_filter extends views_handler { } // Build the exposed form, when its based on an operator. - if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator'])) { - $operator = $this->options['expose']['operator']; + if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id'])) { + $operator = $this->options['expose']['operator_id']; $this->operator_form($form, $form_state); $form[$operator] = $form['operator']; @@ -362,20 +437,20 @@ class views_handler_filter extends views_handler { } // Checkboxes don't work so well in exposed forms due to GET conversions. if ($form['#type'] == 'checkboxes') { - if (empty($form['#no_convert']) || !empty($this->options['expose']['single'])) { + if (empty($form['#no_convert']) || empty($this->options['expose']['multiple'])) { $form['#type'] = 'select'; } - if (empty($this->options['expose']['single'])) { + if (!empty($this->options['expose']['multiple'])) { $form['#multiple'] = TRUE; } } - if (!empty($this->options['expose']['single']) && isset($form['#multiple'])) { + if (empty($this->options['expose']['multiple']) && isset($form['#multiple'])) { unset($form['#multiple']); $form['#size'] = NULL; } - if ($type == 'value' && !empty($this->options['expose']['optional']) && $form['#type'] == 'select' && empty($form['#multiple'])) { - $any_label = variable_get('views_exposed_filter_any_label', 'old_any') == 'old_any' ? t('<Any>') : t('- Any -'); + if ($type == 'value' && empty($this->always_required) && empty($this->options['expose']['required']) && $form['#type'] == 'select' && empty($form['#multiple'])) { + $any_label = variable_get('views_exposed_filter_any_label', 'new_any') == 'old_any' ? t('<Any>') : t('- Any -'); $form['#options'] = array('All' => $any_label) + $form['#options']; $form['#default_value'] = 'All'; } @@ -397,7 +472,7 @@ class views_handler_filter extends views_handler { } return array( - 'operator' => $this->options['expose']['operator'], + 'operator' => $this->options['expose']['operator_id'], 'value' => $this->options['expose']['identifier'], 'label' => $this->options['expose']['label'], ); @@ -413,16 +488,15 @@ class views_handler_filter extends views_handler { } - if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator']) && isset($input[$this->options['expose']['operator']])) { - $this->operator = $input[$this->options['expose']['operator']]; + if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']) && isset($input[$this->options['expose']['operator_id']])) { + $this->operator = $input[$this->options['expose']['operator_id']]; } if (!empty($this->options['expose']['identifier'])) { $value = $input[$this->options['expose']['identifier']]; - // Various ways to check for the absence of optional input. - if (!empty($this->options['expose']['optional'])) { - + // Various ways to check for the absence of non-required input. + if (empty($this->options['expose']['required'])) { if (($this->operator == 'empty' || $this->operator == 'not empty') && $value === '') { $value = ' '; } @@ -433,7 +507,7 @@ class views_handler_filter extends views_handler { } } - if (!empty($this->no_single) && $value === '') { + if (!empty($this->always_multiple) && $value === '') { return FALSE; } } @@ -441,7 +515,7 @@ class views_handler_filter extends views_handler { if (isset($value)) { $this->value = $value; - if (empty($this->no_single) && !empty($this->options['expose']['single'])) { + if (empty($this->always_multiple) && empty($this->options['expose']['multiple'])) { $this->value = array($value); } } @@ -467,14 +541,14 @@ class views_handler_filter extends views_handler { $display_id = ($this->view->display_handler->is_defaulted('filters')) ? 'default' : $this->view->current_display; // shortcut test. - $operator = !empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator']); + $operator = !empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']); // false means that we got a setting that means to recuse ourselves, // so we should erase whatever happened to be there. if (!$status && isset($_SESSION['views'][$this->view->name][$display_id])) { $session = &$_SESSION['views'][$this->view->name][$display_id]; - if ($operator && isset($session[$this->options['expose']['operator']])) { - unset($session[$this->options['expose']['operator']]); + if ($operator && isset($session[$this->options['expose']['operator_id']])) { + unset($session[$this->options['expose']['operator_id']]); } if (isset($session[$this->options['expose']['identifier']])) { @@ -489,8 +563,8 @@ class views_handler_filter extends views_handler { $session = &$_SESSION['views'][$this->view->name][$display_id]; - if ($operator && isset($input[$this->options['expose']['operator']])) { - $session[$this->options['expose']['operator']] = $input[$this->options['expose']['operator']]; + if ($operator && isset($input[$this->options['expose']['operator_id']])) { + $session[$this->options['expose']['operator_id']] = $input[$this->options['expose']['operator_id']]; } $session[$this->options['expose']['identifier']] = $input[$this->options['expose']['identifier']]; @@ -532,7 +606,7 @@ class views_handler_filter_broken extends views_handler_filter { } function ensure_my_table() { /* No table to ensure! */ } - function query() { /* No query to run */ } + function query($group_by = FALSE) { /* No query to run */ } function options_form(&$form, &$form_state) { $form['markup'] = array( '#markup' => '<div class="form-item description">' . t('The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.') . '</div>', 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 601b6169a2d483af30e560695eeca03bd512a66a..6c2266c183062626f11f1bfcfbee2aa7d91ae19c 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_boolean_operator.inc,v 1.6.4.8 2010/12/09 23:52:48 merlinofchaos Exp $ /** * Simple filter to handle matching of boolean values * @@ -13,7 +12,7 @@ */ class views_handler_filter_boolean_operator extends views_handler_filter { // exposed filter options - var $no_single = TRUE; + var $always_multiple = TRUE; // Don't display empty space where the operator would be. var $no_operator = TRUE; // Whether to accept NULL as a false value or not @@ -99,8 +98,8 @@ 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['optional'])) { - $any_label = variable_get('views_exposed_filter_any_label', 'old_any') == 'old_any' ? '<Any>' : t('- Any -'); + if (empty($form_state['exposed']) || empty($this->options['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); } @@ -110,8 +109,8 @@ class views_handler_filter_boolean_operator extends views_handler_filter { } function value_validate($form, &$form_state) { - if ($form_state['values']['options']['value'] == 'All' && empty($form_state['values']['options']['expose']['optional'])) { - form_set_error('value', t('You must select a value unless this is an optional exposed filter.')); + if ($form_state['values']['options']['value'] == 'All' && !empty($form_state['values']['options']['expose']['required'])) { + form_set_error('value', t('You must select a value unless this is an non-required exposed filter.')); } } @@ -131,9 +130,9 @@ class views_handler_filter_boolean_operator extends views_handler_filter { function expose_options() { parent::expose_options(); - $this->options['expose']['operator'] = ''; + $this->options['expose']['operator_id'] = ''; $this->options['expose']['label'] = $this->value_value; - $this->options['expose']['optional'] = FALSE; + $this->options['expose']['required'] = TRUE; } function query() { 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 f5b5cb17ecd27ac10e8c7a16921ae3ffb7bf1069..bd7bd87ef172691705cf6bcaf016bb7bcdccdf20 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_boolean_operator_string.inc,v 1.2.4.1 2009/11/02 22:01:25 merlinofchaos Exp $ /** * Simple filter to handle matching of boolean values. * 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 8493169242c397f932dff415af3d4728e25dfa1e..0f390a31879ce1bca43d04c046c990878406c947 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_date.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_date.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_date.inc,v 1.3.6.7 2011/01/03 17:46:33 dereine Exp $ /** * Filter to handle dates stored as a timestamp. @@ -35,8 +34,8 @@ class views_handler_filter_date extends views_handler_filter_numeric { function options_validate(&$form, &$form_state) { parent::options_validate($form, $form_state); - if (!empty($form_state['values']['options']['expose']['optional'])) { - // Who cares what the value is if it's exposed and optional. + if (!empty($form_state['values']['options']['expose']['required'])) { + // Who cares what the value is if it's exposed and non-required. return; } @@ -48,14 +47,14 @@ class views_handler_filter_date extends views_handler_filter_numeric { return; } - if (!empty($this->options['expose']['optional'])) { - // Who cares what the value is if it's exposed and optional. + if (empty($this->options['expose']['required'])) { + // Who cares what the value is if it's exposed and non-required. return; } $value = &$form_state['values'][$this->options['expose']['identifier']]; - if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator'])) { - $operator = $form_state['values'][$this->options['expose']['operator']]; + if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id'])) { + $operator = $form_state['values'][$this->options['expose']['operator_id']]; } else { $operator = $this->operator; @@ -100,8 +99,8 @@ class views_handler_filter_date extends views_handler_filter_numeric { // Don't filter if value(s) are empty. $operators = $this->operators(); - if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator'])) { - $operator = $input[$this->options['expose']['operator']]; + if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id'])) { + $operator = $input[$this->options['expose']['operator_id']]; } else { $operator = $this->operator; @@ -124,24 +123,17 @@ class views_handler_filter_date extends views_handler_filter_numeric { } function op_between($field) { - if ($this->operator == 'between') { - $a = intval(strtotime($this->value['min'], 0)); - $b = intval(strtotime($this->value['max'], 0)); - } - else { - $a = intval(strtotime($this->value['max'], 0)); - $b = intval(strtotime($this->value['min'], 0)); - } + $a = intval(strtotime($this->value['min'], 0)); + $b = intval(strtotime($this->value['max'], 0)); if ($this->value['type'] == 'offset') { $a = '***CURRENT_TIME***' . sprintf('%+d', $a); // keep sign $b = '***CURRENT_TIME***' . sprintf('%+d', $b); // keep sign } - // %s is safe here because strtotime scrubbed the input and we might - // have a string if using offset. - $placeholder1 = $this->placeholder(); - $placeholder2 = $this->placeholder(); - $this->query->add_where($this->options['group'], "$field BETWEEN $placeholder1 AND $placeholder2", array($placeholder1 => $a, $placeholder2 => $b), 'formula'); + // This is safe because we are manually scrubbing the values. + // It is necessary to do it this way because $a and $b are formulas when using an offset. + $operator = strtoupper($this->operator); + $this->query->add_where_expression($this->options['group'], "$field $operator $a AND $b"); } function op_simple($field) { @@ -149,7 +141,8 @@ class views_handler_filter_date extends views_handler_filter_numeric { if (!empty($this->value['type']) && $this->value['type'] == 'offset') { $value = '***CURRENT_TIME***' . sprintf('%+d', $value); // keep sign } - $placeholder = $this->placeholder(); - $this->query->add_where($this->options['group'], "$field $this->operator $placeholder", array($placeholder => $value), 'formula'); + // This is safe because we are manually scrubbing the value. + // It is necessary to do it this way because $value is a formula when using an offset. + $this->query->add_where_expression($this->options['group'], "$field $this->operator $value"); } } 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 cd5a6182b24f2bf96f8722d387ae50bc1eb3faeb..d0a9f0702f479430d4474ecffe4f0de84188e6ee 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_equality.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_equality.inc @@ -1,11 +1,10 @@ <?php -// $Id: views_handler_filter_equality.inc,v 1.2 2008/09/10 01:08:06 merlinofchaos Exp $ /** * Simple filter to handle equal to / not equal to filters */ class views_handler_filter_equality extends views_handler_filter { // exposed filter options - var $no_single = TRUE; + var $always_multiple = TRUE; /** * Provide simple equality operator @@ -35,5 +34,4 @@ class views_handler_filter_equality extends views_handler_filter { } } } -} - +} \ No newline at end of file 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 b65773f83fd0950d2fd60e7cf5465ffa51efe26c..4b56075a256c1cd13555be9004a5a6b9d7c58ec7 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_group_by_numeric.inc,v 1.1.4.7 2011/01/04 00:55:39 dereine Exp $ /** * Simple filter to handle greater than/less than filters 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 9c000120873573df0c2a2bedaa5d0b79a967781c..9be0c91c495da2b2f27d8b648382b87405f7f038 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_in_operator.inc,v 1.12.4.11 2010/12/16 01:06:06 merlinofchaos Exp $ /** * Simple filter to handle matching of multiple options selectable via checkboxes * @@ -49,8 +48,8 @@ class views_handler_filter_in_operator extends views_handler_filter { $this->options['expose']['reduce'] = FALSE; } - function expose_form_right(&$form, &$form_state) { - parent::expose_form_right($form, $form_state); + function expose_form(&$form, &$form_state) { + parent::expose_form($form, $form_state); $form['expose']['reduce'] = array( '#type' => 'checkbox', '#title' => t('Limit list to selected items'), @@ -137,9 +136,15 @@ class views_handler_filter_in_operator extends views_handler_filter { function value_form(&$form, &$form_state) { $form['value'] = array(); + $options = array(); + + if (empty($form_state['exposed'])) { + // Add a select all option to the value form. + $options = array('all' => t('Select all')); + } $this->get_value_options(); - $options = $this->value_options; + $options += $this->value_options; $default_value = (array) $this->value; $which = 'all'; @@ -149,24 +154,24 @@ class views_handler_filter_in_operator extends views_handler_filter { if (!empty($form_state['exposed'])) { $identifier = $this->options['expose']['identifier']; - if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator'])) { + if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator_id'])) { // exposed and locked. $which = in_array($this->operator, $this->operator_values(1)) ? 'value' : 'none'; } else { - $source = 'edit-' . drupal_html_id($this->options['expose']['operator']); + $source = 'edit-' . drupal_html_id($this->options['expose']['operator_id']); } if (!empty($this->options['expose']['reduce'])) { $options = $this->reduce_value_options(); - if (empty($this->options['expose']['single']) && !empty($this->options['expose']['optional'])) { + if (!empty($this->options['expose']['multiple']) && empty($this->options['expose']['required'])) { $default_value = array(); } } - if (!empty($this->options['expose']['single'])) { - if (!empty($this->options['expose']['optional']) && (empty($default_value) || !empty($this->options['expose']['reduce']))) { + if (empty($this->options['expose']['multiple'])) { + if (empty($this->options['expose']['required']) && (empty($default_value) || !empty($this->options['expose']['reduce']))) { $default_value = 'All'; } elseif (empty($default_value)) { @@ -194,28 +199,13 @@ class views_handler_filter_in_operator extends views_handler_filter { $form_state['input'][$identifier] = $default_value; } - $process = array(); - if ($this->value_form_type == 'checkboxes') { - // If this form element will use checkboxes in the UI, we need to - // check_plain() all the options ourselves since FAPI is inconsistent - // about this. However, instead of directly doing that to the #options - // right now, we define a #process callback since we might change our - // mind later and convert this into a 'select' form element, which - // would lead to double-escaping the options. - $process[] = 'views_process_check_options'; - } if ($which == 'all') { if (empty($form_state['exposed']) && (in_array($this->value_form_type, array('checkbox', 'checkboxes', 'radios', 'select')))) { - $process[] = "form_process_$this->value_form_type"; $form['value']['#prefix'] = '<div id="edit-options-value-wrapper">'; $form['value']['#suffix'] = '</div>'; } - $process[] = 'ctools_dependent_process'; $form['value']['#dependency'] = array($source => $this->operator_values(1)); } - if (!empty($process)) { - $form['value']['#process'] = $process; - } } } @@ -257,9 +247,9 @@ class views_handler_filter_in_operator extends views_handler_filter { return TRUE; } - // If this is single and optional, this says that yes this filter will + // If this is non-multiple and non-required, then this filter will // participate, but using the default settings, *if* 'limit is true. - if (!empty($this->options['expose']['single']) && !empty($this->options['expose']['optional']) && !empty($this->options['expose']['limit'])) { + if (empty($this->options['expose']['multiple']) && empty($this->options['expose']['required']) && !empty($this->options['expose']['limit'])) { $identifier = $this->options['expose']['identifier']; if ($input[$identifier] == 'All') { return TRUE; 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 68716543f3fcfaa37331cbaadbc19774b7aaa11c..9fa4ef76a804b1d85296cf65af6fd23d34253aae 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_many_to_one.inc,v 1.2.4.5 2010/10/12 22:14:55 merlinofchaos Exp $ /** * Complex filter to handle filtering for many to one relationships, 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 0c5ce5756658b238204084edb56b842a70a4e391..e28116c1b100978067f89b4f3676d34898f34a24 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_numeric.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_numeric.inc @@ -1,11 +1,10 @@ <?php -// $Id: views_handler_filter_numeric.inc,v 1.7.6.7 2011/01/01 10:59:37 dereine Exp $ /** * Simple filter to handle greater than/less than filters */ class views_handler_filter_numeric extends views_handler_filter { - var $no_single = TRUE; + var $always_multiple = TRUE; function option_definition() { $options = parent::option_definition(); @@ -133,12 +132,12 @@ class views_handler_filter_numeric extends views_handler_filter { if (!empty($form_state['exposed'])) { $identifier = $this->options['expose']['identifier']; - if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator'])) { + if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator_id'])) { // exposed and locked. $which = in_array($this->operator, $this->operator_values(2)) ? 'minmax' : 'value'; } else { - $source = 'edit-' . drupal_html_id($this->options['expose']['operator']); + $source = 'edit-' . drupal_html_id($this->options['expose']['operator_id']); } } @@ -148,7 +147,6 @@ class views_handler_filter_numeric extends views_handler_filter { '#title' => empty($form_state['exposed']) ? t('Value') : '', '#size' => 30, '#default_value' => $this->value['value'], - '#process' => array('ctools_dependent_process'), '#dependency' => array($source => $this->operator_values(1)), ); if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['value'])) { @@ -184,7 +182,6 @@ class views_handler_filter_numeric extends views_handler_filter { ); if ($which == 'all') { $dependency = array( - '#process' => array('ctools_dependent_process'), '#dependency' => array($source => $this->operator_values(2)), ); $form['value']['min'] += $dependency; @@ -278,8 +275,8 @@ class views_handler_filter_numeric extends views_handler_filter { $rc = parent::accept_exposed_input($input); - if (!empty($this->options['expose']['optional'])) { - // We have to do some of our own optional checking. + if (empty($this->options['expose']['required'])) { + // We have to do some of our own checking for non-required filters. $info = $this->operators(); if (!empty($info[$this->operator]['values'])) { switch ($info[$this->operator]['values']) { 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 9c4408054f8452a13b0f37f8c3c34cb618dc6b95..9ff8ebe27267fbdbf95b90621dad5b51fc156515 100644 --- a/sites/all/modules/views/handlers/views_handler_filter_string.inc +++ b/sites/all/modules/views/handlers/views_handler_filter_string.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_string.inc,v 1.8.4.6 2011/01/05 18:18:40 dereine Exp $ /** * Basic textfield filter to handle string filtering commands @@ -7,7 +6,16 @@ */ class views_handler_filter_string extends views_handler_filter { // exposed filter options - var $no_single = TRUE; + var $always_multiple = TRUE; + var $always_required = TRUE; + + function option_defintion() { + $options = parent::option_defintion(); + + $options['expose']['contains']['required'] = array('default' => TRUE); + + return $options; + } /** * This kind of construct makes it relatively easy for a child class @@ -128,7 +136,10 @@ class views_handler_filter_string extends views_handler_filter { } $options = $this->operator_options('short'); - $output = check_plain($options[$this->operator]); + $output = ''; + if(!empty($options[$this->operator])) { + $output = check_plain($options[$this->operator]); + } if (in_array($this->operator, $this->operator_values(1))) { $output .= ' ' . check_plain($this->value); } @@ -161,12 +172,12 @@ class views_handler_filter_string extends views_handler_filter { if (!empty($form_state['exposed'])) { $identifier = $this->options['expose']['identifier']; - if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator'])) { + if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator_id'])) { // exposed and locked. $which = in_array($this->operator, $this->operator_values(1)) ? 'value' : 'none'; } else { - $source = 'edit-' . drupal_html_id($this->options['expose']['operator']); + $source = 'edit-' . drupal_html_id($this->options['expose']['operator_id']); } } @@ -183,7 +194,6 @@ class views_handler_filter_string extends views_handler_filter { if ($which == 'all') { $form['value'] += array( - '#process' => array('ctools_dependent_process'), '#dependency' => array($source => $this->operator_values(1)), ); } @@ -224,8 +234,7 @@ class views_handler_filter_string extends views_handler_filter { } function op_contains($field) { - $placeholder = $this->placeholder(); - $this->query->add_where($this->options['group'], "$field LIKE $placeholder", array($placeholder => '%' . db_like($this->value) . '%'), 'formula'); + $this->query->add_where($this->options['group'], $field, '%' . db_like($this->value) . '%', 'LIKE'); } function op_word($field) { @@ -257,38 +266,33 @@ class views_handler_filter_string extends views_handler_filter { } function op_starts($field) { - $placeholder = $this->placeholder(); - $this->query->add_where($this->options['group'], "$field LIKE $placeholder", array($placeholder => db_like($this->value) . '%'), 'formula'); + $this->query->add_where($this->options['group'], $field, db_like($this->value) . '%', 'LIKE'); } function op_not_starts($field) { - $placeholder = $this->placeholder(); - $this->query->add_where($this->options['group'], "$field NOT LIKE $placeholder", array($placeholder => db_like($this->value) . '%'), 'formula'); + $this->query->add_where($this->options['group'], $field, db_like($this->value) . '%', 'NOT LIKE'); } function op_ends($field) { - $placeholder = $this->placeholder(); - $this->query->add_where($this->options['group'], "$field LIKE $placeholder", array($placeholder => '%' . db_like($this->value)), 'formula'); + $this->query->add_where($this->options['group'], $field, '%' . db_like($this->value), 'LIKE'); } function op_not_ends($field) { - $placeholder = $this->placeholder(); - $this->query->add_where($this->options['group'], "$field NOT LIKE $placeholder", array($placeholder => '%' . db_like($this->value)), 'formula'); + $this->query->add_where($this->options['group'], $field, '%' . db_like($this->value), 'NOT LIKE'); } function op_not($field) { - $placeholder = $this->placeholder(); - $this->query->add_where($this->options['group'], "$field NOT LIKE $placeholder", array($placeholder => '%' . db_like($this->value) . '%'), 'formula'); + $this->query->add_where($this->options['group'], $field, '%' . db_like($this->value) . '%', 'NOT LIKE'); } function op_shorter($field) { $placeholder = $this->placeholder(); - $this->query->add_where($this->options['group'], "LENGTH($field) < $placeholder", array($placeholder => $this->value), 'formula'); + $this->query->add_where_expression($this->options['group'], "LENGTH($field) < $placeholder", array($placeholder => $this->value)); } function op_longer($field) { $placeholder = $this->placeholder(); - $this->query->add_where($this->options['group'], "LENGTH($field) > $placeholder", array($placeholder => $this->value), 'formula'); + $this->query->add_where_expression($this->options['group'], "LENGTH($field) > $placeholder", array($placeholder => $this->value)); } function op_empty($field) { diff --git a/sites/all/modules/views/handlers/views_handler_relationship.inc b/sites/all/modules/views/handlers/views_handler_relationship.inc index 9b34c3403b404095b8cea9dbbb03a405c14e1368..9af993816db2ea144c242a48537e4edd87df415d 100644 --- a/sites/all/modules/views/handlers/views_handler_relationship.inc +++ b/sites/all/modules/views/handlers/views_handler_relationship.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_relationship.inc,v 1.4.4.4 2010/12/17 21:42:19 merlinofchaos Exp $ /** * @file * Views' relationship handlers. @@ -76,15 +75,15 @@ class views_handler_relationship extends views_handler { parent::options_form($form, $form_state); $form['label'] = array( '#type' => 'textfield', - '#title' => t('Label'), + '#title' => t('Identifier'), '#default_value' => isset($this->options['label']) ? $this->options['label'] : '', - '#description' => t('The label for this relationship that will be displayed only administratively.'), + '#description' => t('Edit the administrative label displayed when referencing this relationship form filters, etc.'), ); $form['required'] = array( '#type' => 'checkbox', '#title' => t('Require this relationship'), - '#description' => t('If required, items that do not contain this relationship will not appear.'), + '#description' => t('Enable to hide items that do not contain this relationship'), '#default_value' => !empty($this->options['required']), ); } diff --git a/sites/all/modules/views/handlers/views_handler_sort.inc b/sites/all/modules/views/handlers/views_handler_sort.inc index 9e4662c65c2100f73b1e1a9bbaf05845915ad711..e609ababbab8d2a1e4c55dc722556dffd8a45408 100644 --- a/sites/all/modules/views/handlers/views_handler_sort.inc +++ b/sites/all/modules/views/handlers/views_handler_sort.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_sort.inc,v 1.2.4.4 2010/12/17 21:42:19 merlinofchaos Exp $ /** * @defgroup views_sort_handlers Views' sort handlers * @{ @@ -74,6 +73,55 @@ class views_handler_sort extends views_handler { } } + /** + * Shortcut to display the expose/hide button. + */ + function show_expose_button(&$form, &$form_state) { + $form['expose_button'] = array( + '#prefix' => '<div class="views-expose clearfix">', + '#suffix' => '</div>', + // Should always come first + '#weight' => -1000, + ); + + // Add a checkbox for JS users, which will have behavior attached to it + // so it can replace the button. + $form['expose_button']['checkbox'] = array( + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('js-only')), + ); + $form['expose_button']['checkbox']['checkbox'] = array( + '#title' => t('Expose this sort to visitors, to allow them to change it.'), + '#type' => 'checkbox', + ); + + // Then add the button itself. + if (empty($this->options['exposed'])) { + $form['expose_button']['markup'] = array( + '#markup' => '<div class="description exposed-description" style="float: left; margin-right:10px">' . t('This sort is not exposed. Expose it to allow the users to change it.') . '</div>', + ); + $form['expose_button']['button'] = array( + '#limit_validation_errors' => array(), + '#type' => 'submit', + '#value' => t('Expose sort'), + '#submit' => array('views_ui_config_item_form_expose'), + ); + $form['expose_button']['checkbox']['checkbox']['#default_value'] = 0; + } + else { + $form['expose_button']['markup'] = array( + '#markup' => '<div class="description exposed-description">' . t('This sort is exposed. If you hide it, users will not be able to change it.') . '</div>', + ); + $form['expose_button']['button'] = array( + '#limit_validation_errors' => array(), + '#type' => 'submit', + '#value' => t('Hide sort'), + '#submit' => array('views_ui_config_item_form_expose'), + ); + $form['expose_button']['checkbox']['checkbox']['#default_value'] = 1; + } + } + /** * Simple validate handler */ @@ -118,41 +166,30 @@ class views_handler_sort extends views_handler { * Provide a list of options for the default sort form. * Should be overridden by classes that don't override sort_form */ - function sort_options() { + function sort_options() { return array( - 'ASC' => t('Sort ascending'), + 'ASC' => t('Sort ascending'), 'DESC' => t('Sort descending'), - ); + ); } - /** - * Since all exposed sorts are grouped into one select box. - * We don't return nothing when views call to exposed_form() - */ - function exposed_form(&$form, &$form_state) { } + function expose_form(&$form, &$form_state) { + // #flatten will move everything from $form['expose'][$key] to $form[$key] + // prior to rendering. That's why the pre_render for it needs to run first, + // so that when the next pre_render (the one for fieldsets) runs, it gets + // the flattened data. + array_unshift($form['#pre_render'], 'views_ui_pre_render_flatten_data'); + $form['expose']['#flatten'] = TRUE; - /** - * Handle the 'left' side fo the exposed options form. - */ - function expose_form_left(&$form, &$form_state) { $form['expose']['label'] = array( '#type' => 'textfield', '#default_value' => $this->options['expose']['label'], '#title' => t('Label'), '#required' => TRUE, '#size' => 40, + '#weight' => -1, ); } - - /** - * Handle the 'right' side fo the exposed options form. - */ - function expose_form_right(&$form, &$form_state) { - $form['expose']['order'] = array( - '#type' => 'value', - '#value' => 'ASC', - ); - } /** * Provide default options for exposed sorts. @@ -174,7 +211,7 @@ class views_handler_sort_broken extends views_handler_sort { } function ensure_my_table() { /* No table to ensure! */ } - function query() { /* No query to run */ } + function query($group_by = FALSE) { /* No query to run */ } function options_form(&$form, &$form_state) { $form['markup'] = array( '#markup' => '<div class="form-item description">' . t('The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.') . '</div>', diff --git a/sites/all/modules/views/handlers/views_handler_sort_date.inc b/sites/all/modules/views/handlers/views_handler_sort_date.inc index 9f0c76bf8ccff9d1cf3a1ca59b4510d5cd725e69..81014828e1562a00b45581108a621464c5c38a50 100644 --- a/sites/all/modules/views/handlers/views_handler_sort_date.inc +++ b/sites/all/modules/views/handlers/views_handler_sort_date.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_sort_date.inc,v 1.1 2008/09/03 19:21:28 merlinofchaos Exp $ /** * Basic sort handler for dates. 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 ddc04c6ed54c3a6b75d15ae28dbb1810206a44c2..61b3409d401c8fc3d862e126b24e0e6e38c3a575 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,5 +1,4 @@ <?php -// $Id: views_handler_sort_group_by_numeric.inc,v 1.1.4.4 2010/11/30 21:14:22 merlinofchaos Exp $ /** * Handler for GROUP BY on simple numeric fields. */ @@ -25,7 +24,7 @@ class views_handler_sort_group_by_numeric extends views_handler_sort { $this->query->add_orderby($this->table_alias, $this->real_field, $this->options['order'], NULL, $params); } - function ui_name() { - return $this->get_field(parent::ui_name()); + function ui_name($short = FALSE) { + return $this->get_field(parent::ui_name($short)); } } diff --git a/sites/all/modules/views/handlers/views_handler_sort_menu_hierarchy.inc b/sites/all/modules/views/handlers/views_handler_sort_menu_hierarchy.inc index 43a2b92e2fdeed52fe313278d5eb2ce2897e07c6..294b3c45ac972f5c9d8dc6b1b072ff0c818aab6c 100644 --- a/sites/all/modules/views/handlers/views_handler_sort_menu_hierarchy.inc +++ b/sites/all/modules/views/handlers/views_handler_sort_menu_hierarchy.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_sort_menu_hierarchy.inc,v 1.1 2008/09/03 19:21:28 merlinofchaos Exp $ /** * Sort in menu hierarchy order. 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 0a1c0a5b45af15e6abb02c54beecf7689f241eb8..3b670cb9eb7444f2c0b3b084b66fec3040db88c7 100644 --- a/sites/all/modules/views/handlers/views_handler_sort_random.inc +++ b/sites/all/modules/views/handlers/views_handler_sort_random.inc @@ -1,23 +1,11 @@ <?php -// $Id: views_handler_sort_random.inc,v 1.1.6.1 2009/11/02 22:01:25 merlinofchaos Exp $ /** * Handle a random sort. */ class views_handler_sort_random extends views_handler_sort { function query() { - switch (db_driver()) { - case 'mysql': - case 'mysqli': - $formula = 'RAND()'; - break; - case 'pgsql': - $formula = 'RANDOM()'; - break; - } - if (!empty($formula)) { - $this->query->add_orderby(NULL, $formula, $this->options['order'], '_' . $this->field); - } + $this->query->add_orderby('rand'); } function options_form(&$form, &$form_state) { diff --git a/sites/all/modules/views/help/about.html b/sites/all/modules/views/help/about.html index 3f91b997267986c921b3ba06da4b4d7364487f09..f4dd9232153c31761356029a85f80db79fad1665 100644 --- a/sites/all/modules/views/help/about.html +++ b/sites/all/modules/views/help/about.html @@ -1,18 +1,62 @@ -<!-- $Id: about.html,v 1.5.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ --> 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 "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: <ul> - <li><a href="topic:views/field">Fields</a>, or the individual pieces of data being displayed. Adding the fields <em>Node: Title</em>, <em>Node: Type</em>, and <em>Node: Post date</em> to a node view, for example, includes the title, content type and creation date in the displayed results </li> + <li><a href="topic:views/field">Fields</a>, or the individual pieces of data being displayed. Adding the fields <em>Node: Title</em>, <em>Node: Type</em>, and <em>Node: Post date</em> to a node view, for example, includes the title, content type and creation date in the displayed results </li> - <li><a href="topic:views/relationship">Relationships</a>, or information about how data elements relate to one another. If relationship data is available, like that provided by a CCK <em>nodereference</em> field, items from a related node may be included in the view </li> + <li><a href="topic:views/relationship">Relationships</a>, or information about how data elements relate to one another. If relationship data is available, like that provided by a CCK <em>nodereference</em> field, items from a related node may be included in the view </li> - <li><a href="topic:views/argument">Arguments</a>, or additional parameters that dynamically refine the view results, passed as part of the path. Adding an argument of <em>Node: Type</em> to a node view with a path of "content", for example, dynamically filters the displayed items by content type. In this example (shown with Clean URLs enabled), accessing the view through the path "<em>http://www.example.com/content/page</em>" displays all posts of the type "page", the path "<em>http://www.example.com/content/story</em>" displays all posts of the type "story", and "<em>http://www.example.com/content</em>" displays all posts regardless of type) </li> + <li><a href="topic:views/argument">Arguments</a>, or additional parameters that dynamically refine the view results, passed as part of the path. Adding an argument of <em>Node: Type</em> to a node view with a path of "content", for example, dynamically filters the displayed items by content type. In this example (shown with Clean URLs enabled), accessing the view through the path "<em>http://www.example.com/content/page</em>" displays all posts of the type "page", the path "<em>http://www.example.com/content/story</em>" displays all posts of the type "story", and "<em>http://www.example.com/content</em>" displays all posts regardless of type) </li> - <li><a href="topic:views/sort">Sort criteria</a>, which determine the order of items displayed in the view results. Adding the sort criteria <em>Node: Post date</em> (in descending order) to a node <em>view</em>, for example, sorts the displayed posts in descending order by creation date </li> + <li><a href="topic:views/sort">Sort criteria</a>, which determine the order of items displayed in the view results. Adding the sort criteria <em>Node: Post date</em> (in descending order) to a node <em>view</em>, for example, sorts the displayed posts in descending order by creation date </li> + + <li><a href="topic:views/filter">Filters</a>, which limit items displayed in the results. Adding the filter <em>Node: Published</em> (and setting it equal to "Published") to a node view, for example, prevents unpublished items from being displayed</li> + + <li><a href="topic:views/display">Displays</a>, which control where the output will be seen. Every view has a default display, which doesn't actually display the view anywhere, but is used to hold the default settings for the view, and is used when the view is called programmatically if another display is not specified. Much more useful to users are the <a href="topic:views/display-page">page</a> display, which gives a view a path and allows it to be the primary content of a page, or the <a href="topic:views/display-block">block</a> display which allows it to appear as secondary content on other pages.</li> + +<li><a href="topic:views/header">Header</a>, which allow you to add by default one or more text area above the views output. </li> + + <li><a href="topic:views/footer">Footer</a>, which allow you to add by default one or more text area beneath the views output. </li> + + <li>The <a href="topic:views/footer">Emtpy Text</a> content will be displayed, when you choose in the Arguments Section "Action to take if argument is not present" the option "Display empty text".</li> - <li><a href="topic:views/filter">Filters</a>, which limit items displayed in the results. Adding the filter <em>Node: Published</em> (and setting it equal to "Published") to a node view, for example, prevents unpublished items from being displayed</li> - <li><a href="topic:views/display">Displays</a>, which control where the output will be seen. Every view has a default display, which doesn't actually display the view anywhere, but is used to hold the default settings for the view, and is used when the view is called programmatically if another display is not specified. Much more useful to users are the <a href="topic:views/display-page">page</a> display, which gives a view a path and allows it to be the primary content of a page, or the <a href="topic:views/display-block">block</a> display which allows it to appear as secondary content on other pages.</li> </ul> + +Parallels between the components in the Views interface and an sql query: + +<table> + <thead> + <tr> + <th>Sql Query</th> + <th>Views Component</th> + <tr> + </thead> + <tr> + <td>SELECT n.title, u.name</td> + <td>fields</td> + </tr> + <tr> + <td>FROM {node} n base table</td> + <td>view type</td> + </tr> + <tr> + <td>INNER JOIN {users} u ON n.uid = u.uid</td> + <td>relationship</td> + </tr> + <tr> + <td>WHERE n.status = 1</td> + <td>filter</td> + </tr> + <tr> + <td>AND u.uid = arg(1)</td> + <td>argument</td> + </tr> + <tr> + <td>ORDER BY n.changed DESC</td> + <td>sort</td> + </tr> +</table> + + diff --git a/sites/all/modules/views/help/advanced-settings.html b/sites/all/modules/views/help/advanced-settings.html new file mode 100644 index 0000000000000000000000000000000000000000..f5fa53c561073741bc08fd64459e248eb7355e46 --- /dev/null +++ b/sites/all/modules/views/help/advanced-settings.html @@ -0,0 +1,8 @@ +<strong>Use AJAX: No</strong> +If set, this view will use an AJAX mechanism for paging, table sorting and exposed filters. This prevents the entire page from refreshing. It is not recommended that you use this if this view is the main content of the page as it will prevent deep linking to specific pages, but it is very useful for side content. +<strong>Distinct: No</strong> +This will make the view display only distinct items. If there are multiple identical items, each will be displayed only once. You can use this to try and remove duplicates from a view, though it does not always work. Note that this can slow queries down, so use it with caution. +<strong>Use grouping: No</strong> +All fields that are selected for grouping will be collapsed to one record per distinct value. Other fields which are selected for aggregation will have the function run on them. For example, you can group nodes on title and count the number of nids in order to get a list of duplicate titles. +<strong>Caching: None</strong> +You can choose a "Time-based" Caching if you want. With it you get the option to choose the length of time raw query results should be cached and "The length of time rendered HTML output should be cached." diff --git a/sites/all/modules/views/help/analyze-theme.html b/sites/all/modules/views/help/analyze-theme.html index 6605a30de6f603e558fc0431125948ea74f3dd0b..290dc0749f5484494f3cba3290d8437d1401b6c0 100644 --- a/sites/all/modules/views/help/analyze-theme.html +++ b/sites/all/modules/views/help/analyze-theme.html @@ -1,4 +1,4 @@ -<!-- $Id: analyze-theme.html,v 1.5.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ --> +<p>Clicking on the "Theme: Information" link provides you with a listing of all posiible theming files. The highlighted files are the ones Views is currently using. All other filenames are suggested templates.</p> <p>You may use any of the following possible theme files to modify individual parts of your view. In total, there are four parts to theming a view.</p> <ul> <li> The <strong>display</strong> theme is usually views-view.tpl.php and it largely controls the decorations around a view; where the header, footer, pager, more link, feed icon, etc, will be placed. </li> diff --git a/sites/all/modules/views/help/api-default-views.html b/sites/all/modules/views/help/api-default-views.html index 2a2837ca91e17dee736292493d988d127ae4ca47..e07b77fa134117c389c11987bb5edcd2af2cca7c 100644 --- a/sites/all/modules/views/help/api-default-views.html +++ b/sites/all/modules/views/help/api-default-views.html @@ -1,4 +1,3 @@ -<!-- $Id: api-default-views.html,v 1.3.6.4 2010/12/23 22:11:34 dereine Exp $ --> Views can be stored in the database, which is typical of smaller sites and hobby sites. However, Views may also be stored directly in the code as "default" views, (which simply means they're available by default). Modules often come with views that are specific to the module data, but it's also possible -- and <b>highly</b> recommended -- that sites which have separate "development" and "production" sites export their views into default views in a site-specific module. This makes it very easy to transfer views from dev to production without making database changes. <h3>Creating a module</h3> @@ -6,7 +5,6 @@ First, create a directory in <em>sites/all/modules</em> for your new module. Cal In this directory, create a <em>mymodule.module</em> file. It can be empty for now, but it should at least contain an opening PHP tag: <pre><?php -// $Id $ </pre> It should not contain a closing ?> tag, as the closing ?> tag is not required and anything AFTER the closing tag, such as a space or a linefeed, will be displayed directly to the browser and can potentially cause problems. @@ -22,8 +20,7 @@ For other uses you may well add additional functions. Second, you need to create a <em>mymodule.info</em> file: -<pre>; $Id $ -name = My module +<pre>name = My module description = My site specific module. core = 6.x </pre> diff --git a/sites/all/modules/views/help/api-example.html b/sites/all/modules/views/help/api-example.html index 9e1710046faf2a549a076d3d3a47378dd7f0e93b..04a65b99e187af27b84856e0f3b0e3b78e700db8 100644 --- a/sites/all/modules/views/help/api-example.html +++ b/sites/all/modules/views/help/api-example.html @@ -1,4 +1,3 @@ -<!-- $Id: api-example.html,v 1.2.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ --> For the new table defined by the Node example module to be understood by the views module you need to create a node_example.views.inc file that describes the table and its relationships to the rest of the database. In order for views to know that this file is to be loaded you need to implement hook_views_api. This is done by adding the following function into your node_example.module file @@ -24,7 +23,6 @@ Below is the contents of a simple node_example.views.inc file that allows you to <pre> <?php -// $Id: api-example.html,v 1.2.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * This file is used to tell the views module about the new node_example table. diff --git a/sites/all/modules/views/help/api-handlers.html b/sites/all/modules/views/help/api-handlers.html index b222618acd41f34b3317f9ddaf824c17bafcab4a..c463d899a52d81ac314d114f77a30ecd675cdc6b 100644 --- a/sites/all/modules/views/help/api-handlers.html +++ b/sites/all/modules/views/help/api-handlers.html @@ -1,4 +1,3 @@ -<!-- $Id: api-handlers.html,v 1.4.6.2 2010/07/19 09:18:42 dereine Exp $ --> In Views, a handler is an object that is part of the view and is part of the query building flow. Handlers are objects; much of the time, the base handlers will work, but often you'll need to override the handler for something. One typical handler override will be views_handler_filter_operator_in which allows you to have a filter select from a list of options; you'll need to override this to provide your list. diff --git a/sites/all/modules/views/help/api-plugins.html b/sites/all/modules/views/help/api-plugins.html index 139003836978e643b25c09345cf7072f78fbacc3..25fbffbe727bb6faec0fbd5c463f9f3d1bc88ca7 100644 --- a/sites/all/modules/views/help/api-plugins.html +++ b/sites/all/modules/views/help/api-plugins.html @@ -1,4 +1,3 @@ -<!-- $Id: api-plugins.html,v 1.7.6.2 2010/07/28 06:58:25 dereine Exp $ --> 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: diff --git a/sites/all/modules/views/help/api-tables.html b/sites/all/modules/views/help/api-tables.html index 288c4ddb96cb5ac809a0a479e547e99f50847727..b101f18c73db1e5cb81088a62d08c15c36c4dfb4 100644 --- a/sites/all/modules/views/help/api-tables.html +++ b/sites/all/modules/views/help/api-tables.html @@ -1,4 +1,3 @@ -<!-- $Id: api-tables.html,v 1.8.4.3 2010/10/12 21:21:02 merlinofchaos Exp $ --> Tables are described to Views via hook_views_data(), which returns an array of table information, keyed by the name of the table. For example, if your module is describing three tables, 'foo', 'bar' and 'baz', your array will look like this: <pre>$data = array( 'foo' => array( @@ -233,3 +232,21 @@ The following items are allowed in the field definition: </dl> For more information about what handlers need/use what data, visit <a href="http://views.doc.logrus.com">the Views API site</a> and check out the available handlers. + +<h3>Support old tabledata</h3> +If you need to rename some tables/fields you can create some references in the views data to be able to continue to work. +Therefore you create the whole table structure of the current views data. + +If you have to rename a single table you need to specify +<pre> +$data['oldtable']['moved to'] = 'newtable'; +</pre> + +If you have to rename/move a single a field to another table you specify +<pre> +$data['oldtable']['oldfield']['field']['moved to'] = array('newtable', 'newfield'); +</pre> +or +<pre> +$data['oldtable']['oldfield']['moved to'] = array('newtable', 'newfield'); +</pre> \ No newline at end of file diff --git a/sites/all/modules/views/help/api-upgrading.html b/sites/all/modules/views/help/api-upgrading.html index 58b0325fcf8221197ad2c294b3b134747ded0b2f..59f90926a5a941a7270d16b8474526372a981378 100644 --- a/sites/all/modules/views/help/api-upgrading.html +++ b/sites/all/modules/views/help/api-upgrading.html @@ -1,4 +1,3 @@ -<!-- $Id: api-upgrading.html,v 1.1.2.5 2011/01/04 00:37:55 dereine Exp $ --> In order to take advantage of the changes in Drupal 7, Views has gone through several API changes. Here's what you should know. @@ -30,35 +29,160 @@ Everyone who used it can extend from views_handler_sort, too. <h3>Ctools dependency</h3> Views requires ctools now, so it can use the dependency system of ctools. -The only thing you have to do is to replace -<pre> -'#process' => array('views_process_dependeny') -</pre> -with -<pre> -'#process' => array('ctools_dependent_process'), -</pre> +The only thing you have to do is to remove views_process_dependency. <h3>Changed add_where api</h3> If your field is a plain sql field: -<code> - $this->query->add_where($this->options['group'], "$this->table_alias.$this->real_field " . $this->operator . " '%s'", $this->value); -</code> +<pre> +$this->query->add_where($this->options['group'], "$this->table_alias.$this->real_field " . $this->operator . " '%s'", $this->value); +</pre> has to be converted to -<code> - $this->query->add_where($this->options['group'], "$this->table_alias.$this->real_field", $this->value, $this->operator); -</code> +<pre> +$this->query->add_where($this->options['group'], "$this->table_alias.$this->real_field", $this->value, $this->operator); +</pre> If your field is a complex where condition: -<code> - $this->query->add_where($this->options['group'], "$upper($field) NOT LIKE $upper('%%%s')", $this->value); -</code> +<pre> +$this->query->add_where($this->options['group'], "$upper($field) NOT LIKE $upper('%%%s')", $this->value); +</pre> has to be converted to -<code> - $placeholder = $this->placeholder(); - $this->query->add_where_expression($this->options['group'], "$field LIKE $placeholder", array($placeholder => '%' . db_like($this->value))); -</code> +<pre> +$placeholder = $this->placeholder(); +$this->query->add_where_expression($this->options['group'], "$field LIKE $placeholder", array($placeholder => '%' . db_like($this->value))); +</pre> placeholder() generates a automatic unique placeholder for you. add_where with operator 'formula' can be converted to add_where_expression. add_having with operator 'formula' can be converted to add_having_expression. +<h3>Changed place for display specific settings</h3> +In the new ui the new place for display settings is at the top of the second column. +Therefore use something like this code in your display plugin: +<pre> +$categories['block'] = array( + 'title' => t('Block settings'), + 'column' => 'second', + 'build' => array( + '#weight' => -10, + ), +); +</pre> + +<h3>Changed filter settings and associated class variables</h3> +'optional' and 'single' are now 'required' and 'multiple', the logic is now opposite. +Also, the 'no_single' and 'no_optional' class variables (known as "object flags" in the API docs) +are now 'always_multiple' and 'always_required'. + +<h3>Changed argument settings</h3> +See the init() function in views_handler_argument for an overview of everything +that changed. + +1. The default actions 'summary asc', 'summary desc', 'summary asc by count', 'summary asc by count' +have been replaced by a single 'summary' action (which takes the sort order and type as options). +2. Wildcards are now called exceptions. +<pre> +$this->options['exception']['value'] = $options['wildcard']; +$this->options['exception']['title'] = $options['wildcard_substitution']; +</pre> +3. Summary plugin options are now stored in 'summary_options' instead of 'style_options' +<pre> +$this->options['summary_options'] = $options['style_options']; +</pre> +4. The selected summary plugin is no longer stored in 'style_plugin'. +<pre> +$this->options['summary']['format'] = $options['style_plugin']; +</pre> +5. The validator options have been moved. +<pre> +$options['validate']['type'] = $options['validate_type']; +$options['validate']['fail'] = $options['validate_fail']; +</pre> +6. The validator settings have been moved from $form['argument_validate'] to ['validate_options'] +This means that dependent code in validate plugins needs to change. +Example change for views_plugin_argument_validate_user: +<pre> + $form['roles'] = array( + '#dependency' => array( +- 'edit-options-argument-validate-user-restrict-roles' => array(1), ++ 'edit-options-validate-options-user-restrict-roles' => array(1), + ), +</pre> + +<h3>The introduction of get_value() and sanitize_value()</h3> +The views_handler class got two new functions: +<pre> +/** + * Get the value that's supposed to be rendered. + * + * @param $values + * An object containing all retrieved values. + * @param $field + * Optional name of the field where the value is stored. + */ +function get_value($values, $field = NULL) { + $alias = isset($field) ? $this->aliases[$field] : $this->field_alias; + if (isset($values->{$alias})) { + return $values->{$alias}; + } +} + +/** + * Sanitize the value for output. + * + * @param $value + * The value being rendered. + * @param $type + * The type of sanitization needed. If not provided, check_plain() is used. + */ +function sanitize_value($value, $type = NULL) { + switch ($type) { + case 'xss': + $value = filter_xss($value); + break; + case 'url': + $value = check_url($value); + break; + default: + $value = check_plain($value); + break; + } + return $value; +} +</pre> +These functions are meant to be used in the render() functions of field handlers, +for fetching data (usually by alias) from the $values object, and for sanitizing values. + +The abstraction of fetching data from rendering data is important because +different query backends have different ways of storing data in $values, and the field alias +is a SQL specific thing. So instead of overriding the whole render() function and copying +all of the logic there (as well as having to constantly keep up with upstream Views changes), +the backend can just override get_values(), which is significantly less code. + +Of course, different ways of fetching and displaying data might require different +ways of sanitizing it, hence the usage of the sanitize_value() function. + +Examples of converting render() field handler implementations: +<pre> +// This +$value = $values->{$this->field_alias}; +// Becomes this +$value = $this->get_value($values); + +// And this +$format = $values->{$this->aliases['format']}; +// Becomes this +$format = $this->get_values($values, 'format'); + +// Instead of this: +return check_plain($value); +// We write: +return $this->sanitize_value($value); + +// Since sanitize_value() supports different sanitization functions, this: +return filter_xss($value); +// Can become: +return $this->sanitize_value($value, 'xss'); +</pre> + + +<h3>Changed views_get_page_view</h3> +In contrast to 6.x views_get_page_view now does stores the current view, not the current page display. \ No newline at end of file diff --git a/sites/all/modules/views/help/api.html b/sites/all/modules/views/help/api.html index 6294e262080ffb3663ca8ca35b0ee69539ecb3ed..6337e8be3493a41360177aa45dde31ced259c06d 100644 --- a/sites/all/modules/views/help/api.html +++ b/sites/all/modules/views/help/api.html @@ -1,4 +1,3 @@ -<!-- $Id: api.html,v 1.5.6.2 2010/12/17 21:13:16 merlinofchaos Exp $ --> Views allows modules to describe their tables relationships to each other, as well as fields, filters, sort criteria and arguments via <strong>hook_views_data()</strong>. Whenever Views deems it necessary, this hook is called, the data aggregated together and cached. <strong>hook_views_data_alter()</strong> may also be used to modify existing data, changing other module's handlers or adding handlers to other module's tables. Views also allows modules to create new display types, style types, row styles, argument default handlers and argument validators via <strong>hook_views_handlers()</strong> and <strong>hook_views_plugins()</strong>. diff --git a/sites/all/modules/views/help/argument.html b/sites/all/modules/views/help/argument.html index 992f62d8eefab018236ec44d6e2d81412dc9e872..c4bdf2b50ba550ea44f4cb3aff08e4196395deea 100644 --- a/sites/all/modules/views/help/argument.html +++ b/sites/all/modules/views/help/argument.html @@ -1,4 +1,3 @@ -<!-- $Id: argument.html,v 1.8.6.1 2010/03/19 23:03:13 merlinofchaos Exp $ --> Arguments are input. While they often come from the URL, <strong>they don't always</strong> so please don't be shocked when they don't. Each display type may have its own source for arguments. Block displays have no source of arguments at all; they cannot pull arguments from the URL, and often require use of the default argument PHP code in order to get arguments. The argument default plugins can be used to get arguments into a block view. See "Provide default", below. In general, arguments are used to filter the view, and in that sense they have a very close relationship to filters, but that isn't necessarily true for every argument. Arguments can be used for any purpose, really; the extent of what the argument does is up to the developer of the argument, but the arguments that come with Views are almost entirely filters. diff --git a/sites/all/modules/views/help/basic-settings.html b/sites/all/modules/views/help/basic-settings.html new file mode 100644 index 0000000000000000000000000000000000000000..a063ff07a1f465211aee09980a17dee5e9ec2232 --- /dev/null +++ b/sites/all/modules/views/help/basic-settings.html @@ -0,0 +1,20 @@ +You choose the <strong>name</strong> of the current display. +This <strong>title</strong> will be displayed with the view, wherever titles are normally displayed; i.e, as the page title, block title, etc. + +When you use have many items to display, you have the choice to display them in different variants. +<dl> +<dt>Display a specified number of items</dt> +<dd>Specify the number of items to display per page and an offset. The offset is the number of items to skip. For example, if this field is 3, the first 3 items will be skipped and not displayed. +<dt>Display all items</dt> +<dd>All items will display, but you can choose an offset. The number of items to skip. For example, if this field is 3, the first 3 items will be skipped and not displayed.</dd> +<dt>Paged output, full pager</dt> +<dd>A Pager can be used to display items, with the possibility to select the next page and also the first and last page. When you have many items the query is very <i>expensive</i>. To avoid this, you can choose the mini pager. +You can also choose the number of items per page. If you enter 0, then there is no limit. Pagers also will respect an offset, if present. If multiple pagers are present on one page you may need to set this number to a higher value so as not to conflict within the ?page= array. Large values will add commas to your URLs, so avoid this if possible. Unless you're experiencing problems with pagers related to this view, you should leave this at 0. Enter the total number of pages to limit the number of values. When you leave the field empty all pages will show. +The <strong>Exposed options</strong> allow users to define their values in a exposed form when view is displayed. +You can choose "Expose items per page". With this option the user can determine how many items per page show in a view. Options for which label should display and what numberic options are also available. +Furthermore, you can choose "Expose Offset". When checked, users can determine how many items should be skipped at the beginning. You can define a label. +</dd> +<dt>Paged output, mini pager</dt> +<dd>The pager optiona are the same as for the "Paged output, full pager" but you have no possibility to jump to the last or first items. </dd> +</dl> +Normally, all views are created with <strong>unrestricted access</strong>. This means any site visitor can see the views. Please consider this when you make a view with a menu link and private data as output. You have by default two options: "Permission" and "Role". If you choose permission, you get a list of all permissions. Only users with the selected permission flag will be able to access this display. If you choose role, you get all roles as checkboxes. Only the checked roles will be able to access this display. Note that users with "access all views" can see any view, regardless of role. diff --git a/sites/all/modules/views/help/demo-video.html b/sites/all/modules/views/help/demo-video.html new file mode 100644 index 0000000000000000000000000000000000000000..43c024033f031fe53a0576cc7f1b059115a62f1a --- /dev/null +++ b/sites/all/modules/views/help/demo-video.html @@ -0,0 +1,5 @@ +<p>Here are some links to demonstration videos. It will get you started working with Views.</p> + +<p><a href="http://drupal.org/node/248766">Views 2 (Drupal 6) Demonstration Video - Drupal Handbook</a></p> + +<p><a href="http://nodeone.se/blogg/taming-the-beast-learn-views-with-nodeone">NodeOne's initial screencasts on the Views 3 UI.</a> diff --git a/sites/all/modules/views/help/display-attachment.html b/sites/all/modules/views/help/display-attachment.html index 3a682eddee9277c2af502447c917930dcb187413..9963b25e129aba1fb48a45d7fa5627a7f9112e5e 100644 --- a/sites/all/modules/views/help/display-attachment.html +++ b/sites/all/modules/views/help/display-attachment.html @@ -1,2 +1 @@ -<!-- $Id: display-attachment.html,v 1.2 2008/04/29 00:35:07 merlinofchaos Exp $ --> Attachment displays are 'attached' to another display in the same view. When the display is visited, the attached display will also be rendered and may be placed before, after or both before and after the original display. Attachment displays are often useful for displaying an argument summary view along with a page display that accepts arguments. This can be used to provide a kind of glossary. \ No newline at end of file diff --git a/sites/all/modules/views/help/display-block.html b/sites/all/modules/views/help/display-block.html index 713c6ef88e88fcfc1a54857d89fb3ee52abcf557..158cad07377b73b6e860caf2562e6784e33ccb9f 100644 --- a/sites/all/modules/views/help/display-block.html +++ b/sites/all/modules/views/help/display-block.html @@ -1,4 +1,3 @@ -<!-- $Id: display-block.html,v 1.5 2008/10/14 17:06:02 merlinofchaos Exp $ --> Block displays will show up on your blocks administration page. Once a block display is created and saved, it can be enabled and positioned in your theme by visiting <strong>administer >> site building >> blocks</strong> and selecting it from the list. Blocks <strong>do not</strong> accept arguments from any source; the only way to get arguments to a block is to provide defaults to it, possibly via the PHP Code default setting. diff --git a/sites/all/modules/views/help/display-default.html b/sites/all/modules/views/help/display-default.html index c50b50328866d41dbcd943a44863c5003b6c0b71..309690aaeb4a46dc31548836705b578fcdf677aa 100644 --- a/sites/all/modules/views/help/display-default.html +++ b/sites/all/modules/views/help/display-default.html @@ -1,4 +1,3 @@ -<!-- $Id: display-default.html,v 1.2 2008/04/29 00:35:07 merlinofchaos Exp $ --> The default display is primarily a display to store settings, and isn't actually used anywhere within the Views system. It is possible for external programs to use the default display, but if they do they will (hopefully) tell you which display they will be working with. The default display is also a convenient display to use to embed into your site using PHP snippets; this is useful, for example, in node content, but this is something that should generally only be done by administrators. In general, you probably want to add either a <a href="topic:views/display-page">page display</a> or a <a href="topic:views/display-block">block display</a>. diff --git a/sites/all/modules/views/help/display-feed.html b/sites/all/modules/views/help/display-feed.html index 690d640323b79badfd5a60f9afe37e09a5ce95f0..a5c0a65510810a016614c3771b1f24785606469e 100644 --- a/sites/all/modules/views/help/display-feed.html +++ b/sites/all/modules/views/help/display-feed.html @@ -1,2 +1 @@ -<!-- $Id: display-feed.html,v 1.2 2008/05/05 05:09:36 merlinofchaos Exp $ --> A feed display allows you to attach an RSS feed to a view. \ No newline at end of file diff --git a/sites/all/modules/views/help/display-page.html b/sites/all/modules/views/help/display-page.html index 1ea3338a2a5372d88a1bbda269b2085865e1eff9..e54b3b97fd357b39990bb33596cfbfac5e9f91df 100644 --- a/sites/all/modules/views/help/display-page.html +++ b/sites/all/modules/views/help/display-page.html @@ -1,6 +1,8 @@ -<!-- $Id: display-page.html,v 1.3.6.1 2010/03/25 20:31:11 merlinofchaos Exp $ --> Page displays have a <a href="topic:views/path">path</a> and an optional <a href="topic:views/menu">menu</a> component. Page displays will be the primary content for the page, meaning they will be displayed in the main content area when you visit the URL that corresponds to the path. Page displays take their arguments from the URL. You can embed arguments into the URL using %; in previous versions of Views, this was '$arg'. For example, 'node/%/foo' will accept URLs such as 'node/1/foo'. -Please remember that using a % placeholder makes the argument required. If you wish to have an optional argument, simply omit the % from the path. I.e. using "page/%" as the path requires an argument and visiting 'http://www.example.com/page' will not trigger the view. \ No newline at end of file +Please remember that using a % placeholder makes the argument required. If you wish to have an optional argument, simply omit the % from the path. I.e. using "page/%" as the path requires an argument and visiting 'http://www.example.com/page' will not trigger the view. + +If you intend to embed a view manually into another view, it is recommended that the page display not be used for embedding. Select a different display type to embed. + diff --git a/sites/all/modules/views/help/display.html b/sites/all/modules/views/help/display.html index df1e36660db92f68e0b11adb5c3a437a993538ce..5eca6fd9a50947835e8d29b5239d8c7f9dad2440 100644 --- a/sites/all/modules/views/help/display.html +++ b/sites/all/modules/views/help/display.html @@ -1,4 +1,3 @@ -<!-- $Id: display.html,v 1.2.6.2 2010/12/09 01:06:33 merlinofchaos Exp $ --> Displays tell Views where the output should go. By adding a display to a View, you can have your view appear as a page, or as a block, or even as an attachment to a different display on the view. Each display can have its own settings, but when created, a display will take all of its <em>basic settings</em> from the <strong>default display</strong> which all Views must have. For most settings, there is an <a href="topic:views/overrides">override</a> button that will override that single setting for the current display. Overridden settings will have a mark in the summary for that display. All 'default display settings' are shown in the other displays in '<i>italic</i>'. When you override a setting, then it is shown 'normal'. diff --git a/sites/all/modules/views/help/embed.html b/sites/all/modules/views/help/embed.html index f66ecc4c82afaeffc301e7fe918eee43f2c26bc4..e39fbf5cd232b98e32d258c5ef14d09877a6a8bd 100644 --- a/sites/all/modules/views/help/embed.html +++ b/sites/all/modules/views/help/embed.html @@ -1,4 +1,3 @@ -<!-- $Id: embed.html,v 1.1 2008/06/13 00:56:19 merlinofchaos Exp $ --> You can easily embed the results of a view into other parts of your site; either with code as a module, or in nodes or blocks as snippets. The easiest way is to use the function <strong>views_embed_view()</strong>: diff --git a/sites/all/modules/views/help/empty-text.html b/sites/all/modules/views/help/empty-text.html new file mode 100644 index 0000000000000000000000000000000000000000..0a085938ceb03e851c2269220841bb9a566b8a02 --- /dev/null +++ b/sites/all/modules/views/help/empty-text.html @@ -0,0 +1,3 @@ +The Emtpy Text content will be displayed when you choose the option <em>Display empty text</em> under the <strong>Arguments</strong> labelled <em>Action to take if argument is not present</em>. + +By default you can choose one or more text areas. diff --git a/sites/all/modules/views/help/example-author-block.html b/sites/all/modules/views/help/example-author-block.html index e8c11e13eb124eddd473cbd7be5dc12ce50d8d5a..41ff071dd824e9c6b09f564696e3077bb981778c 100644 --- a/sites/all/modules/views/help/example-author-block.html +++ b/sites/all/modules/views/help/example-author-block.html @@ -1,10 +1,9 @@ -<!-- $Id: example-author-block.html,v 1.1.6.2 2010/08/13 22:22:28 merlinofchaos Exp $ --> <p>In this example you will create a context-sensitive block that shows the titles of recent blog entries by an author when viewing one of their posts. This will demonstrate using Views <em>arguments</em> to dynamically filter a view's contents at display time.</p> <p>Before working through this example, enable the <strong>Blog</strong> module and populate some entries from a few different users.</p> <h3>Creating the View</h3> -<p>The first step is creating a view for our recent blog entries block. Because the block will show the titles of blog entries, this view is considered a "Node" type. Go to <a target="_blank" href="/admin/structure/views/add">add new view</a>, enter the following properties, and click <strong>Next</strong>:</p> +<p>The first step is creating a view for our recent blog entries block. Because the block will show the titles of blog entries, this view is considered a "Node" type. Go to <a target="_blank" href="base_url:admin/structure/views/add">add new view</a>, enter the following properties, and click <strong>Next</strong>:</p> <dl> <dt>View name</dt> @@ -46,7 +45,7 @@ <li>The <strong>Defaults: Configure Argument User: Uid</strong> settings page has a lot going on, but only a few things that need our attention.</li> <li>The <strong>Title</strong> field here, unlike the Title field under <em>Basic Settings</em>, can be based upon the context that the view is being displayed in. Change the title to 'Recent entries by %1.' %1 will later be expanded to the user's name (based on the User: Uid argument) when the view is displayed.</li> <li>Under <strong>Action to take if argument is not present</strong>, there are a variety of options, ranging from displaying a 404 or a 403 page to simply displaying all values in the view. In our case, if an argument isn't specified (which it won't be, since this view will be displayed in a sidebar block, not as a page with its own URL), we want to give it a default one to act on. Select <em>Provide default argument</em>.</li> -<li>Assuming JavaScript is enabled in your browser, you should now get another selection for <strong>Default argument type</strong>. Select <em>User ID from URL</em>. This will cause Views to first see if it can figure out a user ID from the current URL (for example, user/1). If it can't, it will instead check to see if the current page is a node page (such as node/42) and, if so, take the user ID from the node's author field instead.</li> +<li>Assuming JavaScript is enabled in your browser, you should now get another selection for <strong>Default argument type</strong>. Select <em>User ID from URL</em>, which will then provide a new option, <em>Also look for a node and use the node author</em>. Select it. This will cause Views to first see if it can figure out a user ID from the current URL (for example, user/1). If it can't, it will instead check to see if the current page is a node page (such as node/42) and, if so, take the user ID from the node's author field instead.</li> <li><strong>Validator options</strong> provide a useful way to control what kind of arguments your view will accept. Select <em>User</em> as the <strong>Validator</strong>. By default, changing this setting will check the incoming argument and ensure it's a valid user ID; if not, the view will be hidden from the page.</li> <li>Once you have changed the argument's title, default argument, and validator options, click <strong>Update</strong> to save your changes.</li> <li>You'll notice that now the Live preview no longer shows anything. Did we just break the view? Fortunately, no. It's merely abiding by our wishes to hide itself if there is no valid user ID given to it. Try entering a '1' in the <strong>Arguments</strong> box and clicking <strong>Preview</strong>. You should now see a list of only user 1's blog entries.</li> @@ -59,15 +58,15 @@ <li>In the first column, under <strong>Defaults</strong>, there is a select box containing entries such as <em>Page</em>, <em>Feed</em>, and, yes, <em>Block</em>! Select <em>Block</em> and click <strong>Add display</strong>.</li> <li>There's not much else to do here as far as Views is concerned. Under <strong>Block settings</strong>, click the <em>None</em> link next to <strong>Admin</strong> and fill in a description for the block in the administrative interface, such as: 'Recent blog entries by author.' and click <strong>Update</strong>.</li> <li>Save your work by clicking the <strong>Save</strong> button at the bottom of the Views interface. You should receive a message that the view has been saved.</li> -<li>Next, navigate to the <a target="_blank" href="/admin/build/block">blocks interface</a> and drag the 'Recent blog entries by author' block to the right sidebar region (or similar) and click <strong>Save blocks</strong>.</li> -<li>You'll notice this appeared to do nothing. No block shows in the sidebar. But remember, we are looking at an adminitrative page; we are not looking at a page that would provide a user ID context. Navigate to the <a target="_blank" href="/blog">main blog listing</a> and click on an entry there. You should now see a sidebar block, titled something like "Recent entries by admin," with a list of blog entries beneath it.</li> +<li>Next, navigate to the <a target="_blank" href="base_url:admin/structure/block">blocks interface</a> and drag the 'Recent blog entries by author' block to the right sidebar region (or similar) and click <strong>Save blocks</strong>.</li> +<li>You'll notice this appeared to do nothing. No block shows in the sidebar. But remember, we are looking at an adminitrative page; we are not looking at a page that would provide a user ID context. Navigate to the <a target="_blank" href="base_url:blog">main blog listing</a> and click on an entry there. You should now see a sidebar block, titled something like "Recent entries by admin," with a list of blog entries beneath it.</li> </ol> <h3>Finishing touches</h3> <p>There are still a few remaining things to do before our view is complete. For example, we said that the block was to show <em>recent</em> blog entries, but instead it's showing them in the order they were entered, with oldest on top. Additionally, even unpublished entries are showing in the list currently.</p> <ol> -<li>Return to the <a target="_blank" href="/admin/structure/views/edit/recent_blog_entries">recent_blog_entries view edit page</a>.</li> +<li>Return to the <a target="_blank" href="base_url:admin/structure/views/view/recent_blog_entries">recent_blog_entries view edit page</a>.</li> <li>Add an additional filter by clicking the <strong>+</strong> icon in the <strong>Filters</strong> section in the fourth column.</li> <li>Change <strong>Groups</strong> to <em>Node</em> and select <em>Node: Published</em>. Click <strong>Add</strong>.</li> <li>Under the <strong>Published</strong> selection, choose <em>Yes</em> and click <strong>Update</strong>.</li> diff --git a/sites/all/modules/views/help/example-bulk-export.html b/sites/all/modules/views/help/example-bulk-export.html new file mode 100644 index 0000000000000000000000000000000000000000..33ce28e9e716e0c773c1e39f785e265eea00d552 --- /dev/null +++ b/sites/all/modules/views/help/example-bulk-export.html @@ -0,0 +1,44 @@ +This documentation focuses on the bulk export and version control functionality of the Views module. The following steps document how to export multiple views at once and create a module from the exported code that will allow you to revert any subsequent changes to your views. + +Assumptions: +- You have views you want to bulk export; we'll call them <em>myView1</em> and <em>myView2</em> +- You know how to install and enable a module + + +<ol> +<li><h3>Modules you will need</h3> +<p>Install <a href="http://drupal.org/project/views" target="_blank">Views</a> and <a href="base_url:admin/build/modules" target="_blank">enable</a> the following modules: Views, Views exporter, Views UI</p> +</li> +<li><h3>Evaluate the Current State of Things</h3> +<p>Navigate to the <a href="base_url:admin/build/views" target="_blank">Views Administration page</a>. You should have <em>Edit | Export | Clone | Delete</em> options next to <em>myView1</em> and <em>myView2</em>. Once we're done, "Delete" will become "Revert"!</p> +</li> +<li><h3>Bulk Export Your Views</h3> + <ol> + <li>Click <strong>Tools</strong> > <strong>Bulk Export</strong> to navigate to the <a href="base_url:admin/build/views/tools/exports" target="_blank">Bulk Export page</a> to export <em>myView1</em> and <em>myView2</em>.</li> + <li>Check the boxes to the left of <em>myView1</em> and <em>myView2</em></li> + <li>Choose a module name: my_views</li> + <li>Click Export</li> + </ol> +</li> +<li><h3>Create a Module from the Exported Views</h3> +<p>The results of the export should now be in front of you. Specifically, the results page should be composed of three code-containing regions. This code and the following steps are all you need to create a module that will allow you to revert your views to the state they were in when you exported them. + <ol> + <li>Create a directory called <em>my_views</em> within your sites/all/modules directory.</li> + <li>Create the following files, paste in the appropriate code, and place them into the <em>my_views</em> directory:</li> + <ul> + <li>my_views.info</li> + <li>my_views.module (add a <?php tag at the beginning of this file!)</li> + <li>my_views.views_default.inc (add a <?php tag at the beginning of this file!)</li> + </ul> + </ol> +</li> +<li><h3>Clear the cache</h3> +<p>Just to be safe. Navigate to the <a href="base_url:admin/settings/performance" target="_blank">Performance Administration page</a> and <strong>Clear cached data</strong>.</p> +</li> +<li><h3>Enable the Module Containing Exported Views</h3> +<p>Navigate to the <a href="base_url:admin/build/modules" target="_blank">Modules Administration page</a> and enable <em>my_views Export Module</em>. <strong>Save</strong>.</p> +</li> +<li><h3>Verify Presence of Reversion Option for Exported Views</h3> +<p>Navigate to the <a href="base_url:admin/build/views" target="_blank">Views Administration page</a>. The right of <em>myView1</em> and <em>myView2</em> should now read <em>Edit | Export | Clone | Revert</em>. Congratulations, you now have version control in place for your exported views!</p> +</li> +</ol> diff --git a/sites/all/modules/views/help/example-recent-stories.html b/sites/all/modules/views/help/example-recent-stories.html index 57f373a0ecba9f99cbff989b8e9c42c35f1a6041..7e21324d3dfcf35c2862c18be6836555951d1f59 100644 --- a/sites/all/modules/views/help/example-recent-stories.html +++ b/sites/all/modules/views/help/example-recent-stories.html @@ -1,4 +1,3 @@ -<!-- $Id: example-recent-stories.html,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ --> In this example you will create a list of nodes of the content type "story", to be shown in a block. Through this step-by-step process, you will become familiar with some basic steps in creating a view, and familiarize yourself with the Views User Interface. <ol> @@ -54,5 +53,5 @@ In this example you will create a list of nodes of the content type "story", to <li><h3>Saving the view</h3> <p>Click <strong>Save</strong> to save your work.</p></li> <li><h3>Instructing Drupal to show the block</h3> -<p>Finally, you should tell Drupal to show this block. Configure your block by going to <a target="_blank" href="base_url:admin/build/block">admin/build/block</a>. Locate the block in the list: it is labeled <em>Recent Stories</em>. Place this block in a region and click <strong>Save</strong>. You may click <em>Configure</em> to set a different title, to determine which roles can view the block, and on which pages it appears; If you want your block on the front page only, enter '<front>'.</p></li> +<p>Finally, you should tell Drupal to show this block. Configure your block by going to <a target="_blank" href="base_url:admin/structure/block">admin/structure/block</a>. Locate the block in the list: it is labeled <em>Recent Stories</em>. Place this block in a region and click <strong>Save</strong>. You may click <em>Configure</em> to set a different title, to determine which roles can view the block, and on which pages it appears; If you want your block on the front page only, enter '<front>'.</p></li> </ol> diff --git a/sites/all/modules/views/help/example-user-feed.html b/sites/all/modules/views/help/example-user-feed.html index 58e8ab352df3bb89a0f5abb032aaa8d84a022502..6a28d8f14e2f4b84b55ce41051277a0c80302aa6 100644 --- a/sites/all/modules/views/help/example-user-feed.html +++ b/sites/all/modules/views/help/example-user-feed.html @@ -1,4 +1,3 @@ -<!-- $Id: example-user-feed.html,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ --> <p>In this example you will create a <em>Feed display</em> to show nodes by individual users, dynamically selected through the URL. You will become familiar with the Views 2 interface, as well as learn how to use an argument to pull in a user name and use it in a dynamically created path.</p> <p>A <em>feed</em> is a data format that places your site's content into a file that can be read and displayed by news reader programs. When visiting a site, you may notice a small <a href="http://drupal.org/misc/feed.png">RSS transmission icon</a>, whereby clicking on it, you can subscribe to the site's most recent content. This makes it easier for your visitors to keep up to date with your website. You can also use this format to aggregate information into other sites. For more information, please watch a video from Common Craft about <a href="http://www.commoncraft.com/rss_plain_english">RSS in plain English</a>.</p> <p>Note, Drupal automatically creates a feed for your website, but you may want to create feeds with specific information. In this case, a list per user. </p> @@ -6,7 +5,7 @@ <li> <h3>Creating a new view </h3> <ol> - <li>Go to <a target="_blank" href="/admin/structure/views/add">add new view</a>. Give it the name 'user_feed', description 'A feed of user nodes.', tag 'users', type 'Node' and click Next.</li> + <li>Go to <a target="_blank" href="base_url:admin/structure/views/add">add new view</a>. Give it the name 'user_feed', description 'A feed of user nodes.', tag 'users', type 'Node' and click Next.</li> </ol> </li> <li><strong>About the Interface.</strong> You have been brought to the Views User Interface. As you start, you are editing the "Default" options for the view. In the 1st column on the left- you can see the pull-down menu offers 'Feed', for example, to select settings specific only to RSS views. In the remaining columns, you will be able to add or change options by clicking on links or icons. These options appear below this main area. Most likely, you will need to scroll to see the options appear. As you make changes, these options will appear in bold until you save your view.</li> diff --git a/sites/all/modules/views/help/example-users-by-role.html b/sites/all/modules/views/help/example-users-by-role.html index 1d8033eb4d00b0bf2d0e480b10451719a5c75d09..f5228be3ba843a7088b5b454bce1d121cfcf281b 100644 --- a/sites/all/modules/views/help/example-users-by-role.html +++ b/sites/all/modules/views/help/example-users-by-role.html @@ -1,4 +1,3 @@ -<!-- $Id: example-users-by-role.html,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ --> In this example you will create a page view listing users on your site. Through this step-by-step process, you will become familiar with some basic steps in creating a view, and familiarize yourself with the Views User Interface. <ol> diff --git a/sites/all/modules/views/help/exposed-form.html b/sites/all/modules/views/help/exposed-form.html new file mode 100644 index 0000000000000000000000000000000000000000..ca06e9fba85fcecd492120246d163aabb0af712f --- /dev/null +++ b/sites/all/modules/views/help/exposed-form.html @@ -0,0 +1,24 @@ +This is used when you want to position the exposed form in the sidebar or anywhere else, but not with the view. Instead, a block will be made available to the Drupal block administration system, and the exposed form will appear there. Note that this block must be enabled manually, Views will not enable it for you. +To do this select "Exposed form in block: Yes" and choose one option from "Exposed form style". +<dl> +<dt>Basic</dt> +<dd>When you expose a form and the view is loaded, no filter is selected and all items will displayed.</dd> +<dt>Input required</dt> +<dd>When you expose a form and the view is loaded, only the filter settings are shown. After you select one filter and hit the apply button, the items willi be shown.</dd> +</dl> + +You have several options to customize the appearance of the exposed forms: +<dl> +<dt>Submit button text</dt> +<dd>Text to display in the submit button of the exposed form.</dd> +<dt>Include reset button</dt> +<dd>If checked the exposed form will provide a button to reset all the applied exposed filters</dd> +<dt>Reset button label</dt> +<dd>Text to display in the reset button of the exposed form.</dd> +<dt>Exposed sorts label</dt> +<dd>Text to display as the label of the exposed sort select box.</dd> +<dt>Ascending</dt> +<dd>Text to use when exposed sort is ordered ascending.</dd> +<dt>Descending</dt> +<dd>Text to use when exposed sort is ordered descending.</dd> +</dl> diff --git a/sites/all/modules/views/help/field.html b/sites/all/modules/views/help/field.html index 83e42aee5d28f44a2015da8883659d8f5c56aaba..65aa3f654b3519b7f17fcbd9ca3ed5e1e1626fb0 100644 --- a/sites/all/modules/views/help/field.html +++ b/sites/all/modules/views/help/field.html @@ -1,6 +1,11 @@ -<!-- $Id: field.html,v 1.2 2008/05/15 19:17:11 merlinofchaos Exp $ --> Fields are the individual pieces of data being displayed. Adding the fields <em>Node: Title</em>, <em>Node: Type</em>, and <em>Node: Post date</em> to a node view, for example, includes the title, content type and creation date in the displayed results). -Fields may not appear on every display, because not all style plugins actually use fields. For example, the 'node' row plugin simply displays the node through Drupal's normal mechanisms, and fields are not involved. +Fields may not appear on every display, because not all style plugins actually use <a href="topic:views/style-fields">fields</a>. For example, the '<a href="topic:views/style-node">node</a>' <a href="topic:views/style-row">row plugin</a> simply displays the node through Drupal's normal mechanisms, and fields are not involved. +For the most part, the field settings should be self explanatory. Fields will appear in the order that they are arranged in, and they will usually appear with the label they are given. + +If you add new cck fields you will find them under the Group "Content". Search for the field name. With new modules the list of groups will grow. Modules can add new items with the <em>hook_views_data()</em> hook. + +If you do not find a field, consider whether or not you need a <a href="topic:views/relationship">Relationship</a>. + ++You can override the entire field section - see <a href="topic:views/overrides">here</a> for more information. -For the most part, the field settings should be self explanatory. Fields will appear in the order that they are arranged in, and they will usually appear with the label they are given. \ No newline at end of file diff --git a/sites/all/modules/views/help/filter.html b/sites/all/modules/views/help/filter.html index 447862e361e00cbb336ad8cfd6f5569cdec5d802..704ef2f6e19b9f146ef246b0d8ad0b9e9c308b02 100644 --- a/sites/all/modules/views/help/filter.html +++ b/sites/all/modules/views/help/filter.html @@ -1,4 +1,3 @@ -<!-- $Id: filter.html,v 1.3 2009/02/20 20:46:48 merlinofchaos Exp $ --> Filters are used to reduce the data set that Views provides. That is to say, without any filters applied, Views will return all of your content. You don't want that, so at least some filters must be used. Some very commonly used filters: @@ -10,4 +9,10 @@ Some very commonly used filters: <li> The 'Node: Post date' filter can be used to show only nodes posted before, after, or between a range of dates.</li> </ul> -The above list is only a tiny fraction of the filters available in Views, referenced here to give an idea of the kinds of tasks filters can accomplish. +The above list is only a tiny fraction of the filters available in Views, referenced here to give an idea of the kinds of tasks filters can accomplish. When you do not find a filter type, you may need to choose a <a href="topic:views/relationship">Relationship</a> before the expected filter will show, or to install a new module that contains the requested filter. + +When you click the Rearrange Icon you can first rearrange your filters, easily delete filters and select an operator: "AND" or "Or". By default the "AND" operator is selcted. At the lower right of the window is the new button "Add new group"r. When you click on it, you can drag and drop an individual filter to the new group "Group 1". For this new group and the default group you can select the "Group operator": "And" or "Or". To remove a group, remove all filters and click the "Remove group 1" button. + +When you want that the user to select their own filter, you can expose the filter. A selection box will show for the user and they will be able to select one item. After that the view will reload and only the selected item will be displayed. You can also choose to expose the selection to a block, see <a href="topic:views/exposed-form">here</a>. + +You can override the complete filter section - see <a href="topic:views/overrides">here</a> for more information. diff --git a/sites/all/modules/views/help/getting-started.html b/sites/all/modules/views/help/getting-started.html index a29a2c6ab7c82094ffbece35ee5821aac1193e79..bb5ac2cbc9062febb5ef6f1323cde32498f3171d 100644 --- a/sites/all/modules/views/help/getting-started.html +++ b/sites/all/modules/views/help/getting-started.html @@ -1,4 +1,3 @@ -<!-- $Id: getting-started.html,v 1.8 2008/10/14 18:20:25 merlinofchaos Exp $ --> For those new to Views, it can be a complex system that appears totally overwhelming. The good news is that the UI is designed to compartmentalize everything; this means that for the most part, you can ignore the parts you're not interested in. Start small and build your way up. Because of this, the edit UI can seem overwhelming at first, but there are really just a few things you <strong>have</strong> to know. The rest you can find through exploration. The Views Edit UI image, below, gives an overview of what you'll find on the edit UI. @@ -19,5 +18,7 @@ Notes: 5) You can safely leave a view page to go and do other things. If you come back, the view will still be there, stored in a cache. Keep in mind, however, that while you do this, that view is <em>locked</em>, meaning another user cannot edit this view without breaking the lock. Breaking the lock will discard your changes. +6) Don't forget permissions. Views installs with two default permissions. Users with access all views permissions will have access to all views. Users with administer views permissions will be able to edit and change views. If you are trying to restrict access based on role, make sure that the role does not have access all views checked. + It helps to have something particular in mind that you want to accomplish when using Views. Here are a couple of ideas and a brief sketch of how to accomplish what you want. diff --git a/sites/all/modules/views/help/header.html b/sites/all/modules/views/help/header.html new file mode 100644 index 0000000000000000000000000000000000000000..bc31b490e1d3e849906bbf9803ca769505fdd597 --- /dev/null +++ b/sites/all/modules/views/help/header.html @@ -0,0 +1,3 @@ +In this section you can choose one or more areas, by default a text area, which will display above the view output. + +You can override the complete header section - see <a href="topic:views/overrides">here</a> for more information. diff --git a/sites/all/modules/views/help/menu.html b/sites/all/modules/views/help/menu.html index 208d52d1f0eeacc9f97f085a19317e87339c3c84..bb818a39b08d1f62c9f458e3a0a63a4e4d5ad027 100644 --- a/sites/all/modules/views/help/menu.html +++ b/sites/all/modules/views/help/menu.html @@ -1,4 +1,3 @@ -<!-- $Id: menu.html,v 1.2.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ --> Page displays can hook into the Drupal menu system and provide <strong>menu links</strong> that will appear in the Navigation system as well as <strong>tabs</strong> that can be used to keep Views next to each other. For simple <strong>menu links</strong>, there is very little you need to do; simply select 'Normal menu entry' and fill in the text for the title. This will appear in the Navigation menu by default; you will need to visit the menu administration page to move this to another menu. diff --git a/sites/all/modules/views/help/new.html b/sites/all/modules/views/help/new.html index 606f6a614b45015d5fb1d6572dfc997d28d95b9b..f33bb8ff5537c0d0f35f530302be3e0fc5e9b11a 100644 --- a/sites/all/modules/views/help/new.html +++ b/sites/all/modules/views/help/new.html @@ -1,4 +1,3 @@ -<!-- $Id: new.html,v 1.5.6.1 2010/10/12 21:35:03 merlinofchaos Exp $ --> Views 2 is the newest major release of Views and it is specifically coded for Drupal 6. Views 2 retains all of the core functionality of Views 1, together with a completely revamped user interface and a large set of new features which greatly expand upon the original feature-set of Views 1. This document is a side-by-side comparison of Views 1 versus Views 2 from a user's perspective, detailing the UI changes, some new ways to perform old tasks, the cool new features of Views 2 and how these features can be used to address some of the shortcomings of Views 1. <h2>Admin interface</h2> diff --git a/sites/all/modules/views/help/other-help.html b/sites/all/modules/views/help/other-help.html new file mode 100644 index 0000000000000000000000000000000000000000..65d93e2b630bc488886275656f4cdf10bf826dca --- /dev/null +++ b/sites/all/modules/views/help/other-help.html @@ -0,0 +1,10 @@ +There are many tutorials, podcasts, and a few books on Views that you can turn to for further help. + +Books: +<a href="http://www.drupal-building-blocks.com">Drupal Building Blocks</a> is the Views' author book; check <a href="http://www.drupal.org/books">the Drupal.org books page</a> for a fairly comprehensive list. + +Videos: +See <a href="topic:views/demo-video">this page.</a> + +Google. Many Drupal shops put together helpful tutorials and publish them to Drupal Planet, not to mention the countless users of Views who do it for the community. + diff --git a/sites/all/modules/views/help/overrides.html b/sites/all/modules/views/help/overrides.html index 59b68a9ba4e8eae02d1e9b6efbe3c53fb36c8cc1..586f375bcfc70befb7cd98f2fd58cf06547b2bc5 100644 --- a/sites/all/modules/views/help/overrides.html +++ b/sites/all/modules/views/help/overrides.html @@ -1,7 +1,7 @@ -<!-- $Id: overrides.html,v 1.2.6.1 2010/03/10 20:00:30 merlinofchaos Exp $ --> -If an item is <strong>using defaults</strong> then it is using values from the <strong>default display</strong>. <em>IMPORTANT NOTE:</em> If you modify this value, you are modifying the <strong>default display</strong> and thus modifying for all displays that are using default values. +If an item is <strong>using defaults</strong> then it is using values from the <strong>default <a href="topic:views/display">display</a></strong>. <em>IMPORTANT NOTE:</em> If you modify this value, you are modifying the <strong>default <a href="topic:views/display">display</a></strong> and thus modifying for all displays that are using default values. -If that is not what you intend, you must click the <strong>override</strong> button. Once overridden, that display now has its own version of the value; modifying it will not modify it for other displays. +If that is not what you intend, you must click the <strong>override</strong> button. Once overridden, that display now has its own version of the value; modifying it will not modify it for other displays. You can override in the settings of the non-default display when you are clicking on the header of the section or on the rearrange button. -For <strong>Relationships</strong>, <strong>arguments</strong>, <strong>fields</strong>, <strong>sort criteria</strong>, and <strong>filters</strong>, each of these must be overridden as a group! In other words, you cannot override a single filter, but instead must override all filters. A message will appear on the item to let you know what its status is, but you can only change the status by clicking on the header or the rearrange button for that item. +For <a href="topic:views/relationship">relationships</a>, <a href="topic:views/argument">arguments</a>, <a href="topic:views/field">fields</a>, <a href="topic:views/sort">sort criterias</a>, and <a href="topic:views/filter">filters</a>, each of these must be overridden as a group! In other words, you cannot override a single filter, but instead must override all filters. A message will appear on the item to let you know what its status is, but you can only change the status by clicking on the header or the rearrange button for that item. + diff --git a/sites/all/modules/views/help/path.html b/sites/all/modules/views/help/path.html index 2c4404e0e10cf36c0edc213b532bcdff087f3ea8..142534cba4da486d46e6732524d0ade6ab399eb4 100644 --- a/sites/all/modules/views/help/path.html +++ b/sites/all/modules/views/help/path.html @@ -1,4 +1,3 @@ -<!-- $Id: path.html,v 1.3 2008/06/25 19:26:01 merlinofchaos Exp $ --> If a display has a path that means that it can be retrieved directly by calling a URL as a first class page on your Drupal site. Any items after the path will be passed into the view as arguments. For example, if the path is <strong>foo/bar</strong> and a user visits <strong>http://www.example.com/foo/bar/baz/beta</strong>, 'baz' and 'beta' will be given as arguments to the view. These can be handled by adding items to the <a href="topic:views/arguments">arguments</a> section. You may also use placeholders in your path to represent arguments that come in the middle. For example, the path <strong>node/%/someview</strong> would expect the first argument to be the second part of the path. For example, <strong>node/21/someview</strong> would have an argument of '21'. diff --git a/sites/all/modules/views/help/performance-views-vs-displays.html b/sites/all/modules/views/help/performance-views-vs-displays.html new file mode 100644 index 0000000000000000000000000000000000000000..9f02a5a908b5b96668621b722cbb90364daa2cf4 --- /dev/null +++ b/sites/all/modules/views/help/performance-views-vs-displays.html @@ -0,0 +1,5 @@ +<p>Multiple displays in one view is <strong>appropriate</strong> when they are <strong>fundamentally similar</strong> and are <strong>sharing quite a fair amount of data</strong>. For example, showing upcoming events in either blocks or page and sorting it according to either event name or date of the event will be appropriate to be implemented by four displays (two blocks and two pages) in one view.</p> + +<p>In the other hand, having multiple displays in one view that contains <strong>mostly overrides</strong> will be a burden to the system and will be hard to maintain. The effect of having only couple of such displays has negligible performance difference. It will be magnified when the number of displays in one view is large.</p> + +<p>Another consideration is the use of Views, especially when using multiple views in conjunction with other modules such as Panels. It is entirely possible to have many views on a page due to Panels' ability to contain a view in each pane. Some people have mistaken this as a problem on Panels' or Views' part, but realistically it is likely to be the sheer number of queries that are being run during page render. </p> diff --git a/sites/all/modules/views/help/performance.html b/sites/all/modules/views/help/performance.html new file mode 100644 index 0000000000000000000000000000000000000000..e393452e11a0a961d5b24149fc9bd24105f57f0e --- /dev/null +++ b/sites/all/modules/views/help/performance.html @@ -0,0 +1 @@ +<p>Views module is optimized for certain practices. To ensure Views has its best performance, please follow these best practices for Views.</p> diff --git a/sites/all/modules/views/help/relationship.html b/sites/all/modules/views/help/relationship.html index b37ce143060038ffcc212f506bb1182e02310476..47a659d1e9a815986996ddc6befcdf2b9816361b 100644 --- a/sites/all/modules/views/help/relationship.html +++ b/sites/all/modules/views/help/relationship.html @@ -1,4 +1,3 @@ -<!-- $Id: relationship.html,v 1.6 2009/02/20 20:46:48 merlinofchaos Exp $ --> Relationships allow you to expand the query to include objects other than the base query. This is actually made more difficult to understand by the fact that Views actually includes a few relationships by default, and doesn't tell you they're there. For historical reasons, it would be inconvenient to remove these default relationships. When relationships are present, all fields (including relationships) will gain a new form item to let you select which relationship they will use. They will default to using no relationship at all. The main example of the relationship that is there by default is the node --> user relationship; every node has an author, and if a node is in the query, the user who wrote that node is automatically made available. [Note: the author considers it an error that this relationship is automatic, but by the time it was realized this was in error, it was too late to change it.] @@ -12,3 +11,5 @@ A 'comment' view contains the relationships 'Comment: node' and 'Comment: user'. When you add the "User: name" field, you will be presented with a select box. Either the node relationship or the user relationship must be selected, because there are two possible user names in the view to choose from. Another example of relationships involves the <strong>Files</strong> table. In Drupal, files are related to users, but files are not necessarily related to nodes. However, the upload.module allows some files to be attached to nodes. The only way for Views to deal with this discrepancy is with relationships. When creating a 'node' view, it's possible to add an uploaded files relationship to get file data for nodes that were attached with the upload module. It is also possible to go the other way; from a files view you may add a relationship via the Upload table to view information about the node. + +You can override the complete relationship section - see <a href="topic:views/overrides">overrides</a> for more information. diff --git a/sites/all/modules/views/help/sort.html b/sites/all/modules/views/help/sort.html index 645f2dd84fd7f4119afc70fdcf7078f6b03f801f..9a5640fc1fe99070eb6b0f16c59d5653319a4b31 100644 --- a/sites/all/modules/views/help/sort.html +++ b/sites/all/modules/views/help/sort.html @@ -1,4 +1,3 @@ -<!-- $Id: sort.html,v 1.2 2008/06/13 00:56:19 merlinofchaos Exp $ --> Sort criteria determine what order the records are retrieved from the database and displayed in; generally, all you need to do is pick a field and choose ascending (1, 2, 3, 4) or descending (4, 3, 2, 1) and it will be done. If you have multiple sort criteria, the second (and later) items only come into play if the first item is the same. Different data types sort just a little bit differently from others: diff --git a/sites/all/modules/views/help/style-comment-rss.html b/sites/all/modules/views/help/style-comment-rss.html index 774359ce5de5b4cc2c4f5a5eab9d6c200ee76dfd..c047ee726b6ad838b8704b14f09f602f504faf33 100644 --- a/sites/all/modules/views/help/style-comment-rss.html +++ b/sites/all/modules/views/help/style-comment-rss.html @@ -1,2 +1 @@ -<!-- $Id: style-comment-rss.html,v 1.1 2008/06/13 00:56:19 merlinofchaos Exp $ --> This row style is only available to RSS styles. It produces XML necessary for an RSS feed for the comment. \ No newline at end of file diff --git a/sites/all/modules/views/help/style-fields.html b/sites/all/modules/views/help/style-fields.html index 05a173b075db52a151411267cc497ced8b10be27..4d8d077b053cacb0f8a9e4bdd210a239c7ff351f 100644 --- a/sites/all/modules/views/help/style-fields.html +++ b/sites/all/modules/views/help/style-fields.html @@ -1,6 +1,16 @@ -<!-- $Id: style-fields.html,v 1.3 2008/06/17 20:07:03 merlinofchaos Exp $ --> The <strong>fields</strong> row style displays each field defined in the view, one after another. Each field defines its own output. By default, each field is put in a <div> unless it is selected to be <em>inline</em>. If it is inline, it is put in a <span>. Two items in <div>s will be displayed one after another, with the second one below the first. Two items in <span>s will be displayed on the same line. One item in a <span> next to <div>s is the same as two items in <div>s. This means that for the <em>inline</em> setting to do anything, at least two consecutive items must be set inline. -You may define a separator which will be placed between each item. This separator may be html. You can use &nbsp; to print blank space. \ No newline at end of file +You may define a <i>separator</i> which will be placed between each item. This separator may be html. You can use &nbsp; to print blank space. + +If the view's row style is set to "fields", fields must be added to the View. If there are no fields, you may receive validation errors such as: + +<i>* Display "Defaults" uses fields but there are none defined for it or all are excluded. +* Display "Page" uses fields but there are none defined for it or all are excluded.</i> + +This is because the row style "fields" expects at least one field for display. + +There is also an option to hide empty fields, so empty fields, along with their labels or markup will not be displayed. + +There is also an option to hide empty fields, so empty fields, along with their labels or markup will not be displayed. diff --git a/sites/all/modules/views/help/style-grid.html b/sites/all/modules/views/help/style-grid.html index d9b24fc9109c266c84c3cab6c2bf524bbf8df100..cc2e098ca3ee11fc8c10843f502b4ea91180a97d 100644 --- a/sites/all/modules/views/help/style-grid.html +++ b/sites/all/modules/views/help/style-grid.html @@ -1,5 +1,4 @@ -<!-- $Id: style-grid.html,v 1.3.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ --> -The <strong>grid</strong> style will display each row of your view within a grid. You may customize the number of columns, though it defaults to 4. A grid looks like this: +The <strong>grid</strong> style will display each row of your view within a grid. You may customize the <strong>number of columns</strong>, though it defaults to 4. A grid looks like this: <table width="100%"> <tr><td>row 1</td><td>row 2</td><td>row 3</td><td>row 4</td></tr> @@ -8,9 +7,9 @@ The <strong>grid</strong> style will display each row of your view within a grid <tr><td>row 13</td><td>row 14</td><td>row 15</td><td>row 16</td></tr> </table> -The above uses the 'horizontal' alignment, where rows are added into the grid from left to right. +The above uses the <strong>horizontal</strong> alignment, where rows are added into the grid from left to right. -With a vertical alignment, rows will be placed from top to bottom, like this: +With a <strong>vertical</strong> alignment, rows will be placed from top to bottom, like this (your <strong>row</strong> results will appear as columns): <table width="100%"> <tr><td>row 1</td><td>row 5</td><td>row 9</td><td>row 13</td></tr> <tr><td>row 2</td><td>row 6</td><td>row 10</td><td>row 14</td></tr> @@ -18,4 +17,6 @@ With a vertical alignment, rows will be placed from top to bottom, like this: <tr><td>row 4</td><td>row 8</td><td>row 12</td><td>row 16</td></tr> </table> -This style uses a <a href="topic:views/style-row">row style</a> to determine what each row will look like. \ No newline at end of file +You can also choose to <strong>group a field</strong> from the Fields Section. This grouping field will be displayed as a header, and all rows will be displayed beneath it. + +This style uses a <a href="topic:views/style-row">row style</a> to determine what each row will look like. diff --git a/sites/all/modules/views/help/style-jump.html b/sites/all/modules/views/help/style-jump.html new file mode 100644 index 0000000000000000000000000000000000000000..7f7a13e0026dac0a4e2f882a46a8c349027e3ee2 --- /dev/null +++ b/sites/all/modules/views/help/style-jump.html @@ -0,0 +1,45 @@ +<!-- $Id$ --> +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. + +Some examples of how this might be useful: + + +<h3>Jump to a node</h3> +<ol> +<li>Create a new <strong>Node</strong> view</li> +<li>Select the <strong>Node: Path</strong> and <strong>Node: Title</strong> fields</li> +<li>Configure the <strong>Node: Path</strong> field to "exclude from display" and check "Use absolute link"</li> +<li>Configure the <strong>Node: Title</strong> field by removing the "Label" and unchecking "Link this field to its node"</li> +<li>Set the view style to <strong>jump menu</strong></li> +<li>In the style settings, set the "Path field" to <strong>Node: Path</strong></li> +</ol> + +Your view will now display with a select list and a <strong>Go</strong> button. If you select an item in the list and hit the <strong>Go</strong> button you will see the selected node's page in the browser. + +<h3>Jump to a node's edit page</h3> +<ol> +<li>Create a new <strong>Node</strong> view</li> +<li>Select the <strong>Node: Nid</strong> and <strong>Node: Title</strong> fields</li> +<li>Configure the <strong>Node: Nid</strong> field to "exclude from display" and check "Rewrite the output of this field"</li> +<li>In the text field that appears for rewriting the output of this field, enter <strong>node/[nid]/edit</strong></li> +<li>Configure the <strong>Node: Title</strong> field by removing the "Label" and unchecking "Link this field to its node"</li> +<li>Set the view style to <strong>jump menu</strong></li> +<li>In the style settings, set the "Path field" to <strong>Node: Nid</strong></li> +</ol> + +Your view will now display with a select list and a <strong>Go</strong> button. If you select an item in the list and hit the <strong>Go</strong> button you will see the selected node's edit page in the browser. Please note that users without rights to the node's edit page will see an access denied message. + +<h3>Jump to a user profile</h3> +<ol> +<li>Create a new <strong>User</strong> view</li> +<li>Select the <strong>User: Uid</strong> and <strong>User: Name</strong> fields</li> +<li>Configure the <strong>User: Uid</strong> field to "exclude from display" and check "Rewrite the output of this field"</li> +<li>In the text field that appears for rewriting the output of this field, enter <strong>user/[uid]</strong></li> +<li>Configure the <strong>User: Name</strong> field by removing the "Label" and unchecking "Link this field to its user"</li> +<li>Set the view style to <strong>jump menu</strong></li> +<li>In the style settings, set the "Path field" to <strong>User: Uid</strong></li> +</ol> + +Your view will now display with a select list and a <strong>Go</strong> button. If you select an item in the list and hit the <strong>Go</strong> button you will see the selected user's profile page in the browser. diff --git a/sites/all/modules/views/help/style-list.html b/sites/all/modules/views/help/style-list.html index f5e98baad035b7010a5ff1b7402f6a3074f9ca6f..71fcfa43c98d73da3edae143c5d259f0e55f11f9 100644 --- a/sites/all/modules/views/help/style-list.html +++ b/sites/all/modules/views/help/style-list.html @@ -1,4 +1,3 @@ -<!-- $Id: style-list.html,v 1.3.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ --> The <strong>List</strong> view style will display every row of the view as part of an HTML list construct. For example: <ul> <li> Row 1 </li> diff --git a/sites/all/modules/views/help/style-node-rss.html b/sites/all/modules/views/help/style-node-rss.html index 332b2853ccf3114ec5e6bad6bb20244b7882d76c..9cce41439e44b804f269538a27d51484a7694ca9 100644 --- a/sites/all/modules/views/help/style-node-rss.html +++ b/sites/all/modules/views/help/style-node-rss.html @@ -1,2 +1 @@ -<!-- $Id: style-node-rss.html,v 1.2 2008/06/13 00:56:19 merlinofchaos Exp $ --> This row style is only available to RSS styles. It produces XML necessary for an RSS feed for the node record. \ No newline at end of file diff --git a/sites/all/modules/views/help/style-node.html b/sites/all/modules/views/help/style-node.html index 360b96f4125b2befc8085409faff254808c638a7..91b24eb73258c1e0c7c61767a5a35ad46814e158 100644 --- a/sites/all/modules/views/help/style-node.html +++ b/sites/all/modules/views/help/style-node.html @@ -1,10 +1,11 @@ -<!-- $Id: style-node.html,v 1.4.6.1 2010/09/15 09:01:01 dereine Exp $ --> -The <strong>node</strong> row style will display each item of the view through Drupal's standard <em>node_view()</em> function. Views has very little control over this output, except for the options you see. Instead, the output is run through the standard node template mechanism (typically <strong>node.tpl.php</strong> or a variant thereof) and any decisions about what is output may be done there. +The <strong>node</strong> row style will display each item of the view through Drupal's standard <em>node_view()</em> function. Views has very little control over this output, except for the options you see. You can choose from different <strong>Build modes</strong>. By default there are "Teaser" and "Full node". You can also decide if you want to "Display links" and/or "Display node comments". -Views does add an extra 'suggestion' to the list of possible node templates: <strong>node--view--VIEWNAME.tpl.php</strong> -- you may use this to theme a node specifically for the view. This can be handy for creating very small teasers and the like. +Because the output is run through the standard node template mechanism (typically <strong>node.tpl.php</strong> or a variant thereof), any decisions about what is output may be done there. -You may opt to display the full node body or the node teaser, and you may add the node links (such as he 'comment' links that appear after a node) or not. +Views does add an extra 'suggestion' to the list of possible node templates: <strong>node--view--VIEWNAME.tpl.php</strong> -- you may use this to theme a node specifically for the view. This can be handy for creating very small teasers and the like. +You may opt to display the full node body or the node teaser, and you may add the node links (such as the 'comment' links that appear after a node) or not. + Because of this behavior, <strong>the node row style does not utilize fields</strong> and the Fields section will not be displayed. <strong>Please note that this row style performs a node_load() for every row, and as such can produce a lot of extra queries.</strong> Sometimes this is necessary, but it can have a negative impact on your site's performance! diff --git a/sites/all/modules/views/help/style-row.html b/sites/all/modules/views/help/style-row.html index 2d983035e75382b0f9e4f60506f25667291c4c1a..fce38d5ffccd3a2ed2385013d4b7c9b0c5456671 100644 --- a/sites/all/modules/views/help/style-row.html +++ b/sites/all/modules/views/help/style-row.html @@ -1,4 +1,8 @@ -<!-- $Id: style-row.html,v 1.1 2008/06/13 00:56:19 merlinofchaos Exp $ --> -A row style is an individual style to display only an individual record within a view. For example, a <strong>node</strong> type view would display one node per row; a <strong>user</strong> type view would display one user per row. +A row style is an individual style to display only an individual record within a view. You can choose between <a href="topic:views/style-node">node</a> or <a href="topic:views/style-fields">fields</a>. For example, a node type view would display one node per row; a user type view would display one user per row. + +When you choose <strong>fields</strong>, you must have entries in the <a href="topic:views/field">Fields</a> section to produce an output. To set some options for fields, read <a href="topic:views/style-fields">here</a>. + +Some row styles use <em>fields</em> which means you may select from the available fields to display. Others row styles do not - they are able to use the base type and create a display. Usually, row styles that do not use fields produce less efficient (slower) views, so bear this in mind when contemplating the performance of your site. + ++When you choose <strong>node</strong> the complete node will display through Drupal's standard <em>node_view()</em> function. You can choose some <a href="topic:views/style-node">options</a>. -Some row styles use <em>fields</em> which means you select from the available fields to display; others do not; they are able to use the base type and create a display. Usually, row styles that do not use fields <em>produce less efficient (slower) views</em>, so bear this in mind when contemplating the performance of your site. \ No newline at end of file diff --git a/sites/all/modules/views/help/style-rss.html b/sites/all/modules/views/help/style-rss.html index d661fd7a51bc2faa8743e5315cab3889cf7d07ce..e67bd3092dd43ac0dce2b9f0e351040279b2c606 100644 --- a/sites/all/modules/views/help/style-rss.html +++ b/sites/all/modules/views/help/style-rss.html @@ -1,4 +1,5 @@ -<!-- $Id: style-rss.html,v 1.2 2008/06/13 00:56:19 merlinofchaos Exp $ --> The <strong>RSS</strong> output style is only available for <em>Feed</em> display types. It will display the view as an RSS feed, which is a specialized XML output. This output is not user visible, but can be parsed by feed readers for aggregation. -You may supply a description for the RSS feed; most feed readers will display this description along with the contents of the feed. You may also select to use the site's mission statement for the description. \ No newline at end of file +You may supply a description for the RSS feed; most feed readers will display this description along with the contents of the feed. You may also select to use the site's mission statement for the description. + +Please note that when using RSS views only comes with the one RSS style. There's no style override for RSS. Modules can add more. diff --git a/sites/all/modules/views/help/style-settings.html b/sites/all/modules/views/help/style-settings.html new file mode 100644 index 0000000000000000000000000000000000000000..a39c3acd6d3d2eeaa1528713b40dd0c2ea0dba8e --- /dev/null +++ b/sites/all/modules/views/help/style-settings.html @@ -0,0 +1,3 @@ +Views includes many options for theming or styling. + +TODO: add more here. diff --git a/sites/all/modules/views/help/style-summary-unformatted.html b/sites/all/modules/views/help/style-summary-unformatted.html index 2350a15fbef709a1599c92f3b664d160defea736..258acf528cf9bb45f7f3b2d456a78f64b4e4a21d 100644 --- a/sites/all/modules/views/help/style-summary-unformatted.html +++ b/sites/all/modules/views/help/style-summary-unformatted.html @@ -1,4 +1,3 @@ -<!-- $Id: style-summary-unformatted.html,v 1.1 2008/06/13 00:56:19 merlinofchaos Exp $ --> The <strong>unformatted summary</strong> style is only available for <em>summary</em> styles, which are when an argument has been set to provide a summary if it was not provided with a value. This summary provides the possible candidates for the argument one after another with no special formatting. If <em>inline</em> is selected, the summary items will be enclosed within <span> tags. Otherwise the items will be in <div> tags. You can also elect to display the number of matching records for the argument, plus change the number of items per page for the summary. This is often useful because summary views are often quite small, but other views quite space intensive. It is very common to have far more records available in the summary view than in the more normal view. \ No newline at end of file diff --git a/sites/all/modules/views/help/style-summary.html b/sites/all/modules/views/help/style-summary.html index f6012a4f495c4d48dd97655edb1bc6ec5272bc26..f5b01ecf648a5a7da823e104215d153faa74a862 100644 --- a/sites/all/modules/views/help/style-summary.html +++ b/sites/all/modules/views/help/style-summary.html @@ -1,4 +1,3 @@ -<!-- $Id: style-summary.html,v 1.2 2008/06/13 00:56:19 merlinofchaos Exp $ --> The <strong>list summary</strong> style is only available for <em>summary</em> styles, which are when an argument has been set to provide a summary if it was not provided with a value. This summary provides a list of possible candidates for the argument in a standard HTML list. Like the normal list style, you may set this list to be ordered or not. You can also elect to display the number of matching records for the argument, plus change the number of items per page for the summary. This is often useful because summary views are often quite small, but other views quite space intensive. It is very common to have far more records available in the summary view than in the more normal view. \ No newline at end of file diff --git a/sites/all/modules/views/help/style-table.html b/sites/all/modules/views/help/style-table.html index e7fb89bec4659503e17d42fc86eeeeaf74d69274..b8ade8a352011f00f458a4ff599203872b2bc3ba 100644 --- a/sites/all/modules/views/help/style-table.html +++ b/sites/all/modules/views/help/style-table.html @@ -1,4 +1,3 @@ -<!-- $Id: style-table.html,v 1.2 2008/06/13 00:56:19 merlinofchaos Exp $ --> The <strong>table</strong> style will display the View results as a table; each row of the table will correspond to a row from the view result. When setting the table options, each field in the view will be presented with some information next to each field: diff --git a/sites/all/modules/views/help/style-unformatted.html b/sites/all/modules/views/help/style-unformatted.html index 777d2ed1d567578e4e69a4d8a573b1a1635a9488..99fa3de7fa42a6aafe7accf6f9f2957350b73f0b 100644 --- a/sites/all/modules/views/help/style-unformatted.html +++ b/sites/all/modules/views/help/style-unformatted.html @@ -1,2 +1 @@ -<!-- $Id: style-unformatted.html,v 1.2 2008/06/13 00:56:19 merlinofchaos Exp $ --> The unformatted output style simply places each row of the view, one after another, with no additional formatting. diff --git a/sites/all/modules/views/help/style.html b/sites/all/modules/views/help/style.html index 3eb6fdfee76cb8a42ceba071f01eaf6704ce84de..01dffed3bdb95be70ed3c7db72c5b053bc10b54e 100644 --- a/sites/all/modules/views/help/style.html +++ b/sites/all/modules/views/help/style.html @@ -1,4 +1,3 @@ -<!-- $Id: style.html,v 1.4.6.1 2010/03/16 22:27:29 merlinofchaos Exp $ --> The Views' <strong>style</strong> system is how you customize the output produced by your view. A view style is basically a smart theme template that processes the view data and then outputs it. All styles in Views can be <a href="topic:views/using-theme">overridden</a> by placing copies of the templates in your theme directory and then modifying them. See the <a href="topic:views/analyze-theme">theme: information</a> link available on all views to get hints for which templates a given view is using. <div class="help-box" style="text-align:center"> diff --git a/sites/all/modules/views/help/theme-css.html b/sites/all/modules/views/help/theme-css.html index bfa3593a6d8dc1a086112573bc1220b8a89539b4..bfab97d2e74b8db8c65fd63c137fba894ac171c4 100644 --- a/sites/all/modules/views/help/theme-css.html +++ b/sites/all/modules/views/help/theme-css.html @@ -1,6 +1,7 @@ -<!-- $Id: theme-css.html,v 1.3.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ --> Views uses a wide array of CSS classes on all of its content to ensure that you can easily and accurately select exactly the content you need in order to manipulate it with CSS. +It is possible to enter a custom css class under <a href="topic:views/style">Style</a> settings. The <strong>CSS class</strong> names will be added to the view. This enables you to use specific CSS code for each view. You may define multiples classes separated by spaces. + Typically, every view is wrapped in a div with the name of the view as part of its class (for all these examples, we will assume the name of the view is <strong>myview</strong>), as well as the generic class 'view': <pre> diff --git a/sites/all/modules/views/help/updating-view3.html b/sites/all/modules/views/help/updating-view3.html new file mode 100644 index 0000000000000000000000000000000000000000..aa2d9770d11b8d9a6d5533418641c7e81e4bb1d6 --- /dev/null +++ b/sites/all/modules/views/help/updating-view3.html @@ -0,0 +1 @@ +Most views should automatically convert without issue. It's always a good idea and highly recommended that all views be exported for backup purposes before upgrading to Views 3.x. diff --git a/sites/all/modules/views/help/updating.html b/sites/all/modules/views/help/updating.html index 67f246a821ed7c2d32f5f228e04f5650853e5859..096c917c216fe266cb97eb3249e45a660e6d06aa 100644 --- a/sites/all/modules/views/help/updating.html +++ b/sites/all/modules/views/help/updating.html @@ -1,3 +1,7 @@ -<!-- $Id: updating.html,v 1.3 2008/07/03 05:05:12 merlinofchaos Exp $ --> -TODO: This document needs to be fleshed out. +Views 1 views stored in the database may not convert properly to Views 2. In order to aid with the conversion, a tool is available. In the main Views page, choose Tools -> Convert. Any views you choose will attempt to convert. + +Note that converted Views may not match perfectly! Adjustments may be necessary to retain the integrity of your previous views. +Views 1 views may also be exported before upgrade, and then imported through the standard Import tab. Those views will attempt to convert during import. Exporting your views before upgrade has the added benefit of ensuring a backup. + +There are no known issues converting views from Views 2 to Views 3 at this time. diff --git a/sites/all/modules/views/help/upgrading.html b/sites/all/modules/views/help/upgrading.html index c6527b5452cc744f986e011117f28ce2c4832869..83314b104e89f0572b6a24605de2ca26c5b1cc4c 100644 --- a/sites/all/modules/views/help/upgrading.html +++ b/sites/all/modules/views/help/upgrading.html @@ -1,4 +1,3 @@ -;<!-- $Id: upgrading.html,v 1.1.2.2 2010/11/27 20:12:58 dereine Exp $ --> <h3>Updating templates</h3> If you have theme files for node-view-$viewname of comment-view-$viewname you have diff --git a/sites/all/modules/views/help/using-theme.html b/sites/all/modules/views/help/using-theme.html index c94bbd58a4e047da2166bb817db76a319223e50a..c4164eb474c60ee9d04c6686ccd4e669eae98fda 100644 --- a/sites/all/modules/views/help/using-theme.html +++ b/sites/all/modules/views/help/using-theme.html @@ -1,4 +1,3 @@ -<!-- $Id: using-theme.html,v 1.6.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ --> Views theme templates are straightforward to use with the Drupal theming system. If you are unfamiliar with the theming system at all, you should probably at least read <a href="http://drupal.org/node/173880">drupal.org theming documentation</a>. That said, these are the important things you need to know: <ol> @@ -34,9 +33,9 @@ The contents of the $row variable included these fields, in precisely the order Would print just the title for that row. Please remember that I'm doing this inside the loop, so this will get repeated for every row of the view. -The IDs used to fetch items from the array, id <strong>$row['title']</strong> can be quickly and easily looked up on the Theme: Information page. Once a field has been added to the view, its ID will not change, but note that if there are two "title" fields in a view, one will be 'title' and the other will be 'title1', in order to prevent namespace collisions. +The IDs used to fetch items from the array, id <strong>$row['title']</strong> can be quickly and easily looked up on the Theme: Information page. Once a field has been added to the view, its ID will not change, but note that if there are two "title" fields in a view, one will be 'title' and the other will be 'title_1', in order to prevent namespace collisions. -The important thing here is that Views does provide IDs. Views doesn't tell you what these IDs are, but it's easy to get them by dumping the row data and doing a simple visual inspection. Views does guarantee that these IDs will not change, unless you actually add a new field and remove the existing one (in which case 'title', above, would become 'title1'). +The important thing here is that Views does provide IDs. Views doesn't tell you what these IDs are, but it's easy to get them by dumping the row data and doing a simple visual inspection. Views does guarantee that these IDs will not change, unless you actually add a new field and remove the existing one (in which case 'title', above, would become 'title_1'). <h2>The basic fields template</h2> diff --git a/sites/all/modules/views/help/view-add.html b/sites/all/modules/views/help/view-add.html new file mode 100644 index 0000000000000000000000000000000000000000..46a1a98933e1775f18b61657b54feca0a10172d6 --- /dev/null +++ b/sites/all/modules/views/help/view-add.html @@ -0,0 +1,19 @@ +When you want to create a new view you can enter the following information about it. +First, you must enter a <strong>view name</strong>. This is the unique name of the view. It must contain only alphanumeric characters and underscores; it is used to identify the view internally and to generate unique theming template names for this view. If you are overriding a module provided view, the name must not be changed or a new view will be created instead of overriding. +You can enter a <strong>description of the view</strong>. This description will appear on the Views administrative UI to tell you what the view is about. +You can enter a <strong>view tag</strong>. It will be used help sort views on the administrative page. +You must choose a view type. +<dl> +<dt>Node</dt> +<dd>Nodes are a Drupal site's primary content.</dd> +<dt>Comment</dt> +<dd>When you want to handle comments and information related to the and information related to them.</dd> +<dt>File</dt> +<dd>When you want to handle files and file information.</dd> +<dt>Node revision</dt> +<dd>When you want to handle node revision information, choose this.</dd> +<dt>Term</dt> +<dd>When you want to handle taxonomy, choose this one.</dd> +<dt>User</dt> +<dd>When you want to handle users and user information, choose this one.</dd> +</dl> diff --git a/sites/all/modules/views/help/view-settings.html b/sites/all/modules/views/help/view-settings.html new file mode 100644 index 0000000000000000000000000000000000000000..39902b295cd653ffcd458db3310823a65c0d8102 --- /dev/null +++ b/sites/all/modules/views/help/view-settings.html @@ -0,0 +1,5 @@ +With the Description and Tag you can set the "View description" and the "View tag". The tag help you to organize your views. Only one tag may be entered for a given view. Note that this tag can also be used in themeing, so do not use words already reserved by Drupal for use, such as "Page". + +You can <strong>clone</strong> a view. When you click on the clone link on the upper right, all the options in the current view will copy to a new view, which can be given a new name and edited further. + +You can <strong>export</strong> a view. You can the copy and paste the code from a view into a module or something else. It is a array with all options for that view. diff --git a/sites/all/modules/views/help/view-type.html b/sites/all/modules/views/help/view-type.html index 3285a857107768c9a70060e9070c6d62e86c2ede..bdb80fc0cdf99a0c953631cc20d4333bed451b07 100644 --- a/sites/all/modules/views/help/view-type.html +++ b/sites/all/modules/views/help/view-type.html @@ -1,4 +1,3 @@ -<!-- $Id: view-type.html,v 1.5 2009/02/20 20:46:48 merlinofchaos Exp $ --> <p>The <strong>view type</strong> describes how this view is stored; Views is capable of having Views entirely in code that are not in the database. This allows modules to easily ship with Views built in, and it allows you to create a module to store your views for easy deployment between development and production servers.</p> <dl> diff --git a/sites/all/modules/views/help/views.help.ini b/sites/all/modules/views/help/views.help.ini index 0895d5a7746106e41241c6aaef23897d3483231e..0115c2fe948966d21c22380ced77df2b59629481 100644 --- a/sites/all/modules/views/help/views.help.ini +++ b/sites/all/modules/views/help/views.help.ini @@ -1,19 +1,22 @@ -; $Id: views.help.ini,v 1.18.4.5 2010/08/26 19:00:51 dereine Exp $ [advanced help settings] line break = TRUE [about] title = "What is Views?" -weight = -40 +weight = -50 [getting-started] title = "Getting started" -weight = -45 +weight = -40 + +[new] +title = "What's new in Views 2" +weight = -30 [example-users-by-role] title = "Create a page to list users by role" parent = getting-started -weight = -10 +weight = -20 [example-recent-stories] title = "Create a block of recent stories" @@ -30,12 +33,31 @@ title = "Create a block of author's recent blog posts" parent = getting-started weight = 40 -[view-type] -title = "View types" + +[example-bulk-export] +title = "Create a module from bulk exported views" +parent = getting-started +weight = 50 + +[view-add] +title = "Add a View" +weight = -10 + +[view-settings] +title = "View settings" +weight = 0 + +[basic-settings] +title = "Basic settings" +weight = 10 + +[advanced-settings] +title= "Advanced settings" +weight = 20 [display] title = "Displays" -weight = -30 +weight = -10 [display-default] title = "Default display" @@ -60,119 +82,163 @@ parent = display title = "Feed display" parent = display -[argument] -title = "Arguments" -parent = about - -[field] -title = "Fields" -parent = about - -[sort] -title = "Sorts" -parent = about - -[filter] -title = "Filters" -parent = about - -[relationship] -title = "Relationships" -parent = about +[style-settings] +title = "Style settings" +weight = 30 [style] title = "Output styles (View styles)" -weight = -20 +parent = style-settings +weight = -20 -[style-row] -title = "View row styles" +[style-grid] +title = "Grid (output style)" parent = style -weight = 10 +weight = 0 [style-list] -title = "List output style" +title = "HTML List (output style)" parent = style - -[style-unformatted] -title = "Unformatted output style" -parent = style -weight = -6 +weight = 10 [style-table] -title = "Table output style" +title = "Table (output style)" parent = style -weight = -5 +weight = 20 -[style-grid] -title = "Grid output style" +[style-unformatted] +title = "Unformatted (output style)" parent = style -weight = -5 +weight = 30 [style-rss] title = "RSS output style" parent = style -weight = -5 +weight = 50 + +[style-row] +title = "Row styles" +weight = -10 +parent = style-settings + +[style-jump] +title = "Jump menu output style" +parent = style +weight = -4 [style-fields] -title = "Fields row style" +title = "Fields" parent = style-row +weight = -10 [style-node] -title = "Node row style" +title = "Node" parent = style-row +weight = 0 [style-node-rss] title = "Node RSS item row style" parent = style-row +weight = 10 [style-comment-rss] title = "Comment RSS item row style" parent = style-row +weight = 20 -[style-summary-unformatted] -title = "Unformatted summary style" -parent = "style" -weight = 10 +[performance] +title = "Performance" -[style-summary] -title = "List summary style" -parent = "style" -weight = 10 - -[menu] -title = "Menu options (page display)" - -[path] -title = "Path options (page display)" +[performance-views-vs-displays] +title = "Multiple Views vs Multiple Displays" +parent = performance [analyze-theme] title = "Theme information" +parent = style-settings +weight = 30 [using-theme] title = "Using Views templates" parent = analyze-theme +weight = 40 [theme-css] title = "Using CSS with Views" -parent = analyze-theme +parent = style-settings +weight = 20 + +[menu] +title = "Menu options (page display)" +parent = display-page + +[path] +title = "Path options (page display)" +parent = display-page + +[exposed-form] +title = "Exposed Form" +weight = 45 + +[header] +title = "Header" +weight = 50 + +[footer] +title = "Footer" +weight = 60 + +[empty-text] +title = "Empty Text" +weight = 70 + +[field] +title = "Fields" +weight = 80 + +[relationship] +title = "Relationships" +weight = 90 + +[argument] +title = "Arguments" +weight = 100 + +[style-summary-unformatted] +title = "Summary Style: Unformatted (output style)" +parent = argument + +[style-summary] +title = "Summary Style: List (output style)" +parent = argument + +[sort] +title = "Sort criteria" +weight = 110 + +[filter] +title = "Filters" +weight = 120 [overrides] title = "What are overrides?" +parent = display [embed] title = "Embedding a view into other parts of your site" - -[new] -title = "What's new in Views 2" -weight = -42 +weight = 140 [upgrading] title = "Upgrading your Views from Drupal 6 to Drupal 7" +[updating-view3] +title = "Updating your views from Views 2 to Views 3" +weight = 160 + ; API related [api] title = "Views' API" -weight = 100 +weight = 170 [api-tables] title = "Describing tables to Views" @@ -202,3 +268,13 @@ parent = api title = "Integrating the Node Example module" parent = api weight = 100 + +;Other places to get help +[other-help] +title = "Other places to get help" +weight = 200 + +[demo-video] +title = "Video demos for Views" +weight = 210 +parent = other-help diff --git a/sites/all/modules/views/images/close.png b/sites/all/modules/views/images/close.png new file mode 100644 index 0000000000000000000000000000000000000000..2af0da5b434c9eba96fe2862256b88d33d5b8314 Binary files /dev/null and b/sites/all/modules/views/images/close.png differ diff --git a/sites/all/modules/views/images/loading-small.gif b/sites/all/modules/views/images/loading-small.gif new file mode 100644 index 0000000000000000000000000000000000000000..5cbf6e7b75523144e46e36aba2d58263b767b93b Binary files /dev/null and b/sites/all/modules/views/images/loading-small.gif differ diff --git a/sites/all/modules/views/images/loading.gif b/sites/all/modules/views/images/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..2dbcd624aa8b28a0e6cbe5a54d4cb03534009e38 Binary files /dev/null and b/sites/all/modules/views/images/loading.gif differ diff --git a/sites/all/modules/views/images/sprites.png b/sites/all/modules/views/images/sprites.png index 908362229800862620d45fafead8476df6f66c2d..b7df250a03204f3ced9e686279324ad2c0ade68c 100644 Binary files a/sites/all/modules/views/images/sprites.png and b/sites/all/modules/views/images/sprites.png differ diff --git a/sites/all/modules/views/includes/admin.inc b/sites/all/modules/views/includes/admin.inc index cd0d64a1afc24cc3c77866c6686e66076f0c4d75..71d2b55453d979fabb90eb3a99579068522f393a 100644 --- a/sites/all/modules/views/includes/admin.inc +++ b/sites/all/modules/views/includes/admin.inc @@ -1,21 +1,60 @@ <?php -// $Id: admin.inc,v 1.161.4.86 2011/01/04 23:54:35 dereine Exp $ /** * @file admin.inc * Provides the Views' administrative interface. */ /** - * Page callback to list views in the system. + * Create an array of Views admin CSS for adding or attaching. + * + * This returns an array of arrays. Each array represents a single + * file. The array format is: + * - file: The fully qualified name of the file to send to drupal_add_css + * - options: An array of options to pass to drupal_add_css. */ -function views_ui_list_views($arg = NULL) { - if ($arg != NULL) { - return drupal_not_found(); +function views_ui_get_admin_css() { + $module_path = drupal_get_path('module', 'views_ui'); + $list = array(); + $list[$module_path . '/css/views-admin.css'] = array(); + + $list[$module_path . '/css/ie/views-admin.ie7.css'] = array( + 'browsers' => array( + 'IE' => 'lte IE 7', + '!IE' => FALSE + ), + 'preprocess' => FALSE, + ); + + $list[$module_path . '/css/views-admin.theme.css'] = array(); + + // Add in any theme specific CSS files we have + $themes = list_themes(); + $theme_key = $GLOBALS['theme']; + while ($theme_key) { + $list[$module_path . "/css/views-admin.$theme_key.css"] = array( + 'group' => CSS_THEME, + ); + $theme_key = isset($themes[$theme_key]->base_theme) ? $themes[$theme_key]->base_theme : ''; + } + // Views contains style overrides for the following modules + $module_list = array('contextual', 'advanced_help', 'ctools'); + foreach ($module_list as $module) { + if (module_exists($module)) { + $list[$module_path . '/css/views-admin.' . $module . '.css'] = array(); + } } - $output = theme('views_ui_list_views'); - views_ui_check_advanced_help(); - return $output; + + return $list; +} + +/** + * Adds standard Views administration CSS to the current page. + */ +function views_ui_add_admin_css() { + foreach (views_ui_get_admin_css() as $file => $options) { + drupal_add_css($file, $options); + } } /** @@ -26,7 +65,7 @@ function views_ui_list_views($arg = NULL) { * be useful. */ function views_ui_check_advanced_help() { - if (variable_get('views_hide_help_message', FALSE)) { + if (!variable_get('views_ui_show_advanced_help_warning', TRUE)) { return; } @@ -34,789 +73,1741 @@ function views_ui_check_advanced_help() { $filename = db_query_range("SELECT filename FROM {system} WHERE type = 'module' AND name = 'advanced_help'", 0, 1) ->fetchField(); if ($filename && file_exists($filename)) { - drupal_set_message(t('If you <a href="@modules">enable the advanced help module</a>, Views will provide more and better help. <a href="@hide">Hide this message.</a>', array('@modules' => url('admin/modules'),'@hide' => url('admin/structure/views/tools')))); + drupal_set_message(t('If you <a href="@modules">enable the advanced help module</a>, Views will provide more and better help. <a href="@hide">Hide this message.</a>', array('@modules' => url('admin/modules'),'@hide' => url('admin/structure/views/settings')))); } else { - drupal_set_message(t('If you install the advanced help module from !href, Views will provide more and better help. <a href="@hide">Hide this message.</a>', array('!href' => l('http://drupal.org/project/advanced_help', 'http://drupal.org/project/advanced_help'), '@hide' => url('admin/structure/views/tools')))); + drupal_set_message(t('If you install the advanced help module from !href, Views will provide more and better help. <a href="@hide">Hide this message.</a>', array('!href' => l('http://drupal.org/project/advanced_help', 'http://drupal.org/project/advanced_help'), '@hide' => url('admin/structure/views/settings')))); } } } /** - * Preprocess the list views theme + * #pre_render callback for the live preview element. + * + * Delaying the preview generation until the rendering phase ensures that time + * isn't wasted generating a preview if it won't be displayed (for example, if + * after processing the Edit form, a redirect is issued). */ -function template_preprocess_views_ui_list_views(&$vars) { - $items = array(); - $sorts = array(); - - $views = views_get_all_views(); +function views_ui_pre_render_preview($element) { + $preview = views_ui_preview($element['#view'], $element['#display_id'], $element['#preview_args']); + // @todo HTML does not support a FORM inside a FORM. Remove this hack after + // fixing Views UI to display the preview outside of the edit form, so that + // we don't have to mess with the exposed widget form in this way. + $preview = preg_replace('@</?form.*?>@', '', $preview); + $element['#markup'] = $preview; + return $element; +} - // Respond to a reset command by clearing session and doing a drupal goto - // back to the base URL. - if (isset($_GET['op']) && $_GET['op'] == t('Reset')) { - unset($_SESSION['views']['#admin']); - drupal_goto('admin/structure/views'); - } - if (count($_GET) <= 1) { - if (isset($_SESSION['views']['#admin']) && is_array($_SESSION['views']['#admin'])) { - $_GET += $_SESSION['views']['#admin']; - } - } - else { - $_SESSION['views']['#admin'] = $_GET; - unset($_SESSION['views']['#admin']['q']); +/** + * Returns the results of the live preview. + */ +function views_ui_preview($view, $display_id, $args = array()) { + // When this function is invoked as a page callback, each Views argument is + // passed separately. + if (!is_array($args)) { + $args = array_slice(func_get_args(), 2); } - $form_state = array( - 'views' => $views, - 'method' => 'get', - 'rerender' => TRUE, - 'no_redirect' => TRUE, - 'always_process' => TRUE, - 'build_info' => array( - 'args' => array(), - ), - ); + // Save $_GET['q'] so it can be restored before returning from this function. + $q = $_GET['q']; - $vars['widgets'] = drupal_build_form('views_ui_list_views_form', $form_state); - unset($vars['widgets']['form_id']); - unset($vars['widgets']['form_build_id']); - $vars['widgets'] = drupal_render($vars['widgets']); + // Determine where the query and performance statistics should be output. + $show_query = variable_get('views_ui_show_sql_query', FALSE); + $show_info = variable_get('views_ui_show_preview_information', FALSE); + $show_location = variable_get('views_ui_show_sql_query_where', 'above'); - $vars['help_type_icon'] = ''; - if (module_exists('advanced_help')) { - $vars['help_type_icon'] = theme('advanced_help_topic', array('module' => 'views', 'topic' => 'view-type')); + $show_stats = variable_get('views_ui_show_performance_statistics', FALSE); + if ($show_stats) { + $show_stats = variable_get('views_ui_show_sql_query_where', 'above'); } - $base_tables = views_fetch_base_tables(); + $combined = ($show_query === $show_stats); - foreach ($views as $view) { - if ($form_state['values']['tag'] != 'all') { - if ($form_state['values']['tag'] == 'none') { - if (!empty($view->tag)) { - continue; - } - } - elseif ($form_state['values']['tag'] != $view->tag) { - continue; + $rows = array('query' => array(), 'statistics' => array()); + $output = ''; + + $errors = $view->validate(); + if ($errors === TRUE) { + $view->ajax = TRUE; + $view->live_preview = TRUE; + + // AJAX happens via $_POST but everything expects exposed data to + // be in GET. Copy stuff but remove ajax-framework specific keys. + $exposed_input = $_POST; + foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', 'ajax_html_ids', 'ajax_page_state') as $key) { + if (isset($exposed_input[$key])) { + unset($exposed_input[$key]); } } - if ($form_state['values']['type'] != 'all' && $form_state['values']['type'] != $view->type) { - continue; - } + // @todo Remove this hack after fixing Views UI to display the preview + // outside of the edit form, so that the edit form doesn't conflict with + // the exposed widget form. + $exposed_input['form_id'] = 'views_exposed_form'; + unset($exposed_input['form_build_id'], $exposed_input['form_token']); - if ($form_state['values']['base'] != 'all' && $form_state['values']['base'] != $view->base_table) { - continue; - } + $view->set_exposed_input($exposed_input); - if ($form_state['values']['display'] != 'all' && empty($view->display[$form_state['values']['display']])) { - continue; - } + // Store the current view URL for later use: + $view->set_display($display_id); + $view->set_arguments($args); - if ($form_state['values']['status'] != 'all' && (!empty($view->disabled) == $form_state['values']['status'])) { - continue; + if ($view->display_handler->get_option('path')) { + $path = $view->get_url(); } - $item = new stdClass(); - $item->ops = array(); + // Make view links come back to preview. + $view->override_path = 'admin/structure/views/nojs/preview/' . $view->name . '/' . $display_id; - if (empty($view->disabled)) { - $item->ops[] = l(t('Edit'), "admin/structure/views/edit/$view->name"); - $item->ops[] = l(t('Export'), "admin/structure/views/export/$view->name"); - $item->ops[] = l(t('Clone'), "admin/structure/views/clone/$view->name"); + // Also override $_GET['q'] so we get the pager. + $_GET['q'] = $view->override_path; + if ($args) { + $_GET['q'] .= '/' . implode('/', $args); } - if ($view->type != t('Default')) { - $text = $view->type == t('Overridden') ? t('Revert') : t('Delete'); - $item->ops[] = l($text, "admin/structure/views/delete/$view->name"); + + // Suppress contextual links of entities within the result set during a + // Preview. + // @todo We'll want to add contextual links specific to editing the View, so + // the suppression may need to be moved deeper into the Preview pipeline. + views_ui_contextual_links_suppress_push(); + try { + $preview = $view->preview($display_id, $args); } - else { - if (empty($view->disabled)) { - $item->ops[] = l(t('Disable'), "admin/structure/views/disable/$view->name", array('query' => drupal_get_destination())); - } - else { - $item->ops[] = l(t('Enable'), "admin/structure/views/enable/$view->name", array('query' => drupal_get_destination())); - } + catch (Exception $e) { + drupal_set_message($e->getMessage(), 'error'); } + views_ui_contextual_links_suppress_pop(); + + // Prepare the query information and statistics to show either above or + // below the view preview. + if ($show_info || $show_query || $show_stats) { + // Get information from the preview for display. + if (!empty($view->build_info['query'])) { + if ($show_query) { + $query = $view->build_info['query']; + // Only the sql default class has a method getArguments. + $quoted = array(); + + if (get_class($view->query) == 'views_plugin_query_default') { + $arguments = $query->getArguments(); + $connection = Database::getConnection(); + foreach ($query->arguments() as $key => $val) { + if (is_array($val)) { + $quoted[$key] = implode(', ', array_map(array($connection, 'quote'), $val)); + } + else { + $quoted[$key] = $connection->quote($val); + } + } + } + $rows['query'][] = array('<strong>' . t('Query') . '</strong>', '<pre>' . check_plain(strtr($query, $quoted)) . '</pre>'); + if (!empty($view->additional_queries)) { + $queries = '<strong>' . t('These queries were run during view rendering:') . '</strong>'; + foreach ($view->additional_queries as $query) { + if ($queries) { + $queries .= "\n"; + } + $queries .= t('[@time ms]', array('@time' => intval($query[1] * 100000) / 100)) . ' ' . $query[0]; + } - $item->ops = implode(' | ', $item->ops); - if (empty($view->display)) { - $item->path = t('Warning! Broken view!'); - } - else { - $view->init_display(); // Make sure all the handlers are set up - $all_paths = array(); - foreach ($view->display as $display) { - if (!empty($display->handler) && $display->handler->has_path()) { - $one_path = $display->handler->get_option('path'); - if (empty($path_sort)) { - $path_sort = strtolower($one_path); + $rows['query'][] = array('<strong>' . t('Other queries') . '</strong>', '<pre>' . $queries . '</pre>'); } - if (empty($view->disabled) && strpos($one_path, '%') === FALSE) { - $all_paths[] = l($one_path, $one_path); + } + if ($show_info) { + $rows['query'][] = array('<strong>' . t('Title') . '</strong>', filter_xss_admin($view->get_title())); + if (isset($path)) { + $path = l($path, $path); } else { - $all_paths[] = check_plain($one_path); + $path = t('This display has no path.'); } + $rows['query'][] = array('<strong>' . t('Path') . '</strong>', $path); } - } - if (!empty($all_paths)) { - $item->path = implode(', ', array_unique($all_paths)); - } - } - - $item->type = $view->type; - $item->name = $view->name; - if (!empty($view->tag)) { - $item->tag = $view->tag; - } - - $item->title = $view->get_title(); - $item->base = !empty($base_tables[$view->base_table]['title']) ? $base_tables[$view->base_table]['title'] : t('Broken'); + if ($show_stats) { + $rows['statistics'][] = array('<strong>' . t('Query build time') . '</strong>', t('@time ms', array('@time' => intval($view->build_time * 100000) / 100))); + $rows['statistics'][] = array('<strong>' . t('Query execute time') . '</strong>', t('@time ms', array('@time' => intval($view->execute_time * 100000) / 100))); + $rows['statistics'][] = array('<strong>' . t('View render time') . '</strong>', t('@time ms', array('@time' => intval($view->render_time * 100000) / 100))); - $item->displays = array(); - foreach ($view->display as $display) { - if (!empty($display->handler->definition['admin'])) { - $item->displays[$display->handler->definition['admin']] = TRUE; + } + drupal_alter('views_preview_info', $rows, $view); + } + else { + // No query was run. Display that information in place of either the + // query or the performance statistics, whichever comes first. + if ($combined || ($show_location === 'above')) { + $rows['query'] = array(array('<strong>' . t('Query') . '</strong>', t('No query was run'))); + } + else { + $rows['statistics'] = array(array('<strong>' . t('Query') . '</strong>', t('No query was run'))); + } } } - - if ($item->displays) { - ksort($item->displays); - $item->displays = implode(', ', array_keys($item->displays)); - } - - $item->description = check_plain($view->description); - $item->classes = empty($view->disabled) ? 'view-enabled' : 'view-disabled'; - $items[] = $item; - - $sort = intval(empty($view->disabled) xor $form_state['values']['sort'] == 'asc'); - - switch ($form_state['values']['order']) { - case 'name': - default: - $sort .= strtolower($view->name); - break; - case 'title': - $sort .= strtolower($item->title); - break; - case 'path': - $sort .= strtolower($raw_path); // $path; - break; - case 'type': - $sort .= $view->type . $view->name; - break; - case 'tag': - $sort .= strtolower($view->tag); - break; - case 'desc': - $sort .= strtolower($view->description); - break; - } - - $sorts[] = $sort; - } - - if ($form_state['values']['sort'] == 'desc') { - arsort($sorts); } else { - asort($sorts); + foreach ($errors as $error) { + drupal_set_message($error, 'error'); + } + $preview = t('Unable to preview due to validation errors.'); } - $i = array(); - foreach ($sorts as $id => $title) { - $i[] = $items[$id]; + // Assemble the preview, the query info, and the query statistics in the + // requested order. + if ($show_location === 'above') { + if ($combined) { + $output .= '<div class="views-query-info">' . theme('table', array('rows' => array_merge($rows['query'], $rows['statistics']))) . '</div>'; + } + else { + $output .= '<div class="views-query-info">' . theme('table', array('rows' => $rows['query'])) . '</div>'; + } + } + elseif ($show_stats === 'above') { + $output .= '<div class="views-query-info">' . theme('table', array('rows' => $rows['statistics'])) . '</div>'; } - views_add_css('views-list'); - $vars['views'] = $i; + $output .= $preview; - $getting_started = ''; - if (module_exists('advanced_help')) { - $getting_started = theme('advanced_help_topic', array('module' => 'views', 'topic' => 'getting-started', 'type' => 'title')); + if ($show_location === 'below') { + if ($combined) { + $output .= '<div class="views-query-info">' . theme('table', array('rows' => array_merge($rows['query'], $rows['statistics']))) . '</div>'; + } + else { + $output .= '<div class="views-query-info">' . theme('table', array('rows' => $rows['query'])) . '</div>'; + } } - if (!$getting_started) { - $getting_started = t('Install the advanced help module for the getting started'); + elseif ($show_stats === 'below') { + $output .= '<div class="views-query-info">' . theme('table', array('rows' => $rows['statistics'])) . '</div>'; } - $vars['help'] = t('Not sure what to do? Try the "!getting-started" page.', array('!getting-started' => $getting_started)); + $_GET['q'] = $q; + return $output; +} + +/** + * AJAX callback that returns the preview section of the edit form. + */ +function views_ui_preview_callback($form, $form_state) { + return $form['displays']['preview']; } /** - * Provide a form for sorting and filtering the list of views. + * Page callback to add a new view. */ -function views_ui_list_views_form($form, &$form_state) { - if (!variable_get('clean_url', FALSE)) { - $form['q'] = array( - '#type' => 'hidden', - '#value' => $_GET['q'], - ); - } +function views_ui_add_page() { + views_ui_add_admin_css(); + drupal_set_title(t('Add new view')); + return drupal_get_form('views_ui_add_form'); +} - $all = array('all' => t('- All -')); - $none = array('none' => t('- None -')); +/** + * Form builder for the "add new view" page. + */ +function views_ui_add_form($form, &$form_state) { + ctools_include('dependent'); + $form['#attached']['js'][] = drupal_get_path('module', 'views_ui') . '/js/views-admin.js'; + $form['#attributes']['class'] = array('views-admin'); - $form['type'] = array( - '#type' => 'select', - '#title' => t('Storage'), - '#options' => array( - 'all' => t('- All -'), - t('Normal') => t('Normal'), - t('Default') => t('Default'), - t('Overridden') => t('Overridden'), + $form['human_name'] = array( + '#type' => 'textfield', + '#title' => t('View name'), + '#required' => TRUE, + '#size' => 32, + '#default_value' => !empty($form_state['view']) ? $form_state['view']->human_name : '', + '#maxlength' => 255, + ); + $form['name'] = array( + '#type' => 'machine_name', + '#maxlength' => 32, + '#machine_name' => array( + 'exists' => 'views_get_view', + 'source' => array('human_name'), ), - '#default_value' => 'all', + '#description' => t('A unique machine-readable name for this View. It must only contain lowercase letters, numbers, and underscores.'), ); - $status = array( - '0' => t('Disabled'), - '1' => t('Enabled'), + $form['description_enable'] = array( + '#type' => 'checkbox', + '#title' => t('Description'), ); - $form['status'] = array( - '#type' => 'select', - '#title' => t('Status'), - '#options' => array_merge($all, $status), - '#default_value' => 'all', + $form['description'] = array( + '#type' => 'textfield', + '#title' => t('Provide description'), + '#title_display' => 'invisible', + '#size' => 64, + '#default_value' => !empty($form_state['view']) ? $form_state['view']->description : '', + '#dependency' => array( + 'edit-description-enable' => array(1), + ), ); - $bases = array(); - foreach (views_fetch_base_tables() as $table => $info) { - $bases[$table] = $info['title']; - } + // Create a wrapper for the entire dynamic portion of the form. Everything + // that can be updated by AJAX goes somewhere inside here. For example, this + // is needed by "Show" dropdown (below); it changes the base table of the + // view and therefore potentially requires all options on the form to be + // dynamically updated. + $form['displays'] = array(); + + // Create the part of the form that allows the user to select the basic + // properties of what the view will display. + $form['displays']['show'] = array( + '#type' => 'fieldset', + '#tree' => TRUE, + '#attributes' => array('class' => array('container-inline')), + ); - $form['base'] = array( + // Create the "Show" dropdown, which allows the base table of the view to be + // selected. + $wizard_plugins = views_ui_get_wizards(); + $options = array(); + foreach ($wizard_plugins as $key => $w) { + $options[$key] = $w['title']; + } + $form['displays']['show']['wizard_key'] = array( '#type' => 'select', - '#title' => t('Type'), - '#options' => array_merge($all, $bases), - '#default_value' => 'all', + '#title' => t('Show'), + '#options' => $options, + ); + $show_form = &$form['displays']['show']; + $show_form['wizard_key']['#default_value'] = views_ui_get_selected($form_state, array('show', 'wizard_key'), 'node', $show_form['wizard_key']); + // Changing this dropdown updates the entire content of $form['displays'] via + // AJAX. + views_ui_add_ajax_trigger($show_form, 'wizard_key', array('displays')); + + // Build the rest of the form based on the currently selected wizard plugin. + $wizard_key = $show_form['wizard_key']['#default_value']; + $get_instance = $wizard_plugins[$wizard_key]['get_instance']; + $wizard_instance = $get_instance($wizard_plugins[$wizard_key]); + $form = $wizard_instance->build_form($form, $form_state); + + $form['save'] = array( + '#type' => 'submit', + '#value' => t('Save & exit'), + '#validate' => array('views_ui_wizard_form_validate'), + '#submit' => array('views_ui_add_form_save_submit'), + ); + $form['continue'] = array( + '#type' => 'submit', + '#value' => t('Continue & edit'), + '#validate' => array('views_ui_wizard_form_validate'), + '#submit' => array('views_ui_add_form_store_edit_submit'), + '#process' => array_merge(array('views_ui_default_button'), element_info_property('submit', '#process', array())), + ); + $form['cancel'] = array( + '#type' => 'submit', + '#value' => t('Cancel'), + '#submit' => array('views_ui_add_form_cancel_submit'), + '#limit_validation_errors' => array(), ); - $tags = array(); + return $form; +} - $extras = array(); - if (isset($form_state['views'])) { - foreach ($form_state['views'] as $name => $view) { - if (!empty($view->tag)) { - $tags[$view->tag] = $view->tag; - } +/** + * Gets the current value of a #select element, from within a form constructor function. + * + * This function is intended for use in highly dynamic forms (in particular the + * add view wizard) which are rebuilt in different ways depending on which + * triggering element (AJAX or otherwise) was most recently fired. For example, + * sometimes it is necessary to decide how to build one dynamic form element + * based on the value of a different dynamic form element that may not have + * even been present on the form the last time it was submitted. This function + * takes care of resolving those conflicts and gives you the proper current + * value of the requested #select element. + * + * By necessity, this function sometimes uses non-validated user input from + * $form_state['input'] in making its determination. Although it performs some + * minor validation of its own, it is not complete. The intention is that the + * return value of this function should only be used to help decide how to + * build the current form the next time it is reloaded, not to be saved as if + * it had gone through the normal, final form validation process. Do NOT use + * the results of this function for any other purpose besides deciding how to + * build the next version of the form. + * + * @param $form_state + * The standard associative array containing the current state of the form. + * @param $parents + * An array of parent keys that point to the part of the submitted form + * values that are expected to contain the element's value (in the case where + * this form element was actually submitted). In a simple case (assuming + * #tree is TRUE throughout the form), if the select element is located in + * $form['wrapper']['select'], so that the submitted form values would + * normally be found in $form_state['values']['wrapper']['select'], you would + * pass array('wrapper', 'select') for this parameter. + * @param $default_value + * The default value to return if the #select element does not currently have + * a proper value set based on the submitted input. + * @param $element + * An array representing the current version of the #select element within + * the form. + * + * @return + * The current value of the #select element. A common use for this is to feed + * it back into $element['#default_value'] so that the form will be rendered + * with the correct value selected. + */ +function views_ui_get_selected($form_state, $parents, $default_value, $element) { + // For now, don't trust this to work on anything but a #select element. + if (!isset($element['#type']) || $element['#type'] != 'select' || !isset($element['#options'])) { + return $default_value; + } + + // If there is a user-submitted value for this element that matches one of + // the currently available options attached to it, use that. We need to check + // $form_state['input'] rather than $form_state['values'] here because the + // triggering element often has the #limit_validation_errors property set to + // prevent unwanted errors elsewhere on the form. This means that the + // $form_state['values'] array won't be complete. We could make it complete + // by adding each required part of the form to the #limit_validation_errors + // property individually as the form is being built, but this is difficult to + // do for a highly dynamic and extensible form. This method is much simpler. + if (!empty($form_state['input'])) { + $key_exists = NULL; + $submitted = drupal_array_get_nested_value($form_state['input'], $parents, $key_exists); + // Check that the user-submitted value is one of the allowed options before + // returning it. This is not a substitute for actual form validation; + // rather it is necessary because, for example, the same select element + // might have #options A, B, and C under one set of conditions but #options + // D, E, F under a different set of conditions. So the form submission + // might have occurred with option A selected, but when the form is rebuilt + // option A is no longer one of the choices. In that case, we don't want to + // use the value that was submitted anymore but rather fall back to the + // default value. + if ($key_exists && in_array($submitted, array_keys($element['#options']))) { + return $submitted; } } - asort($tags); + // Fall back on returning the default value if nothing was returned above. + return $default_value; +} - $form['tag'] = array( - '#type' => 'select', - '#title' => t('Tag'), - '#options' => array_merge($all, $none, $tags), - '#default_value' => 'all', +/** + * Converts a form element in the add view wizard to be AJAX-enabled. + * + * This function takes a form element and adds AJAX behaviors to it such that + * changing it triggers another part of the form to update automatically. It + * also adds a submit button to the form that appears next to the triggering + * element and that duplicates its functionality for users who do not have + * JavaScript enabled (the button is automatically hidden for users who do have + * JavaScript). + * + * To use this function, call it directly from your form builder function + * immediately after you have defined the form element that will serve as the + * JavaScript trigger. Calling it elsewhere (such as in hook_form_alter()) may + * mean that the non-JavaScript fallback button does not appear in the correct + * place in the form. + * + * @param $wrapping_element + * The element whose child will server as the AJAX trigger. For example, if + * $form['some_wrapper']['triggering_element'] represents the element which + * will trigger the AJAX behavior, you would pass $form['some_wrapper'] for + * this parameter. + * @param $trigger_key + * The key within the wrapping element that identifies which of its children + * serves as the AJAX trigger. In the above example, you would pass + * 'triggering_element' for this parameter. + * @param $refresh_parents + * An array of parent keys that point to the part of the form that will be + * refreshed by AJAX. For example, if triggering the AJAX behavior should + * cause $form['dynamic_content']['section'] to be refreshed, you would pass + * array('dynamic_content', 'section') for this parameter. + */ +function views_ui_add_ajax_trigger(&$wrapping_element, $trigger_key, $refresh_parents) { + $seen_ids = &drupal_static(__FUNCTION__ . ':seen_ids', array()); + $seen_buttons = &drupal_static(__FUNCTION__ . ':seen_buttons', array()); + + // Add the AJAX behavior to the triggering element. + $triggering_element = &$wrapping_element[$trigger_key]; + $triggering_element['#ajax']['callback'] = 'views_ui_ajax_update_form'; + // We do not use drupal_html_id() to get an ID for the AJAX wrapper, because + // it remembers IDs across AJAX requests (and won't reuse them), but in our + // case we need to use the same ID from request to request so that the + // wrapper can be recognized by the AJAX system and its content can be + // dynamically updated. So instead, we will keep track of duplicate IDs + // (within a single request) on our own, later in this function. + $triggering_element['#ajax']['wrapper'] = 'edit-view-' . implode('-', $refresh_parents) . '-wrapper'; + + // Add a submit button for users who do not have JavaScript enabled. It + // should be displayed next to the triggering element on the form. + $button_key = $trigger_key . '_trigger_update'; + $wrapping_element[$button_key] = array( + '#type' => 'submit', + // Hide this button when JavaScript is enabled. + '#attributes' => array('class' => array('js-hide')), + '#submit' => array('views_ui_nojs_submit'), + // Add a process function to limit this button's validation errors to the + // triggering element only. We have to do this in #process since until the + // form API has added the #parents property to the triggering element for + // us, we don't have any (easy) way to find out where its submitted values + // will eventually appear in $form_state['values']. + '#process' => array_merge(array('views_ui_add_limited_validation'), element_info_property('submit', '#process', array())), + // Add an after-build function that inserts a wrapper around the region of + // the form that needs to be refreshed by AJAX (so that the AJAX system can + // detect and dynamically update it). This is done in #after_build because + // it's a convenient place where we have automatic access to the complete + // form array, but also to minimize the chance that the HTML we add will + // get clobbered by code that runs after we have added it. + '#after_build' => array_merge(element_info_property('submit', '#after_build', array()), array('views_ui_add_ajax_wrapper')), ); - - $displays = array(); - foreach (views_fetch_plugin_data('display') as $id => $info) { - if (!empty($info['admin'])) { - $displays[$id] = $info['admin']; + // Copy #weight and #access from the triggering element to the button, so + // that the two elements will be displayed together. + foreach (array('#weight', '#access') as $property) { + if (isset($triggering_element[$property])) { + $wrapping_element[$button_key][$property] = $triggering_element[$property]; } } - - asort($displays); - - $form['display'] = array( - '#type' => 'select', - '#title' => t('Displays'), - '#options' => array_merge($all, $displays), - '#default_value' => 'all', - ); - - $form['order'] = array( - '#type' => 'select', - '#title' => t('Sort by'), - '#options' => array( - 'name' => t('Name'), - 'title' => t('Title'), - 'tag' => t('Tag'), - 'path' => t('Path'), - 'type' => t('Type'), - 'desc' => t('Description'), - ), - '#default_value' => 'name', - ); - - $form['sort'] = array( - '#type' => 'select', - '#title' => t('Order'), - '#options' => array( - 'asc' => t('Up'), - 'desc' => t('Down'), - ), - '#default_value' => 'asc', - ); - - // Autosubmit all form elements. - ctools_add_js('auto-submit'); - $form['#attributes']['class'][] = 'ctools-auto-submit-full-form'; - - $form['submit'] = array( - '#name' => '', // so it won't in the $_GET args - '#type' => 'submit', - '#id' => 'edit-views-apply', - '#value' => t('Apply'), - '#attributes' => array('class' => array('ctools-use-ajax', 'ctools-auto-submit-click')), + // For easiest integration with the form API and the testing framework, we + // always give the button a unique #value, rather than playing around with + // #name. + $button_title = !empty($triggering_element['#title']) ? $triggering_element['#title'] : $trigger_key; + if (empty($seen_buttons[$button_title])) { + $wrapping_element[$button_key]['#value'] = t('Update "@title" choice', array( + '@title' => $button_title, + )); + $seen_buttons[$button_title] = 1; + } + else { + $wrapping_element[$button_key]['#value'] = t('Update "@title" choice (@number)', array( + '@title' => $button_title, + '@number' => ++$seen_buttons[$button_title], + )); + } + + // Attach custom data to the triggering element and submit button, so we can + // use it in both the process function and AJAX callback. + $ajax_data = array( + 'wrapper' => $triggering_element['#ajax']['wrapper'], + 'trigger_key' => $trigger_key, + 'refresh_parents' => $refresh_parents, + // Keep track of duplicate wrappers so we don't add the same wrapper to the + // page more than once. + 'duplicate_wrapper' => !empty($seen_ids[$triggering_element['#ajax']['wrapper']]), ); + $seen_ids[$triggering_element['#ajax']['wrapper']] = TRUE; + $triggering_element['#views_ui_ajax_data'] = $ajax_data; + $wrapping_element[$button_key]['#views_ui_ajax_data'] = $ajax_data; +} - if (!empty($_SESSION['views']['#admin'])) { - $form['reset'] = array( - '#type' => 'submit', - '#id' => 'edit-views-reset', - '#value' => t('Reset'), - ); +/** + * Processes a non-JavaScript fallback submit button to limit its validation errors. + */ +function views_ui_add_limited_validation($element, &$form_state) { + // Retrieve the AJAX triggering element so we can determine its parents. (We + // know it's at the same level of the complete form array as the submit + // button, so all we have to do to find it is swap out the submit button's + // last array parent.) + $array_parents = $element['#array_parents']; + array_pop($array_parents); + $array_parents[] = $element['#views_ui_ajax_data']['trigger_key']; + $ajax_triggering_element = drupal_array_get_nested_value($form_state['complete form'], $array_parents); + + // Limit this button's validation to the AJAX triggering element, so it can + // update the form for that change without requiring that the rest of the + // form be filled out properly yet. + $element['#limit_validation_errors'] = array($ajax_triggering_element['#parents']); + + // If we are in the process of a form submission and this is the button that + // was clicked, the form API workflow in form_builder() will have already + // copied it to $form_state['triggering_element'] before our #process + // function is run. So we need to make the same modifications in $form_state + // as we did to the element itself, to ensure that #limit_validation_errors + // will actually be set in the correct place. + if (!empty($form_state['triggering_element'])) { + $clicked_button = &$form_state['triggering_element']; + if ($clicked_button['#name'] == $element['#name'] && $clicked_button['#value'] == $element['#value']) { + $clicked_button['#limit_validation_errors'] = $element['#limit_validation_errors']; + } } - $form['#token'] = FALSE; - return $form; + return $element; } /** - * Page callback for the live preview. + * After-build function that adds a wrapper to a form region (for AJAX refreshes). * - * @todo make this use a template + * This function inserts a wrapper around the region of the form that needs to + * be refreshed by AJAX, based on information stored in the corresponding + * submit button form element. */ -function views_ui_preview($js, $view) { - // Take off the items we know so that we can have just the args passed - // in for later use. - $func_args = func_get_args(); - array_shift($func_args); // $js - array_shift($func_args); // $view - $display_id = (count($func_args)) ? array_shift($func_args) : 'default'; - - $form_state = array( - 'display_id' => $display_id, - 'view_args' => $func_args ? implode('/', $func_args) : '', - 'rerender' => TRUE, - 'no_redirect' => TRUE, - 'view' => &$view, - 'ajax' => $js, - 'build_info' => array( - 'args' => array(), - ), - ); +function views_ui_add_ajax_wrapper($element, &$form_state) { + // Don't add the wrapper <div> if the same one was already inserted on this + // form. + if (empty($element['#views_ui_ajax_data']['duplicate_wrapper'])) { + // Find the region of the complete form that needs to be refreshed by AJAX. + // This was earlier stored in a property on the element. + $complete_form = &$form_state['complete form']; + $refresh_parents = $element['#views_ui_ajax_data']['refresh_parents']; + $refresh_element = drupal_array_get_nested_value($complete_form, $refresh_parents); + + // The HTML ID that AJAX expects was also stored in a property on the + // element, so use that information to insert the wrapper <div> here. + $id = $element['#views_ui_ajax_data']['wrapper']; + $refresh_element += array( + '#prefix' => '', + '#suffix' => '', + ); + $refresh_element['#prefix'] = '<div id="' . $id . '" class="views-ui-ajax-wrapper">' . $refresh_element['#prefix']; + $refresh_element['#suffix'] .= '</div>'; - $form = drupal_build_form('views_ui_preview_form', $form_state); - $output = drupal_render($form); - $args = array(); - if (isset($form_state['view_args']) && $form_state['view_args'] !== '') { - $args = explode('/', $form_state['view_args']); + // Copy the element that needs to be refreshed back into the form, with our + // modifications to it. + drupal_array_set_nested_value($complete_form, $refresh_parents, $refresh_element); } - $errors = $view->validate(); - if ($errors === TRUE) { - $view->ajax = $js; - $view->live_preview = TRUE; - $view->set_exposed_input($_POST); + return $element; +} - // Store the current view URL for later use: - $view->set_display($form_state['display_id']); - $view->set_arguments($args); +/** + * Updates a part of the add view form via AJAX. + * + * @return + * The part of the form that has changed. + */ +function views_ui_ajax_update_form($form, $form_state) { + // The region that needs to be updated was stored in a property of the + // triggering element by views_ui_add_ajax_trigger(), so all we have to do is + // retrieve that here. + return drupal_array_get_nested_value($form, $form_state['triggering_element']['#views_ui_ajax_data']['refresh_parents']); +} - if ($view->display_handler->get_option('path')) { - $path = $view->get_url(); - } +/** + * Non-Javascript fallback for updating the add view form. + */ +function views_ui_nojs_submit($form, &$form_state) { + $form_state['rebuild'] = TRUE; +} - // Make view links come back to preview. - $view->override_path = 'admin/structure/views/nojs/preview/' . $view->name . '/' . $form_state['display_id']; +/** + * Validate the add view form. + */ +function views_ui_wizard_form_validate($form, &$form_state) { + $w = views_ui_get_wizard($form_state['values']['show']['wizard_key']); + $form_state['wizard'] = $w; + $get_instance = $w['get_instance']; + $form_state['wizard_instance'] = $get_instance($w); + $errors = $form_state['wizard_instance']->validate($form, $form_state); + foreach ($errors as $name => $message) { + form_set_error($name, $message); + } +} - // also override $_GET['q'] so we get the pager - $_GET['q'] = $view->override_path; - if ($form_state['view_args']) { - $_GET['q'] .= '/' . $form_state['view_args']; +/** + * Process the add view form, 'save'. + */ +function views_ui_add_form_save_submit($form, &$form_state) { + try { + $view = $form_state['wizard_instance']->create_view($form, $form_state); + } + catch (ViewsWizardException $e) { + drupal_set_message($e->getMessage(), 'error'); + $form_state['redirect'] = 'admin/structure/views'; + } + $view->save(); + menu_rebuild(); + cache_clear_all('*', 'cache_views', TRUE); + cache_clear_all(); + $form_state['redirect'] = 'admin/structure/views'; + if (!empty($view->display['page'])) { + $display = $view->display['page']; + if ($display->handler->has_path()) { + $one_path = $display->handler->get_option('path'); + if (strpos($one_path, '%') === FALSE) { + $form_state['redirect'] = $one_path; // PATH TO THE VIEW IF IT HAS ONE + return; + } } + } + drupal_set_message(t('Your view was saved. You may edit it from the list below.')); +} - $preview = $view->preview($form_state['display_id'], $args); +/** + * Process the add view form, 'continue'. + */ +function views_ui_add_form_store_edit_submit($form, &$form_state) { + try { + $view = $form_state['wizard_instance']->create_view($form, $form_state); + } + catch (ViewsWizardException $e) { + drupal_set_message($e->getMessage(), 'error'); + $form_state['redirect'] = 'admin/structure/views'; + } + // Just cache it temporarily to edit it. + views_ui_cache_set($view); + $form_state['redirect'] = 'admin/structure/views/view/' . $view->name; +} - // Get information from the preview for display. - if (!empty($view->build_info['query'])) { - $rows = array(); - $query = $view->build_info['query']; - // Only the sql default class has a method getArguments. - $quoted = array(); +/** + * Cancel the add view form. + */ +function views_ui_add_form_cancel_submit($form, &$form_state) { + $form_state['redirect'] = 'admin/structure/views'; +} - if (get_class($view->query) == 'views_plugin_query_default') { - $arguments = $query->getArguments(); - $connection = Database::getConnection(); - foreach ((array)$query->arguments() as $key => $val) { - $quoted[$key] = $connection->quote($val); +/** + * Form element validation handler for a taxonomy autocomplete field. + * + * This allows a taxonomy autocomplete field to be validated outside the + * standard Field API workflow, without passing in a complete field widget. + * Instead, all that is required is that $element['#field_name'] contain the + * name of the taxonomy autocomplete field that is being validated. + * + * This function is currently not used for validation directly, although it + * could be. Instead, it is only used to store the term IDs and vocabulary name + * in the element value, based on the tags that the user typed in. + * + * @see taxonomy_autocomplete_validate() + */ +function views_ui_taxonomy_autocomplete_validate($element, &$form_state) { + $value = array(); + if ($tags = $element['#value']) { + // Get the machine names of the vocabularies we will search, keyed by the + // vocabulary IDs. + $field = field_info_field($element['#field_name']); + $vocabularies = array(); + if (!empty($field['settings']['allowed_values'])) { + foreach ($field['settings']['allowed_values'] as $tree) { + if ($vocabulary = taxonomy_vocabulary_machine_name_load($tree['vocabulary'])) { + $vocabularies[$vocabulary->vid] = $tree['vocabulary']; } } - $rows[] = array('<strong>' . t('Query') . '</strong>', '<pre>' . check_plain(strtr($query, $quoted)) . '</pre>'); - if (!empty($view->additional_queries)) { - $queries = '<strong>' . t('These queries were run during view rendering:') . '</strong>'; - foreach ($view->additional_queries as $query) { - if ($queries) { - $queries .= "\n"; - } - $queries .= t('[@time ms]', array('@time' => intval($query[1] * 100000) / 100)) . ' ' . $query[0]; - } - - $rows[] = array('<strong>' . t('Other queries') . '</strong>', '<pre>' . $queries . '</pre>'); + } + // Store the term ID of each (valid) tag that the user typed. + $typed_terms = drupal_explode_tags($tags); + foreach ($typed_terms as $typed_term) { + if ($terms = taxonomy_term_load_multiple(array(), array('name' => trim($typed_term), 'vid' => array_keys($vocabularies)))) { + $term = array_pop($terms); + $value['tids'][] = $term->tid; } + } + // Store the term IDs along with the name of the vocabulary. Currently + // Views (as well as the Field UI) assumes that there will only be one + // vocabulary, although technically the API allows there to be more than + // one. + if (!empty($value['tids'])) { + $value['tids'] = array_unique($value['tids']); + $value['vocabulary'] = array_pop($vocabularies); + } + } + form_set_value($element, $value, $form_state); +} - $rows[] = array('<strong>' . t('Title') . '</strong>', filter_xss_admin($view->get_title())); - if (isset($path)) { - $path = l($path, $path); - } - else { - $path = t('This display has no path.'); - } +/** + * Theme function; returns basic administrative information about a view. + * + * TODO: template + preprocess + */ +function theme_views_ui_view_info($variables) { + $view = $variables['view']; + $title = $view->get_human_name(); - $rows[] = array('<strong>' . t('Path') . '</strong>', $path); + $displays = _views_ui_get_displays_list($view); + $displays = empty($displays) ? t('None') : format_plural(count($displays), 'Display', 'Displays') . ': ' . '<em>' . implode(', ', $displays) . '</em>'; - $rows[] = array('<strong>' . t('Query build time') . '</strong>', t('@time ms', array('@time' => intval($view->build_time * 100000) / 100))); - $rows[] = array('<strong>' . t('Query execute time') . '</strong>', t('@time ms', array('@time' => intval($view->execute_time * 100000) / 100))); - $rows[] = array('<strong>' . t('View render time') . '</strong>', t('@time ms', array('@time' => intval($view->render_time * 100000) / 100))); - drupal_alter('views_preview_info', $rows, $view); + switch ($view->type) { + case t('Default'): + default: + $type = t('In code'); + break; - $info = theme('table', array('rows' => $rows)); - } - else { - $info = theme('table', array('rows' => array(array('<strong>' . t('Query') . '</strong>', t('No query was run'))))); - } - } - else { - foreach ($errors as $error) { - drupal_set_message($error, 'error'); - } - $preview = t('Unable to preview due to validation errors.'); - $info = ''; + case t('Normal'): + $type = t('In database'); + break; + + case t('Overridden'): + $type = t('Database overriding code'); } - $info = '<div class="views-query-info">' . $info . '</div>'; + $output = ''; + $output .= '<div class="views-ui-view-title">' . $title . "</div>\n"; + $output .= '<div class="views-ui-view-displays">' . $displays . "</div>\n"; + $output .= '<div class="views-ui-view-storage">' . $type . "</div>\n"; + $output .= '<div class="views-ui-view-base">' . t('Type') . ': ' . $variables['base']. "</div>\n"; + return $output; +} + +/** + * Page to delete a view. + */ +function views_ui_break_lock_confirm($form, &$form_state, $view) { + $form_state['view'] = &$view; + $form = array(); - if (variable_get('views_ui_query_on_top', FALSE)) { - $output .= $info . $preview; + if (empty($view->locked)) { + return t('There is no lock on view %view to break.', array('%name' => $view->name)); } - else { - $output .= $preview . $info; + + $cancel = 'admin/structure/views/view/' . $view->name . '/edit'; + if (!empty($_REQUEST['cancel'])) { + $cancel = $_REQUEST['cancel']; } - if (!$js) { - views_add_css('views-admin'); - drupal_set_title($view->get_title()); - return $output; + $account = user_load($view->locked->uid); + return confirm_form($form, + t('Are you sure you want to break the lock on view %name?', + array('%name' => $view->name)), + $cancel, + t('By breaking this lock, any unsaved changes made by !user will be lost!', array('!user' => theme('username', array('account' => $account)))), + t('Break lock'), + t('Cancel')); +} + +/** + * Submit handler to break_lock a view. + */ +function views_ui_break_lock_confirm_submit(&$form, &$form_state) { + ctools_object_cache_clear_all('view', $form_state['view']->name); + $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->name . '/edit'; + drupal_set_message(t('The lock has been broken and you may now edit this view.')); +} + +/** + * Page callback for the Edit View page. + */ +function views_ui_edit_page($view, $display_id = NULL) { + $display_id = views_ui_edit_page_display($view, $display_id); + if (!in_array($display_id, array(MENU_ACCESS_DENIED, MENU_NOT_FOUND))) { + $build = drupal_get_form('views_ui_edit_form', $view, $display_id); } else { - $commands = array(); - if (!empty($view->js_settings)) { - $commands[] = ajax_command_settings($view->js_settings); - } - $display = ''; - if ($messages = theme('status_messages')) { - $display = '<div class="views-messages">' . $messages . '</div>'; + $build = $display_id; + } + + return $build; +} + +/** + * Helper function to return the used display_id for the edit page + * + * This function handles access to the display. + */ +function views_ui_edit_page_display($view, $display_id) { + // Determine the displays available for editing. + if ($tabs = views_ui_edit_page_display_tabs($view)) { + // If a display isn't specified, use the first one. + if (empty($display_id)) { + foreach ($tabs as $id => $tab) { + if (!isset($tab['#access']) || $tab['#access']) { + $display_id = $id; + break; + } + } } - $display .= $output; - if ($display) { - $commands[] = ajax_command_html('div#views-live-preview', $display); + // If a display is specified, but we don't have access to it, return + // an access denied page. + if ($display_id && (!isset($tabs[$display_id]) || (isset($tabs[$display_id]['#access']) && !$tabs[$display_id]['#access']))) { + return MENU_ACCESS_DENIED; } - return $js ? array('#type' => 'ajax', '#commands' => $commands) : $commands; + + return $display_id; } + elseif ($display_id) { + return MENU_ACCESS_DENIED; + } + else { + $display_id = NULL; + } + + return $display_id; } /** - * Form for generating argument information for the live preview. + * Form builder callback for editing a View. + * + * @todo Remove as many #prefix/#suffix lines as possible. Use #theme_wrappers + * instead. + * + * @todo Rename to views_ui_edit_view_form(). See that function for the "old" + * version. */ -function views_ui_preview_form($form, &$form_state) { - $view = &$form_state['view']; - $view->init_display(); - $options = array(); - foreach ($view->display as $id => $display) { - $options[$id] = $display->display_title; +function views_ui_edit_form($form, &$form_state, $view, $display_id = NULL) { + // Do not allow the form to be cached, because $form_state['view'] can become + // stale between page requests. + // @see views_ui_ajax_get_form() for how this affects #ajax. + // @todo To remove this and allow the form to be cacheable: + // - Change $form_state['view'] to $form_state['temporary']['view']. + // - Add a #process function to initialize $form_state['temporary']['view'] + // on cached form submissions. + // - Update ctools_include() to support cached forms, or else use + // form_load_include(). + $form_state['no_cache'] = TRUE; + + ctools_include('dependent'); + $form['#attached']['js'][] = ctools_attach_js('dependent'); + $form['#attached']['js'][] = ctools_attach_js('collapsible-div'); + + $form['#tree'] = TRUE; + // @todo When more functionality is added to this form, cloning here may be + // too soon. But some of what we do with $view later in this function + // results in making it unserializable due to PDO limitations. + $form_state['view'] = clone($view); + + $form['#attached']['library'][] = array('system', 'ui.tabs'); + $form['#attached']['library'][] = array('system', 'ui.dialog'); + $form['#attached']['library'][] = array('system', 'drupal.ajax'); + $form['#attached']['library'][] = array('system', 'jquery.form'); + // TODO: This should be getting added to the page when an ajax popup calls + // for it, instead of having to add it manually here. + $form['#attached']['js'][] = 'misc/tabledrag.js'; + + $form['#attached']['css'] = views_ui_get_admin_css(); + $module_path = drupal_get_path('module', 'views_ui'); + + $form['#attached']['js'][] = $module_path . '/js/views-admin.js'; + $form['#attached']['js'][] = array( + 'data' => array('views' => array('ajax' => array( + 'id' => '#views-ajax-body', + 'title' => '#views-ajax-title', + 'popup' => '#views-ajax-popup', + 'defaultForm' => views_ui_get_default_ajax_message(), + ))), + 'type' => 'setting', + ); + + $form += array( + '#prefix' => '', + '#suffix' => '', + ); + $form['#prefix'] = $form['#prefix'] . '<div class="views-edit-view views-admin clearfix">'; + $form['#suffix'] = '</div>' . $form['#suffix']; + + if (isset($view->locked) && is_object($view->locked)) { + $form['locked'] = array( + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('view-locked', 'messages', 'warning')), + '#markup' => t('This view is being edited by user !user, and is therefore locked from editing by others. This lock is !age old. Click here to <a href="!break">break this lock</a>.', array('!user' => theme('username', array('account' => user_load($view->locked->uid))), '!age' => format_interval(REQUEST_TIME - $view->locked->updated), '!break' => url('admin/structure/views/view/' . $view->name . '/break-lock'))), + ); + } + if (isset($view->vid) && $view->vid == 'new') { + $message = t('* All changes are stored temporarily. Click Save to make your changes permanent. Click Cancel to discard the view.'); + } + else { + $message = t('* All changes are stored temporarily. Click Save to make your changes permanent. Click Cancel to discard your changes.'); } - $form['#attributes'] = array( - 'class' => array('clearfix'), + $form['changed'] = array( + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('view-changed', 'messages', 'warning')), + '#markup' => $message, ); + if (empty($view->changed)) { + $form['changed']['#attributes']['class'][] = 'js-hide'; + } - $form['display_id'] = array( - '#type' => 'select', - '#title' => t('Display'), - '#options' => $options, - '#default_value' => $form_state['display_id'], - '#id' => 'preview-display-id', + $form['help_text'] = array( + '#prefix' => '<div>', + '#suffix' => '</div>', + '#markup' => t('Modify the display(s) of your view below or add new displays.'), ); - $form['args'] = array( - '#type' => 'textfield', - '#title' => t('Arguments'), - '#default_value' => $form_state['view_args'], - '#description' => t('Separate arguments with a / as though they were a URL path.'), - '#id' => 'preview-args', + $form['actions'] = array( + '#type' => 'actions', + '#weight' => 0, ); - $form['preview'] = array( + if (empty($view->changed)) { + $form['actions']['#attributes'] = array( + 'class' => array( + 'js-hide', + ), + ); + } + + $form['actions']['save'] = array( + '#type' => 'submit', + '#value' => t('Save'), + // Taken from the "old" UI. @TODO: Review and rename. + '#validate' => array('views_ui_edit_view_form_validate'), + '#submit' => array('views_ui_edit_view_form_submit'), + ); + $form['actions']['cancel'] = array( '#type' => 'submit', - '#value' => t('Preview'), - '#id' => 'preview-submit', + '#value' => t('Cancel'), + '#submit' => array('views_ui_edit_view_form_cancel'), ); - $form['live_preview'] = array( - '#type' => 'checkbox', - '#title' => t('Automatic live preview'), - '#default_value' => !variable_get('views_ui_disable_live_preview', 0), + $form['displays'] = array( + '#prefix' => '<h1 class="unit-title clearfix">' . t('Displays') . '</h1>' . "\n" . '<div class="views-displays">', + '#suffix' => '</div>', + ); + + $form['displays']['top']['#theme_wrappers'] = array('views_container'); + $form['displays']['top']['#attributes']['class'] = array('views-display-top'); + + // Extra actions for the display + $form['displays']['top']['extra_actions'] = array( + '#theme' => 'links__ctools_dropbutton', + '#attributes' => array( + 'id' => 'views-display-extra-actions', + 'class' => array( + 'horizontal', 'right', 'links', 'actions', + ), + ), + '#links' => array( + 'edit-details' => array( + 'title' => t('edit view name/description'), + 'href' => "admin/structure/views/nojs/edit-details/$view->name", + 'attributes' => array('class' => array('views-ajax-link')), + ), + 'analyze' => array( + 'title' => t('analyze view'), + 'href' => "admin/structure/views/view/$view->name/analyze", + ), + 'clone' => array( + 'title' => t('clone view'), + 'href' => "admin/structure/views/view/$view->name/clone", + ), + 'export' => array( + 'title' => t('export view'), + 'href' => "admin/structure/views/view/$view->name/export", + ), + ), ); + if (isset($view->type) && $view->type != t('Default')) { + if ($view->type == t('Overridden')) { + $form['displays']['top']['extra_actions']['#links']['revert'] = array( + 'title' => t('revert view'), + 'href' => "admin/structure/views/view/$view->name/revert", + 'query' => array('destination' => "admin/structure/views/view/$view->name"), + ); + } + else { + $form['displays']['top']['extra_actions']['#links']['delete'] = array( + 'title' => t('delete view'), + 'href' => "admin/structure/views/view/$view->name/delete", + ); + } + } + + // Determine the displays available for editing. + if ($tabs = views_ui_edit_page_display_tabs($view)) { + if ($display_id) { + $tabs[$display_id]['#active'] = TRUE; + } + $tabs['#prefix'] = '<h2 class="element-invisible">' . t('Secondary tabs') . '</h2><ul class="tabs secondary">'; + $tabs['#suffix'] = '</ul>'; + $form['displays']['top']['tabs'] = $tabs; + } + + // Buttons for adding a new display. + foreach (views_fetch_plugin_names('display') as $type => $label) { + $form['displays']['top']['add_display'][$type] = array( + '#type' => 'submit', + '#value' => t('Add !display', array('!display' => $label)), + '#limit_validation_errors' => array(), + '#submit' => array('views_ui_edit_form_submit_add_display', 'views_ui_edit_form_submit_delay_destination'), + '#attributes' => array('class' => array('add-display')), + // Allow JavaScript to remove the 'Add ' prefix from the button label when + // placing the button in a "Add" dropdown menu. + '#process' => array_merge(array('views_ui_form_button_was_clicked'), element_info_property('submit', '#process', array())), + '#values' => array(t('Add !display', array('!display' => $label)), $label), + ); + } + + // The rest requires a display to be selected. + if ($display_id) { + $form_state['display_id'] = $display_id; + + // The part of the page where editing will take place. + $view->set_display($display_id); + // This element is the ctools collapsible-div container for the display edit elements. + $form['displays']['settings'] = array( + '#theme_wrappers' => array('container'), + '#attributes' => array( + 'class' => array( + 'views-display-settings', + 'box-margin', + 'ctools-collapsible-container', + ), + ), + '#id' => 'edit-display-settings', + ); + $display_title = views_ui_get_display_label($view, $display_id, FALSE); + // Add a handle for the ctools collapsible-div. The handle is the title of the display + $form['displays']['settings']['tab_title']['#markup'] = '<h2 id="edit-display-settings-title" class="ctools-collapsible-handle">' . t('@display_title details', array('@display_title' => ucwords($display_title))) . '</h2>'; + // The ctools collapsible-div content + $form['displays']['settings']['settings_content']= array( + '#theme_wrappers' => array('container'), + '#id' => 'edit-display-settings-content', + '#attributes' => array( + 'class' => array( + 'ctools-collapsible-content', + ), + ), + ); + // Add the edit display content + $form['displays']['settings']['settings_content']['tab_content'] = views_ui_get_display_tab($view, $display_id); + $form['displays']['settings']['settings_content']['tab_content']['#theme_wrappers'] = array('container'); + $form['displays']['settings']['settings_content']['tab_content']['#attributes'] = array('class' => array('views-display-tab')); + $form['displays']['settings']['settings_content']['tab_content']['#id'] = 'views-tab-' . $display_id; + // Mark deleted displays as such. + if (!empty($view->display[$display_id]->deleted)) { + $form['displays']['settings']['settings_content']['tab_content']['#attributes']['class'][] = 'views-display-deleted'; + } + + // Add preview controls + $form['displays']['settings']['settings_content']['preview_controls'] = array( + '#theme_wrappers' => array('container'), + '#attributes' => array( + 'class' => array( + 'clearfix', + ), + ), + '#id' => 'edit-display-preview-controls', + ); + + // Add a checkbox controlling whether or not this display auto-previews. + $form['displays']['settings']['settings_content']['preview_controls']['live_preview'] = array( + '#type' => 'checkbox', + '#id' => 'edit-displays-live-preview', + '#title' => t('Auto preview'), + '#default_value' => variable_get('views_ui_always_live_preview', TRUE), + ); + + // Add the arguments textfield + $form['displays']['settings']['settings_content']['preview_controls']['view_args'] = array( + '#type' => 'textfield', + '#title' => t('Preview with contextual filters:'), + '#description' => t('Separate contextual filter values with a "/". For example, %example.', array('%example' => '40/12/10')), + '#id' => 'preview-args', + ); + + // Add the preview button + $form['displays']['settings']['settings_content']['preview_controls']['button'] = array( + '#type' => 'submit', + '#value' => t('Preview'), + '#attributes' => array('class' => array('arguments-preview')), + '#pre_render' => array('ctools_dependent_pre_render'), + '#prefix' => '<div id="preview-submit-wrapper">', + '#suffix' => '</div>', + '#id' => 'preview-submit', + '#submit' => array('views_ui_edit_form_submit_preview'), + '#ajax' => array( + 'path' => 'admin/structure/views/view/' . $view->name . '/edit/' . $display_id . '/ajax', + 'callback' => 'views_ui_preview_callback', + 'wrapper' => 'views-live-preview', + ), + // Make ENTER in arguments textfield (and other controls) submit the form + // as this button, not the Save button. + // @todo This only works for JS users. To make this work for nojs users, + // we may need to split Preview into a separate form. + '#process' => array_merge(array('views_ui_default_button'), element_info_property('submit', '#process', array())), + ); + + // Hide the button on the autopreview checkbox, but only based on a setting. + if (!variable_get('views_ui_always_live_preview_button', FALSE)) { + $form['displays']['settings']['settings_content']['preview_controls']['button']['#dependency'] = array( + 'edit-displays-live-preview' => array(0), + ); + } + + // The live preview. + // @todo: Figure out whether $view->preview and $view->editing might be enough already. + $view->views_ui_context = TRUE; + + $form['displays']['preview'] = array( + '#theme_wrappers' => array('container'), + '#id' => 'views-live-preview', + ); + + $form['displays']['preview']['preview'] = array(); + if (variable_get('views_ui_always_live_preview', TRUE) || !empty($form_state['show_preview']) || !empty($form_state['values']['displays']['settings']['settings_content']['preview_controls']['live_preview'])) { + $preview_args = isset($form_state['values']['displays']['settings']['settings_content']['preview_controls']['view_args']) ? $form_state['values']['displays']['settings']['settings_content']['preview_controls']['view_args'] : ''; + $preview_args = ($preview_args !== '') ? explode('/', $preview_args) : array(); + $form['displays']['preview']['preview'] += array( + '#type' => 'markup', + '#pre_render' => array_merge(array('views_ui_pre_render_preview'), element_info_property('markup', '#pre_render', array())), + '#view' => $view, + '#display_id' => $display_id, + '#preview_args' => $preview_args, + ); + } + + // The content of the popup dialog. + $form['ajax-area'] = array( + '#theme_wrappers' => array('container'), + '#id' => 'views-ajax-popup', + ); + $form['ajax-area']['ajax-title'] = array( + '#markup' => '<h2 id="views-ajax-title"></h2>', + ); + $form['ajax-area']['ajax-body'] = array( + '#theme_wrappers' => array('container'), + '#id' => 'views-ajax-body', + '#markup' => views_ui_get_default_ajax_message(), + ); + + // WYSIWYG does not yet work on AJAX returned content unless the editor + // libraries are loaded on the base page (http://drupal.org/node/356480). + // @todo Remove this when that issue is resolved. + if (module_exists('wysiwyg')) { + $form['dummy_text_format'] = array('#type' => 'text_format', '#prefix' => '<div style="display:none">', '#suffix' => '</div>'); + } + } - $form['#action'] = url("admin/structure/views/nojs/preview/$view->name"); return $form; } +function views_ui_get_default_ajax_message() { + return '<div class="message">' . t("Click on an item to edit that item's details.") . '</div>'; +} + /** - * Submit the preview form. - * - * This just takes the data and stores it on the form state in a - * known location. The caller will be responsible for using it. + * Submit handler to add a display to a view. */ -function views_ui_preview_form_submit(&$form, &$form_state) { - $form_state['display_id'] = $form_state['values']['display_id']; - $form_state['view_args'] = $form_state['values']['args']; +function views_ui_edit_form_submit_add_display($form, &$form_state) { + $view = $form_state['view']; + + // Create the new display. + $parents = $form_state['triggering_element']['#parents']; + $display_type = array_pop($parents); + $display_id = $view->add_display($display_type); + views_ui_cache_set($view); + + // Redirect to the new display's edit page. + $form_state['redirect'] = 'admin/structure/views/view/' . $view->name . '/edit/' . $display_id; } /** - * Page callback to add a new view. + * Submit handler to duplicate a display for a view. */ -function views_ui_add_page() { - $form_state = array( - 'view' => NULL, - 'build_info' => array( - 'args' => array(), - ), - ); +function views_ui_edit_form_submit_duplicate_display($form, &$form_state) { + $view = $form_state['view']; + $display_id = $form_state['display_id']; + + // Create the new display. + $display = $view->display[$display_id]; + $new_display_id = $view->add_display($display->display_plugin); + $view->display[$new_display_id] = clone $display; + $view->display[$new_display_id]->id = $new_display_id; + views_ui_cache_set($view); - $form = drupal_build_form('views_ui_add_form', $form_state); - return drupal_render($form); + // Redirect to the new display's edit page. + $form_state['redirect'] = 'admin/structure/views/view/' . $view->name . '/edit/' . $new_display_id; } /** - * Page callback to add a new view. + * Submit handler to delete a display from a view. */ -function views_ui_clone_page($view) { - $form_state = array( - 'view' => $view->copy(), - 'build_info' => array( - 'args' => array(), - ), - ); +function views_ui_edit_form_submit_delete_display($form, &$form_state) { + $view = $form_state['view']; + $display_id = $form_state['display_id']; + + // Mark the display for deletion. + $view->display[$display_id]->deleted = TRUE; + views_ui_cache_set($view); - drupal_set_title(t('Clone view %view', array('%view' => $view->name)), PASS_THROUGH); - return drupal_render(drupal_build_form('views_ui_add_form', $form_state)); + // Redirect to the top-level edit page. The first remaining display will + // become the active display. + $form_state['redirect'] = 'admin/structure/views/view/' . $view->name; } /** - * Form constructor callback to create the views Add Form, phase 1. + * Submit handler to add a restore a removed display to a view. */ -function views_ui_add_form($form, &$form_state) { - $view = $form_state['view']; - $form = array(); +function views_ui_edit_form_submit_undo_delete_display($form, &$form_state) { + // Create the new display + $id = $form_state['display_id']; + $form_state['view']->display[$id]->deleted = FALSE; - $form['human_name'] = array( - '#type' => 'textfield', - '#title' => t('View name'), - '#description' => t('A descriptive name for this view. Spaces are allowed.'), - '#default_value' => $view ? $view->human_name : '', - '#required' => TRUE, - '#size' => 32, - '#maxlength' => 255, - ); + // Store in cache + views_ui_cache_set($form_state['view']); - $form['name'] = array( - '#type' => 'machine_name', - '#maxlength' => 32, - '#machine_name' => array( - 'exists' => 'views_get_view', - 'source' => array('human_name'), - ), - '#description' => t('A unique machine-readable name for this View. It must only contain lowercase letters, numbers, and underscores.'), - ); + // Redirect to the top-level edit page. + $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->name . '/edit/' . $id; +} - $form['description'] = array( - '#type' => 'textfield', - '#title' => t('View description'), - '#description' => t('This description will appear on the Views administrative UI to tell you what the view is about.'), - '#default_value' => $view ? $view->description : '', - '#maxlength' => 255, +/** + * Submit handler when Preview button is clicked. + */ +function views_ui_edit_form_submit_preview($form, &$form_state) { + // Rebuild the form with a pristine $view object. + $form_state['build_info']['args'][0] = views_ui_cache_load($form_state['view']->name); + $form_state['show_preview'] = TRUE; + $form_state['rebuild'] = TRUE; +} + +/** + * Submit handler for form buttons that do not complete a form workflow. + * + * The Edit View form is a multistep form workflow, but with state managed by + * the CTools object cache rather than $form_state['rebuild']. Without this + * submit handler, buttons that add or remove displays would redirect to the + * destination parameter (e.g., when the Edit View form is linked to from a + * contextual link). This handler can be added to buttons whose form submission + * should not yet redirect to the destination. + */ +function views_ui_edit_form_submit_delay_destination($form, &$form_state) { + if (isset($_GET['destination']) && $form_state['redirect'] !== FALSE) { + if (!isset($form_state['redirect'])) { + $form_state['redirect'] = $_GET['q']; + } + if (is_string($form_state['redirect'])) { + $form_state['redirect'] = array($form_state['redirect']); + } + $options = isset($form_state['redirect'][1]) ? $form_state['redirect'][1] : array(); + if (!isset($options['query']['destination'])) { + $options['query']['destination'] = $_GET['destination']; + } + $form_state['redirect'][1] = $options; + unset($_GET['destination']); + } +} + +/** + * Adds tabs for navigating across Displays when editing a View. + * + * This function can be called from hook_menu_local_tasks_alter() to implement + * these tabs as secondary local tasks, or it can be called from elsewhere if + * having them as secondary local tasks isn't desired. The caller is responsible + * for setting the active tab's #active property to TRUE. + */ +function views_ui_edit_page_display_tabs($view) { + $tabs = array(); + + // Create a tab for each display. + foreach ($view->display as $id => $display) { + $tabs[$id] = array( + '#theme' => 'menu_local_task', + '#link' => array( + 'title' => views_ui_get_display_label($view, $id), + 'href' => 'admin/structure/views/view/' . $view->name . '/edit/' . $id, + 'localized_options' => array(), + ), + ); + if (!empty($display->deleted)) { + $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'views-display-deleted-link'; + } + } + + // If the default display isn't supposed to be shown, don't display its tab. + if (!views_ui_show_default_display($view)) { + $tabs['default']['#access'] = FALSE; + } + + return $tabs; +} + +/** + * Controls whether or not the default display should have its own tab on edit. + */ +function views_ui_show_default_display($view) { + // Always show the default display for advanced users who prefer that mode. + $advanced_mode = variable_get('views_ui_show_master_display', FALSE); + // For other users, show the default display only if there are no others, and + // hide it if there's at least one "real" display. + $additional_displays = (count($view->display) == 1); + + return $advanced_mode || $additional_displays; +} + +/** + * Returns a renderable array representing the edit page for one display. + */ +function views_ui_get_display_tab($view, $display_id) { + $build = array(); + $display = $view->display[$display_id]; + $plugin = $display->handler->definition; + // If the plugin doesn't exist, display an error message instead of an edit + // page. + if (empty($plugin)) { + $title = isset($display->display_title) ? $display->display_title : t('Invalid'); + // @TODO: Improved UX for the case where a plugin is missing. + $build['#markup'] = t("Error: Display @display refers to a plugin named '@plugin', but that plugin is missing.", array('@display' => $display->id, '@plugin' => $display->display_plugin)); + } + // Build the content of the edit page. + else { + $build['details'] = views_ui_get_display_tab_details($view, $display); + } + // In AJAX context, views_ui_regenerate_tab() returns this outside of form + // context, so hook_form_views_ui_edit_form_alter() is insufficient. + drupal_alter('views_ui_display_tab', $build, $view, $display_id); + return $build; +} + +/** + * Helper function to get the display details section of the edit UI. + * + * @param $view + * @param $display + * + * @return array + * A renderable page build array. + */ +function views_ui_get_display_tab_details($view, $display) { + $display_title = views_ui_get_display_label($view, $display->id, FALSE); + $build = array( + '#theme_wrappers' => array('container'), + '#attributes' => array('id' => 'edit-display-settings-details',), ); - $form['tag'] = array( - '#type' => 'textfield', - '#title' => t('View tag'), - '#description' => t('Enter an optional tag for this view; it is used only to help sort views on the administrative page.'), - '#default_value' => $view ? $view->tag : '', - '#autocomplete_path' => 'admin/views/ajax/autocomplete/tag', + $build['top']['#theme_wrappers'] = array('container'); + $build['top']['#attributes']['id'] = 'edit-display-settings-top'; + $build['top']['#attributes']['class'] = array('views-ui-display-tab-actions', 'views-ui-display-tab-bucket', 'clearfix'); + + $plugin = views_fetch_plugin_data('display', $view->display[$display->id]->display_plugin); + // The following is for display purposes only. We need to determine if there is more than one button and wrap + // the buttons in a .ctools-dropbutton class if more than one is present. Otherwise, we'll just wrap the + // actions in the .ctools-button class. + $isDisplayDeleted = !empty($display->deleted); + $isDeletable = empty($plugin['no remove']); + // The master display cannot be cloned. + $isDefault = $display->id == 'default'; + + if (!$isDisplayDeleted && $isDeletable && !$isDefault) { + $prefix = '<div class="ctools-button ctools-dropbutton"><div class="ctools-link"><a href="#" class="ctools-twisty ctools-text">open</a></div><div class="ctools-content"><ul class="horizontal right actions">'; + $suffix = '</ul></div></div>'; + $itemElement = 'li'; + } + else { + $prefix = '<div class="ctools-button"><div class="ctools-content"><ul class="horizontal right actions">'; + $suffix = '</ul></div></div>'; + $itemElement = 'li'; + } + + // The Delete, Duplicate and Undo Delete buttons. + $build['top']['actions'] = array( + '#prefix' => $prefix, + '#suffix' => $suffix, ); - $base_tables = array(); - foreach (views_fetch_base_tables() as $table => $info) { - $base_tables[$table] = $info['title'] . '<div class="description">' . $info['description'] . '</div>'; + if (!$isDisplayDeleted) { + if (!$isDefault) { + $build['top']['actions']['duplicate'] = array( + '#type' => 'submit', + '#value' => t('clone') . " " . $display_title, + '#limit_validation_errors' => array(), + '#submit' => array('views_ui_edit_form_submit_duplicate_display', 'views_ui_edit_form_submit_delay_destination'), + '#prefix' => '<' . $itemElement . ' class="duplicate">', + "#suffix" => '</' . $itemElement . '>', + ); + } + if ($isDeletable) { + $build['top']['actions']['delete'] = array( + '#type' => 'submit', + '#value' => t('delete') . " " . $display_title, + '#limit_validation_errors' => array(), + '#submit' => array('views_ui_edit_form_submit_delete_display', 'views_ui_edit_form_submit_delay_destination'), + '#prefix' => '<' . $itemElement . ' class="delete">', + "#suffix" => '</' . $itemElement . '>', + ); + } + } + else { + $build['top']['actions']['undo_delete'] = array( + '#type' => 'submit', + '#value' => t('undo delete of') . " " . $display_title, + '#limit_validation_errors' => array(), + '#submit' => array('views_ui_edit_form_submit_undo_delete_display', 'views_ui_edit_form_submit_delay_destination'), + '#prefix' => '<' . $itemElement . ' class="undo-delete">', + "#suffix" => '</' . $itemElement . '>', + ); } - $form['base_table'] = array( - '#type' => 'radios', - '#title' => t('View type'), - '#description' => t('The view type is the primary table for which information is being retrieved. The view type controls what arguments, fields, sort criteria and filters are available, so once this is set it <strong>cannot be changed</strong>.'), - '#default_value' => $view ? $view->base_table : 'node', - '#options' => $base_tables, + // The area above the three columns. + $build['top']['display_title'] = array( + '#theme' => 'views_ui_display_tab_setting', + '#description' => t('Display name'), + '#link' => $display->handler->option_link(check_plain($display->display_title), 'display_title'), ); - if ($view) { - $form['base_table']['#disabled'] = TRUE; + $build['columns'] = array(); + $build['columns']['#theme_wrappers'] = array('container'); + $build['columns']['#attributes'] = array('id' => 'edit-display-settings-main', 'class' => array('clearfix', 'views-display-columns'),); + + $build['columns']['first']['#theme_wrappers'] = array('container'); + $build['columns']['first']['#attributes'] = array('class' => array('views-display-column', 'first')); + + $build['columns']['second']['#theme_wrappers'] = array('container'); + $build['columns']['second']['#attributes'] = array('class' => array('views-display-column', 'second')); + + $build['columns']['second']['settings'] = array(); + $build['columns']['second']['header'] = array(); + $build['columns']['second']['footer'] = array(); + $build['columns']['second']['pager'] = array(); + + // The third column buckets are wrapped in a CTools collapsible div + $build['columns']['third']['#theme_wrappers'] = array('container'); + $build['columns']['third']['#attributes'] = array('class' => array('views-display-column', 'third', 'ctools-collapsible-container', 'ctools-collapsible-remember')); + // Specify an id that won't change after AJAX requests, so ctools can keep + // track of the user's preferred collapsible state. Use the same id across + // different displays of the same view, so changing displays doesn't + // recollapse the column. + $build['columns']['third']['#attributes']['id'] = 'views-ui-advanced-column-' . $view->name; + // Collapse the div by default. + if (!variable_get('views_ui_show_advanced_column', FALSE)) { + $build['columns']['third']['#attributes']['class'][] = 'ctools-collapsed'; + } + $build['columns']['third']['advanced'] = array('#markup' => '<h3 class="ctools-collapsible-handle">' . t('Advanced') . '</h3>',); + $build['columns']['third']['collapse']['#theme_wrappers'] = array('container'); + $build['columns']['third']['collapse']['#attributes'] = array('class' => array('ctools-collapsible-content',),); + + // Each option (e.g. title, access, display as grid/table/list) fits into one + // of several "buckets," or boxes (Format, Fields, Sort, and so on). + $buckets = array(); + + // Fetch options from the display plugin, with a list of buckets they go into. + $options = array(); + $display->handler->options_summary($buckets, $options); + + // Place each option into its bucket. + foreach ($options as $id => $option) { + // Each option self-identifies as belonging in a particular bucket. + $buckets[$option['category']]['build'][$id] = views_ui_edit_form_get_build_from_option($id, $option, $view, $display); } - $form['submit'] = array( - '#type' => 'submit', - '#value' => t('Next'), - '#validate' => array('views_ui_add_form_validate'), - '#submit' => array('views_ui_add_form_submit'), - ); + // Place each bucket into the proper column. + foreach ($buckets as $id => $bucket) { + // Let buckets identify themselves as belonging in a column. + if (isset($bucket['column']) && isset($build['columns'][$bucket['column']])) { + $column = $bucket['column']; + } + // If a bucket doesn't pick one of our predefined columns to belong to, put + // it in the last one. + else { + $column = 'third'; + } + if (isset($bucket['build']) && is_array($bucket['build'])) { + // The third column is a CTools collapsible div, so + // the structure of the form is a little different for this column + if ($column === 'third') { + $build['columns'][$column]['collapse'][$id] = $bucket['build']; + $build['columns'][$column]['collapse'][$id]['#theme_wrappers'][] = 'views_ui_display_tab_bucket'; + $build['columns'][$column]['collapse'][$id]['#title'] = !empty($bucket['title']) ? $bucket['title'] : ''; + $build['columns'][$column]['collapse'][$id]['#name'] = !empty($bucket['title']) ? $bucket['title'] : $id; + } + else { + $build['columns'][$column][$id] = $bucket['build']; + $build['columns'][$column][$id]['#theme_wrappers'][] = 'views_ui_display_tab_bucket'; + $build['columns'][$column][$id]['#title'] = !empty($bucket['title']) ? $bucket['title'] : ''; + $build['columns'][$column][$id]['#name'] = !empty($bucket['title']) ? $bucket['title'] : $id; + } + } + } - return $form; + // Fetch the style plugin info so we know whether to list fields or not. + $style_plugin = $display->handler->get_plugin(); + $uses_fields = $style_plugin && $style_plugin->uses_fields(); + if ($uses_fields) { + $build['columns']['first']['fields'] = views_ui_edit_form_get_bucket('field', $view, $display); + } + $build['columns']['first']['filters'] = views_ui_edit_form_get_bucket('filter', $view, $display); + $build['columns']['first']['sorts'] = views_ui_edit_form_get_bucket('sort', $view, $display); + $build['columns']['second']['header'] = views_ui_edit_form_get_bucket('header', $view, $display); + $build['columns']['second']['footer'] = views_ui_edit_form_get_bucket('footer', $view, $display); + $build['columns']['third']['collapse']['arguments'] = views_ui_edit_form_get_bucket('argument', $view, $display); + $build['columns']['third']['collapse']['relationships'] = views_ui_edit_form_get_bucket('relationship', $view, $display); + $build['columns']['third']['collapse']['empty'] = views_ui_edit_form_get_bucket('empty', $view, $display); + + return $build; } /** - * Validate the add view form. + * Build a renderable array representing one option on the edit form. + * + * This function might be more logical as a method on an object, if a suitable + * object emerges out of refactoring. */ -function views_ui_add_form_validate($form, &$form_state) { - $name = $form_state['values']['name']; +function views_ui_edit_form_get_build_from_option($id, $option, $view, $display) { + $option_build = array(); + $option_build['#theme'] = 'views_ui_display_tab_setting'; - // View name must be alphanumeric or underscores, no other punctuation. - if (preg_match('/[^a-zA-Z0-9_]/', $name) || is_numeric($name)) { - form_error($form['name'], t('View name must be alphanumeric or underscores only, but cannot be numeric.')); + $option_build['#description'] = $option['title']; + + $option_build['#link'] = $display->handler->option_link($option['value'], $id, '', empty($option['desc']) ? '' : $option['desc']); + + $option_build['#links'] = array(); + if (!empty($option['links']) && is_array($option['links'])) { + foreach ($option['links'] as $link_id => $link_value) { + $option_build['#settings_links'][] = $display->handler->option_link($option['setting'], $link_id, 'views-button-configure', $link_value); + } } - // View name must already exist. - $view = views_get_view($form_state['values']['name']); - if ($view && $view->type != t('Default')) { - form_error($form['name'], t('You must use a unique name for this view.')); + if (!empty($display->handler->options['defaults'][$id])) { + $display_id = 'default'; + $option_build['#defaulted'] = TRUE; + } + else { + $display_id = $display->id; + if (!$display->handler->is_default_display()) { + if ($display->handler->defaultable_sections($id)) { + $option_build['#overridden'] = TRUE; + } + } } + $option_build['#attributes']['class'][] = drupal_clean_css_identifier($display_id . '-' . $id); + if (!empty($view->changed_sections[$display_id . '-' . $id])) { + $option_build['#changed'] = TRUE; + } + return $option_build; } -/** - * Process the add view form - */ -function views_ui_add_form_submit($form, &$form_state) { - $view = $form_state['view'] ? $form_state['view'] : views_new_view(); - $view->name = $form_state['values']['name']; - $view->human_name = $form_state['values']['human_name']; - $view->description = $form_state['values']['description']; - $view->tag = $form_state['values']['tag']; - $view->core = VERSION; - if (empty($form['base_table']['#disabled'])) { - $view->base_table = $form_state['values']['base_table']; +function template_preprocess_views_ui_display_tab_setting(&$variables) { + static $zebra = 0; + $variables['zebra'] = ($zebra % 2 === 0 ? 'odd' : 'even'); + $zebra++; + + // Put the main link to the left side + array_unshift($variables['settings_links'], $variables['link']); + $variables['settings_links'] = implode('<span class="views-ajax-link"> | </span>', $variables['settings_links']); + + // Add classes associated with this display tab to the overall list. + $variables['classes_array'] = array_merge($variables['classes_array'], $variables['class']); + + if (!empty($variables['defaulted'])) { + $variables['classes_array'][] = 'defaulted'; + } + if (!empty($variables['overridden'])) { + $variables['classes_array'][] = 'overridden'; + $variables['attributes_array']['title'][] = t('Overridden'); } - views_ui_cache_set($view); - $form_state['redirect'] ='admin/structure/views/edit/' . $view->name; + // Append a colon to the description, if requested. + if ($variables['description'] && $variables['description_separator']) { + $variables['description'] .= t(':'); + } } -/** - * Page to delete a view. - */ -function views_ui_delete_confirm($form, &$form_state, $view) { - $form_state['view'] = &$view; - $form = array(); +function template_preprocess_views_ui_display_tab_bucket(&$variables) { + $element = $variables['element']; - $cancel = 'admin/structure/views'; - if (!empty($_REQUEST['cancel'])) { - $cancel = $_REQUEST['cancel']; + $variables['item_help_icon'] = ''; + if (!empty($element['#item_help_icon'])) { + $variables['item_help_icon'] = render($element['#item_help_icon']); } - - if ($view->type == t('Overridden')) { - $title = t('Are you sure you want to revert the view %name?', array('%name' => $view->name)); - $desc = t('Reverting the view will delete the view that is in the database, reverting it to the original default view. Any changes you have made will be lost and cannot be recovered.'); - $button = t('Revert'); + if (!empty($element['#name'])) { + $variables['classes_array'][] = drupal_clean_css_identifier(strtolower($element['#name'])); } - else { - $title = t('Are you sure you want to delete the view %name?', array('%name' => $view->name)); - $desc = t('Deleting a view cannot be undone.'); - $button = t('Delete'); + if (!empty($element['#overridden'])) { + $variables['classes_array'][] = 'overridden'; + $variables['attributes_array']['title'][] = t('Overridden'); } - return confirm_form($form, - $title, - $cancel, - $desc, - $button, - t('Cancel')); + $variables['content'] = $element['#children']; + $variables['title'] = $element['#title']; + $variables['actions'] = !empty($element['#actions']) ? $element['#actions'] : ''; } -/** - * Submit handler to delete a view. - */ -function views_ui_delete_confirm_submit(&$form, &$form_state) { - $form_state['view']->delete(); - ctools_object_cache_clear('view', $form_state['view']->name); - drupal_set_message(t('The view has been deleted.')); - $form_state['redirect'] = 'admin/structure/views'; +function template_preprocess_views_ui_display_tab_column(&$variables) { + $element = $variables['element']; + + $variables['content'] = $element['#children']; + $variables['column'] = $element['#column']; } /** - * Page to delete a view. + * Move form elements into fieldsets for presentation purposes. + * + * Many views forms use #tree = TRUE to keep their values in a hierarchy for + * easier storage. Moving the form elements into fieldsets during form building + * would break up that hierarchy. Therefore, we wait until the pre_render stage, + * where any changes we make affect presentation only and aren't reflected in + * $form_state['values']. */ -function views_ui_break_lock_confirm($form, &$form_state, $view) { - $form_state['view'] = &$view; - $form = array(); - - if (empty($view->locked)) { - return t('There is no lock on view %view to break.', array('%name' => $view->name)); - } - - $cancel = 'admin/structure/views/edit/' . $view->name; - if (!empty($_REQUEST['cancel'])) { - $cancel = $_REQUEST['cancel']; +function views_ui_pre_render_add_fieldset_markup($form) { + foreach (element_children($form) as $key) { + $element = $form[$key]; + // In our form builder functions, we added an arbitrary #fieldset property + // to any element that belongs in a fieldset. If this form element has that + // property, move it into its fieldset. + if (isset($element['#fieldset']) && isset($form[$element['#fieldset']])) { + $form[$element['#fieldset']][$key] = $element; + // Remove the original element this duplicates. + unset($form[$key]); + } } - $account = user_load($view->locked->uid); - return confirm_form($form, - t('Are you sure you want to break the lock on view %name?', - array('%name' => $view->name)), - $cancel, - t('By breaking this lock, any unsaved changes made by !user will be lost!', array('!user' => theme('username', array('account' => $account)))), - t('Break lock'), - t('Cancel')); + return $form; } /** - * Submit handler to break_lock a view. + * Flattens the structure of an element containing the #flatten property. + * + * If a form element has #flatten = TRUE, then all of it's children + * get moved to the same level as the element itself. + * So $form['to_be_flattened'][$key] becomes $form[$key], and + * $form['to_be_flattened'] gets unset. */ -function views_ui_break_lock_confirm_submit(&$form, &$form_state) { - ctools_object_cache_clear_all('view', $form_state['view']->name); - $form_state['redirect'] = 'admin/structure/views/edit/' . $form_state['view']->name; - drupal_set_message(t('The lock has been broken and you may now edit this view.')); +function views_ui_pre_render_flatten_data($form) { + foreach (element_children($form) as $key) { + $element = $form[$key]; + if (!empty($element['#flatten'])) { + foreach (element_children($element) as $child_key) { + $form[$child_key] = $form[$key][$child_key]; + } + // All done, remove the now-empty parent. + unset($form[$key]); + } + } + + return $form; } /** - * The main view edit page + * Moves argument options into their place. + * + * When configuring the default argument behavior, almost each of the radio + * buttons has its own fieldset shown bellow it when the radio button is + * clicked. That fieldset is created through a custom form process callback. + * Each element that has #argument_option defined and pointing to a default + * behavior gets moved to the appropriate fieldset. + * So if #argument_option is specified as 'default', the element is moved + * to the 'default_options' fieldset. */ -function views_ui_edit_page($view) { - drupal_set_title(t('Edit view %view', array('%view' => $view->name)), PASS_THROUGH); - $output = theme('views_ui_edit_view', array('view' => $view)); - views_ui_check_advanced_help(); - return $output; +function views_ui_pre_render_move_argument_options($form) { + foreach (element_children($form) as $key) { + $element = $form[$key]; + if (!empty($element['#argument_option'])) { + $container_name = $element['#argument_option'] . '_options'; + if (isset($form['no_argument']['default_action'][$container_name])) { + $form['no_argument']['default_action'][$container_name][$key] = $element; + } + // Remove the original element this duplicates. + unset($form[$key]); + } + } + return $form; } /** - * Export a view for cut & paste. + * Custom form radios process function. + * + * Roll out a single radios element to a list of radios, + * using the options array as index. + * While doing that, create a container element underneath each option, which + * contains the settings related to that option. + * + * @see form_process_radios */ -function views_ui_export_page($form, &$form_state, $view) { - $code = $view->export(); - $lines = substr_count($code, "\n"); - $form['code'] = array( - '#type' => 'textarea', - '#title' => $view->name, - '#default_value' => $code, - '#rows' => $lines, - ); - return $form; +function views_ui_process_container_radios($element) { + if (count($element['#options']) > 0) { + foreach ($element['#options'] as $key => $choice) { + $element += array($key => array()); + // Generate the parents as the autogenerator does, so we will have a + // unique id for each radio button. + $parents_for_id = array_merge($element['#parents'], array($key)); + + $element[$key] += array( + '#type' => 'radio', + '#title' => $choice, + // The key is sanitized in drupal_attributes() during output from the + // theme function. + '#return_value' => $key, + '#default_value' => isset($element['#default_value']) ? $element['#default_value'] : NULL, + '#attributes' => $element['#attributes'], + '#parents' => $element['#parents'], + '#id' => drupal_html_id('edit-' . implode('-', $parents_for_id)), + '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL, + ); + $element[$key . '_options'] = array( + '#type' => 'container', + '#attributes' => array('class' => array('views-admin-dependent')), + ); + } + } + return $element; } -/** - * Import a view from cut & paste +/* + * Import a view from cut & paste. */ function views_ui_import_page($form, &$form_state) { $form['name'] = array( @@ -841,11 +1832,15 @@ function views_ui_import_page($form, &$form_state) { } /** - * Validate handler to import a view + * Validate handler to import a view. */ function views_ui_import_validate($form, &$form_state) { $view = ''; views_include('view'); + // Be forgiving if someone pastes views code that starts with '<?php'. + if (substr($form_state['values']['view'], 0, 5) == '<?php') { + $form_state['values']['view'] = substr($form_state['values']['view'], 5); + } ob_start(); eval($form_state['values']['view']); ob_end_clean(); @@ -934,41 +1929,12 @@ function views_ui_import_validate($form, &$form_state) { } /** - * Submit handler for view import + * Submit handler for view import. */ function views_ui_import_submit($form, &$form_state) { // Store in cache and then go to edit. views_ui_cache_set($form_state['view']); - $form_state['redirect'] = 'admin/structure/views/edit/' . $form_state['view']->name; -} - -/** - * The main edit view form, which is really just a save/cancel/delete button. - */ -function views_ui_edit_view_form($form, &$form_state, $view) { - $form['buttons']['save'] = array( - '#type' => 'submit', - '#value' => t('Save'), - '#validate' => array('views_ui_edit_view_form_validate'), - '#submit' => array('views_ui_edit_view_form_submit'), - ); - - $form['buttons']['cancel'] = array( - '#type' => 'submit', - '#value' => t('Cancel'), - '#submit' => array('views_ui_edit_view_form_cancel'), - ); - - if (is_numeric($view->vid)) { - $form['buttons']['delete'] = array( - '#type' => 'submit', - '#value' => $view->type == t('Overridden') ? t('Revert') : t('Delete'), - '#submit' => array('views_ui_edit_view_form_delete'), - ); - } - - $form_state['view'] = &$view; - return $form; + $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->name . '/edit'; } /** @@ -1002,6 +1968,8 @@ function views_ui_edit_view_form_submit($form, &$form_state) { foreach ($form_state['view']->display as $id => $display) { if (!empty($display->new_id)) { $form_state['view']->display[$id]->id = $display->new_id; + // Redirect the user to the renamed display to be sure that the page itself exists and doesn't throw errors. + $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->name . '/edit/' . $display->new_id; } } @@ -1037,321 +2005,26 @@ function views_ui_edit_view_form_cancel($form, &$form_state) { function views_ui_edit_view_form_delete($form, &$form_state) { unset($_REQUEST['destination']); // Redirect to the delete confirm page - $form_state['redirect'] = array('admin/structure/views/delete/' . $form_state['view']->name, array('query' => drupal_get_destination() + array('cancel' => 'admin/structure/views/edit/' . $form_state['view']->name))); -} - -/** - * Preprocess the view edit page. - */ -function template_preprocess_views_ui_edit_view(&$vars) { - $view = &$vars['view']; - ctools_include('dependent'); - - // The form has to be saved as variable because of strict warnings. - $form = drupal_get_form('views_ui_edit_view_form', $view); - $vars['save_button'] = drupal_render($form); - - $table = views_fetch_data($view->base_table); - $vars['base_table'] = !empty($table['table']['base']['title']) ? - $table['table']['base']['title'] : t('Unknown or missing table name'); - - views_include('tabs'); - $tabs = new views_tabset; - - $vars['message'] = '<div class="message">' . t("Click on an item to edit that item's details.") . '</div>'; - - if (!$view->set_display('default')) { - drupal_set_message(t('This view has a broken default display and cannot be used.'), 'error'); - } - - foreach ($view->display as $display) { - list($title, $body) = views_ui_display_tab($view, $display); - // The first display is the default. - $tabs->set($display->id, $title, $body); - } - - // This is the area that will render beneath the links - $form_state = array( - 'view' => &$view, - 'ajax' => FALSE, - 'build_info' => array( - 'args' => array(), - ), - 'no_cache' => TRUE, - ); - - $form = drupal_build_form('views_ui_add_display_form', $form_state); - $display_button = drupal_render($form); - $form = drupal_get_form('views_ui_analyze_view_button', $view); - $analyze_button = drupal_render($form); - $form = drupal_get_form('views_ui_reorder_displays_button', $view); - $reorder_button = drupal_render($form); - $tabs->add_extra($display_button . $reorder_button . $analyze_button); - - $vars['tabs'] = $tabs->render(); - - $form_state = array( - 'display_id' => 'default', - 'view_args' => '', - 'rerender' => FALSE, - 'no_redirect' => TRUE, - 'view' => &$view, - 'input' => array(), - 'build_info' => array( - 'args' => array(), - ), - ); - $preview_form = drupal_build_form('views_ui_preview_form', $form_state); - $vars['preview'] = drupal_render($preview_form); - - $vars['locked'] = NULL; - if (isset($view->locked) && is_object($view->locked)) { - $account = array(); - $account['account'] = user_load($view->locked->uid); - $account['name'] = $account['account']->name; - $vars['locked'] = theme('username', array('account' => $account['account'])); - $vars['lock_age'] = format_interval(REQUEST_TIME - $view->locked->updated); - $vars['break'] = url('admin/structure/views/break-lock/' . $view->name); - } - - $vars['quick_links_raw'] = array( - 'views-export' => array( - 'title' => t('Export'), - 'attributes' => array('title' => t("Export this view")), - 'href' => "admin/structure/views/export/$view->name", - ), - 'views-clone' => array( - 'title' => t('Clone'), - 'attributes' => array('title' => t("Create a copy of this view")), - 'href' => "admin/structure/views/clone/$view->name", - ), - ); - - $paths = array(); - foreach ($view->display as $id => $display) { - if (!empty($display->handler) && $display->handler->has_path()) { - $path = $display->handler->get_path(); - if (strpos($path, '%') === FALSE && !isset($paths[$path])) { - $vars['quick_links_raw']['views-view-' . $display->id] = array( - 'title' => t('View "@display"', array('@display' => $display->display_title)), - 'attributes' => array('title' => t("Go to the real page for this display")), - 'href' => $path, - ); - // Displays can have the same path; no point in showing more than one link. - $paths[$path] = TRUE; - } - } - } - - if (module_exists('contextual')) { - $build = array( - '#prefix' => '<div class="contextual-links-wrapper">', - '#suffix' => '</div>', - '#theme' => 'links__contextual', - '#links' => $vars['quick_links_raw'], - '#attributes' => array('class' => array('contextual-links')), - '#attached' => array( - 'library' => array(array('contextual', 'contextual-links')), - ), - ); - $vars['quick_links'] = drupal_render($build); - } - else { - $vars['quick_links'] = theme('links__views_quick_links', array('links' => $vars['quick_links_raw'])); - } - views_add_css('views-admin'); - views_add_js('ajax'); - drupal_add_library('system', 'jquery.form'); - - // Also add any js files required by plugins: - $plugins = views_fetch_plugin_data(); - foreach ($plugins as $type => $type_plugins) { - foreach ($type_plugins as $name => $plugin) { - if (!empty($plugin['js'])) { - foreach ($plugin['js'] as $file) { - drupal_add_js($file); - } - } - } - } - - $settings = array('views' => array('ajax' => array( - 'id' => '#views-ajax-pad', - 'title' => '#views-ajax-title', - 'defaultForm' => $vars['message'], - ))); - - drupal_add_js($settings, 'setting'); -} - -function template_preprocess_views_ui_edit_tab(&$vars) { - $view = $vars['view']; - $display = $vars['display']; - $plugin = $display->handler->definition; - - $top = $left = $middle = $right = ''; - - // If this form was submitted it was already handled, so force it not to - // submit again. - - $vars['remove'] = ''; - $vars['clone'] = ''; - if (empty($plugin['no remove'])) { - if (!empty($_POST['form_id']) && in_array($_POST['form_id'], array('views_ui_remove_display_form', 'views_ui_clone_display_form'))) { - unset($_POST['form_id']); - } - $form_state = array('view' => &$view, 'display_id' => $display->id, 'ajax' => FALSE, 'build_info' => array('args' => array())); - $remove_form = drupal_build_form('views_ui_remove_display_form', $form_state); - $clone_form = drupal_build_form('views_ui_clone_display_form', $form_state); - $vars['remove'] = drupal_render($remove_form); - $vars['clone'] = drupal_render($clone_form); - } - - // basic fields - $vars['title'] = check_plain($display->display_title); - $vars['description'] = check_plain($plugin['help']); - - // Special fields if this is the default display. - $vars['default'] = ($display->id == 'default'); - $vars['details_class'] = drupal_clean_css_identifier('details'); - if (!empty($view->changed_sections['details'])) { - $vars['details_changed'] = TRUE; - } - - foreach (array('human_name', 'tag', 'description') as $property) { - if (!empty($view->changed_sections[$property])) { - $vars['details_changed'][$property] = TRUE; - } - switch ($property) { - case 'human_name': - $title = t('Human name'); - break; - case 'tag': - $title = t('Tag'); - break; - case 'description': - $title = t('Description'); - break; - } - $value = empty($view->{$property}) ? t('None') : check_plain($view->{$property}); - $vars['details'][$property] = $title . ': ' . l($value, "admin/structure/views/nojs/$property/$view->name", array('attributes' => array('class' => 'views-ajax-link'))); - } - - // Calculate options from display plugin. - $options = $categories = array(); - $display->handler->options_summary($categories, $options); - - // Build all of the options we were returned and put them into the - // category data fields. - foreach ($options as $id => $option) { - if (empty($categories[$option['category']]['data'])) { - $categories[$option['category']]['data'] = array(); - } - $categories[$option['category']]['data'][$id] = array(); - $data = &$categories[$option['category']]['data'][$id]; - $data['content'] = ''; - $data['links'] = ''; - $data['overridden'] = FALSE; - $data['defaulted'] = FALSE; - - // If there are optional links, build them first so they float properly. - if (!empty($option['links'])) { - foreach ($option['links'] as $link_id => $link_value) { - $data['links'] .= $display->handler->option_link($link_value, $link_id, 'views-button-configure'); - } - } - if (!empty($option['title'])) { - $data['content'] .= $option['title'] . ': '; - } - - $data['content'] .= $display->handler->option_link($option['value'], $id, '', empty($option['desc']) ? '' : $option['desc']); - if (!empty($display->handler->options['defaults'][$id])) { - $display_id = 'default'; - $data['defaulted'] = TRUE; - } - else { - $display_id = $display->id; - if (!$display->handler->is_default_display()) { - if ($display->handler->defaultable_sections($id)) { - $data['overridden'] = TRUE; - } - } - } - $data['class'][] = drupal_clean_css_identifier($display_id . '-' . $id); - if (!empty($view->changed_sections[$display_id . '-' . $id])) { - $data['changed'] = TRUE; - } - } - - $vars['categories'] = $categories; - - // Add a help icon - if (isset($plugin['help topic']) && module_exists('advanced_help')) { - $vars['display_help_icon'] = theme('advanced_help_topic', array('module' => $plugin['module'], 'topic' => $plugin['help topic'])); - } - else { - $vars['display_help_icon'] = ''; - } - - // Fetch style plugin info because it has some effect on how/what we render. - $style_plugin = $display->handler->get_plugin(); - - $vars['fields'] = ''; - $vars['areas'] = array(); - foreach (array('header', 'footer', 'empty') as $area) { - $vars['areas'][$area] = theme('views_ui_edit_item', array( - 'type' => $area, 'view' => $view, 'display' => $display, - )); - } - $vars['fields'] = theme('views_ui_edit_item', array('type' => 'field', 'view' => $view, 'display' => $display, 'no_fields' => !($style_plugin && $style_plugin->uses_fields()))); - $vars['relationships'] = theme('views_ui_edit_item', array('type' => 'relationship', 'view' => $view, 'display' => $display)); - $vars['arguments'] = theme('views_ui_edit_item', array('type' => 'argument', 'view' => $view, 'display' => $display)); - $vars['filters'] = theme('views_ui_edit_item', array('type' => 'filter', 'view' => $view, 'display' => $display)); - $vars['sorts'] = theme('views_ui_edit_item', array('type' => 'sort', 'view' => $view, 'display' => $display)); -} - -/** - * Generate the summary output for a single display to render in a tab. - */ -function views_ui_display_tab($view, $display) { - if (isset($display->handler)) { - $plugin = $display->handler->definition; - } - if (empty($plugin)) { - $title = isset($display->display_title) ? $display->display_title : t('Invalid'); - return array($title, t("Error: Display @display refers to a plugin named '@plugin', but that plugin doesn't exist!", array('@display' => $display->id, '@plugin' => $display->display_plugin))); - - // @todo We can do a better 'plugin does not exist' tab. - } - - // The display should always be initialized prior to this call. - if (empty($display->handler)) { - return FALSE; - } - - $body = theme('views_ui_edit_tab', array('view' => $view, 'display' => $display)); - return array($display->display_title, $body); + $form_state['redirect'] = array('admin/structure/views/view/' . $form_state['view']->name . '/delete', array('query' => drupal_get_destination() + array('cancel' => 'admin/structure/views/view/' . $form_state['view']->name . '/edit'))); } /** * Add information about a section to a display. */ -function template_preprocess_views_ui_edit_item(&$vars) { - $type = $vars['type']; - $view = $vars['view']; - $display = $vars['display']; - +function views_ui_edit_form_get_bucket($type, $view, $display) { + $build = array( + '#theme_wrappers' => array('views_ui_display_tab_bucket'), + ); $types = views_object_types(); - $vars['overridden'] = FALSE; - $vars['defaulted'] = FALSE; - $vars['item_help_icon'] = module_exists('advanced_help') ? theme('advanced_help_topic', array('module' => 'views', 'topic' => $type)) : ''; - - if ($vars['no_fields']) { - $vars['title'] = $types[$type]['title']; - $vars['rearrange'] = NULL; - $vars['add'] = NULL; - return; + $build['#overridden'] = FALSE; + $build['#defaulted'] = FALSE; + if (module_exists('advanced_help')) { + $build['#item_help_icon'] = array( + '#theme' => 'advanced_help_topic', + '#module' => 'views', + '#topic' => $type, + ); } // Different types now have different rearrange forms, so we use this switch @@ -1359,32 +2032,68 @@ function template_preprocess_views_ui_edit_item(&$vars) { switch ($type) { case 'filter': $rearrange_url = "admin/structure/views/nojs/rearrange-$type/$view->name/$display->id/$type"; + $rearrange_text = t('And/Or'); + // TODO: Add another class to have another symbol for filter rearrange. + $class = 'icon compact rearrange'; break; default: $rearrange_url = "admin/structure/views/nojs/rearrange/$view->name/$display->id/$type"; + $rearrange_text = t('Sort'); + $class = 'icon compact rearrange'; + } + + // Create an array of actions to pass to theme_links + $actions = array(); + $count_handlers = count($display->handler->get_handlers($type)); + $actions['add'] = array( + 'title' => t('Add'), + 'href' => "admin/structure/views/nojs/add-item/$view->name/$display->id/$type", + 'attributes'=> array('class' => array('icon compact add', 'views-ajax-link'), 'title' => t('Add'), 'id' => 'views-add-' . $type), + 'html' => TRUE, + ); + if ($count_handlers > 1) { + $actions['rearrange'] = array( + 'title' => $rearrange_text, + 'href' => $rearrange_url, + 'attributes' => array('class' => array($class, 'views-ajax-link'), 'title' => t('Rearrange'), 'id' => 'views-rearrange-' . $type), + 'html' => TRUE, + ); + } + if ($count_handlers > 0) { + $actions['delete'] = array( + 'title' => t('Delete'), + 'href' => "admin/structure/views/nojs/delete-item/$view->name/$display->id/$type", + 'attributes' => array('class' => array('icon compact delete', 'views-ajax-link'), 'title' => t('delete'), 'id' => 'views-delete-' . $type), + 'html' => TRUE, + ); } - $vars['rearrange'] = l('<span>' . t('Rearrange') . '</span>', $rearrange_url, array('attributes' => array('class' => array('views-button-rearrange', 'views-ajax-link'), 'title' => t('Rearrange')), 'html' => TRUE)); - - $vars['add'] = l('<span>' . t('Add') . '</span>', "admin/structure/views/nojs/add-item/$view->name/$display->id/$type", array('attributes' => array('class' => array('views-button-add', 'views-ajax-link'), 'title' => t('Add'), 'id' => 'views-add-' . $type), 'html' => true)); + // Render the array of links + $build['#actions'] = theme('links__ctools_dropbutton', + array( + 'links' => $actions, + 'attributes' => array( + 'class' => array('inline', 'links', 'actions', 'horizontal', 'right') + ), + 'class' => array('views-ui-settings-bucket-operations'), + ) + ); if (!$display->handler->is_default_display()) { if (!$display->handler->is_defaulted($types[$type]['plural'])) { - $vars['overridden'] = TRUE; + $build['#overridden'] = TRUE; } else { - $vars['defaulted'] = TRUE; + $build['#defaulted'] = TRUE; } } - if ($display->display_plugin != 'default') { - $vars['title'] = l($types[$type]['title'], "admin/structure/views/nojs/config-type/$view->name/$display->id/$type", array('attributes' => array('class' => array('views-ajax-link'), 'id' => 'views-title-' . $type))); - } - else { - $vars['title'] = $types[$type]['title']; - } + $build['#name'] = $build['#title'] = $types[$type]['title']; - $fields = array(); + // If there's an options form for the bucket, link to it. + if (!empty($types[$type]['options'])) { + $build['#title'] = l($build['#title'], "admin/structure/views/nojs/config-type/$view->name/$display->id/$type", array('attributes' => array('class' => array('views-ajax-link'), 'id' => 'views-title-' . $type))); + } static $relationships = NULL; if (!isset($relationships)) { @@ -1405,21 +2114,27 @@ function template_preprocess_views_ui_edit_item(&$vars) { $grouping = FALSE; if ($type == 'filter') { $group_info = $view->display_handler->get_option('filter_groups'); - if (!empty($group_info['groups']) && count($group_info['groups']) > 1) { + // If there is only one group but it is using the "OR" filter, we still + // treat it as a group for display purposes, since we want to display the + // "OR" label next to items within the group. + if (!empty($group_info['groups']) && (count($group_info['groups']) > 1 || current($group_info['groups']) == 'OR')) { $grouping = TRUE; $groups = array(0 => array()); } } + $build['fields'] = array(); + foreach ($display->handler->get_option($types[$type]['plural']) as $id => $field) { - $fields[$id] = array(); + // Build the option link for this handler ("Node: ID = article"). + $build['fields'][$id] = array(); + $build['fields'][$id]['#theme'] = 'views_ui_display_tab_setting'; $handler = $display->handler->get_handler($type, $id); if (empty($handler)) { - $fields[$id]['class'][] = 'broken'; + $build['fields'][$id]['#class'][] = 'broken'; $field_name = t('Broken/missing handler: @table > @field', array('@table' => $field['table'], '@field' => $field['field'])); - $fields[$id]['title'] = l($field_name, "admin/structure/views/nojs/config-item/$view->name/$display->id/$type/$id", array('attributes' => array('class' => array('views-ajax-link')), 'html' => TRUE)); - $fields[$id]['info'] = ''; + $build['fields'][$id]['#link'] = l($field_name, "admin/structure/views/nojs/config-item/$view->name/$display->id/$type/$id", array('attributes' => array('class' => array('views-ajax-link')), 'html' => TRUE)); continue; } @@ -1428,36 +2143,21 @@ function template_preprocess_views_ui_edit_item(&$vars) { $field_name = '(' . $relationships[$field['relationship']] . ') ' . $field_name; } - $fields[$id]['title'] = l($field_name, "admin/structure/views/nojs/config-item/$view->name/$display->id/$type/$id", array('attributes' => array('class' => array('views-ajax-link')), 'html' => TRUE)); - $fields[$id]['class'][] = drupal_clean_css_identifier($display->id . '-' . $type . '-' . $id); + $description = $handler->admin_summary(); + $link_text = $field_name . (empty($description) ? '' : " ($description)"); + $build['fields'][$id]['#link'] = l($link_text, "admin/structure/views/nojs/config-item/$view->name/$display->id/$type/$id", array('attributes' => array('class' => array('views-ajax-link')), 'html' => TRUE)); + $build['fields'][$id]['#class'][] = drupal_clean_css_identifier($display->id . '-' . $type . '-' . $id); if (!empty($view->changed_sections[$display->id . '-' . $type . '-' . $id])) { - $fields[$id]['changed'] = TRUE; + // @TODO: #changed is no longer being used? + $build['fields'][$id]['#changed'] = TRUE; } - $fields[$id]['info'] = $handler->admin_summary(); if ($display->handler->use_group_by()) { - $fields[$id]['links'] = l('<span>' . t('Group settings') . '</span>', "admin/structure/views/nojs/config-item-group/$view->name/$display->id/$type/$id", array('attributes' => array('class' => 'views-button-configure views-ajax-link', 'title' => t('Group settings')), 'html' => true)); + $build['fields'][$id]['#settings_links'][] = l('<span>' . t('Group settings') . '</span>', "admin/structure/views/nojs/config-item-group/$view->name/$display->id/$type/$id", array('attributes' => array('class' => 'views-button-configure views-ajax-link', 'title' => t('Group settings')), 'html' => true)); } if ($handler->has_extra_options()) { - $fields[$id]['links'] = l('<span>' . t('Settings') . '</span>', "admin/structure/views/nojs/config-item-extra/$view->name/$display->id/$type/$id", array('attributes' => array('class' => array('views-button-configure', 'views-ajax-link'), 'title' => t('Settings')), 'html' => true)); - } - - if ($handler->needs_style_plugin()) { - $style_plugin = views_fetch_plugin_data('style', $handler->options['style_plugin']); - $style_title = empty($style_plugin['title']) ? t('Missing style plugin') : $style_plugin['title']; - $pid = $id . '-style-plugin'; - - if (!empty($style_plugin['uses options'])) { - $fields[$pid]['links'] = l('<span>' . t('Change settings for this style') . '</span>', "admin/structure/views/nojs/config-style/$view->name/$display->id/$type/$id", array('attributes' => array('class' => array('views-button-configure', 'views-ajax-link'), 'title' => t('Settings')), 'html' => true)); - } - - $fields[$pid]['title'] = ' ' . t(' Style: !style', array('!style' => l($style_title, "admin/structure/views/nojs/change-style/$view->name/$display->id/$type/$id", array('attributes' => array('class' => array('views-ajax-link')))))); - $fields[$pid]['class'][] = drupal_clean_css_identifier($display->id . '-' . $type . '-' . $pid); - if (!empty($view->changed_sections[$display->id . '-' . $type . '-' . $pid])) { - $fields[$pid]['changed'] = TRUE; - } - $fields[$pid]['info'] = ''; + $build['fields'][$id]['#settings_links'][] = l('<span>' . t('Settings') . '</span>', "admin/structure/views/nojs/config-item-extra/$view->name/$display->id/$type/$id", array('attributes' => array('class' => array('views-button-configure', 'views-ajax-link'), 'title' => t('Settings')), 'html' => true)); } if ($grouping) { @@ -1473,73 +2173,69 @@ function template_preprocess_views_ui_edit_item(&$vars) { // If using grouping, re-order fields so that they show up properly in the list. if ($type == 'filter' && $grouping) { - $store = $fields; - $fields = array(); + $store = $build['fields']; + $build['fields'] = array(); foreach ($groups as $gid => $contents) { - if (!empty($fields)) { - $operator = ') ' . ($group_info['operator'] == 'OR' ? t('OR') : t('AND')) . ' ('; - } - else { - $operator = '('; + // Display an operator between each group. + if (!empty($build['fields'])) { + $build['fields'][] = array( + '#theme' => 'views_ui_display_tab_setting', + '#class' => array('views-group-text'), + '#link' => ($group_info['operator'] == 'OR' ? t('OR') : t('AND')), + ); } - $fields[] = array( - 'class' => 'views-group-text', - 'title' => $operator, - 'info' => '', - ); - $started = FALSE; - foreach ($contents as $pid) { - $operator = ' '; - if ($started) { - $operator .= ($group_info['groups'][$gid] == 'OR' ? t('OR') : t('AND')) . ' '; + // Display an operator between each pair of filters within the group. + $keys = array_keys($contents); + $last = end($keys); + foreach ($contents as $key => $pid) { + if ($key != $last) { + $store[$pid]['#link'] .= ' ' . ($group_info['groups'][$gid] == 'OR' ? t('OR') : t('AND')); } - $store[$pid]['title'] = $operator . $store[$pid]['title']; - $started = TRUE; - $fields[$pid] = $store[$pid]; + $build['fields'][$pid] = $store[$pid]; } } - $fields[] = array( - 'class' => 'views-group-text', - 'title' => ')', - 'info' => '', - ); } - $vars['fields'] = $fields; + return $build; } /** - * Regenerate the tabs for AJAX updates. + * Regenerate the current tab for AJAX updates. */ -function views_ui_regenerate_tabs(&$view, &$output, $display_id = NULL) { - if (empty($display_id)) { - $displays = array_keys($view->display); - } - elseif (!is_array($display_id)) { - $displays = array($display_id); - if ($display_id != 'default') { - $displays[] = 'default'; - } - } - else { - $displays = $display_id; - } - +function views_ui_regenerate_tab(&$view, &$output, $display_id) { if (!$view->set_display('default')) { return; } - foreach ($displays as $id) { - list($title, $body) = views_ui_display_tab($view, $view->display[$id]); - $output[] = ajax_command_html('#views-tab-' . $id, $body); - $output[] = ajax_command_html('#views-tab-title-' . $id, check_plain($title)); + $build = views_ui_get_display_tab($view, $display_id); + views_ui_add_microweights($build); + $output[] = ajax_command_html('#views-tab-' . $display_id, drupal_render($build)); +} + +/** + * Recursively adds microweights to a render array, similar to what form_builder() does for forms. + * + * @todo Submit a core patch to fix drupal_render() to do this, so that all + * render arrays automatically preserve array insertion order, as forms do. + */ +function views_ui_add_microweights(&$build) { + $count = 0; + foreach (element_children($build) as $key) { + if (!isset($build[$key]['#weight'])) { + $build[$key]['#weight'] = $count/1000; + } + views_ui_add_microweights($build[$key]); + $count++; } } /** - * Provide standard buttons for the forms to make it easy. Also provide + * Provide a standard set of Apply/Cancel/OK buttons for the forms. Also provide * a hidden op operator because the forms plugin doesn't seem to properly * provide which button was clicked. + * + * TODO: Is the hidden op operator still here somewhere, or is that part of the + * docblock outdated? */ function views_ui_standard_form_buttons(&$form, &$form_state, $form_id, $name = NULL, $third = NULL, $submit = NULL) { $form['buttons'] = array( @@ -1548,36 +2244,46 @@ function views_ui_standard_form_buttons(&$form, &$form_state, $form_id, $name = ); if (empty($name)) { - $name = t('Update'); - } - - // Add the override and update button - if ($name == t('Update default display')) { - $form['buttons']['override_update'] = array( - '#type' => 'submit', - '#value' => t('Update and override'), - '#submit' => array( - 'views_ui_edit_display_form_override_update_section', - 'views_ui_standard_submit', - 'views_ui_edit_display_form_override_update', - ), - ); + $name = t('Apply'); + $view = $form_state['view']; + if (!empty($view->stack) && count($view->stack) > 1) { + $name = t('Apply and continue'); + } + $names = array(t('Apply'), t('Apply and continue')); } + // Forms that are purely informational set an ok_button flag, so we know not + // to create an "Apply" button for them. if (empty($form_state['ok_button'])) { - // but be sure submit button validates! $form['buttons']['submit'] = array( '#type' => 'submit', '#value' => $name, - '#submit' => array('views_ui_standard_submit', $form_id . '_submit'), + // The regular submit handler ($form_id . '_submit') does not apply if + // we're updating the default display. It does apply if we're updating + // the current display. Since we have no way of knowing at this point + // which display the user wants to update, views_ui_standard_submit will + // take care of running the regular submit handler as appropriate. + '#submit' => array('views_ui_standard_submit'), ); - // Take sure that the validation handler exists. + // Form API button click detection requires the button's #value to be the + // same between the form build of the initial page request, and the initial + // form build of the request processing the form submission. Ideally, the + // button's #value shouldn't change until the form rebuild step. However, + // views_ui_ajax_form() implements a different multistep form workflow than + // the Form API does, and adjusts $view->stack prior to form processing, so + // we compensate by extending button click detection code to support any of + // the possible button labels. + if (isset($names)) { + $form['buttons']['submit']['#values'] = $names; + $form['buttons']['submit']['#process'] = array_merge(array('views_ui_form_button_was_clicked'), element_info_property($form['buttons']['submit']['#type'], '#process', array())); + } + // If a validation handler exists for the form, assign it to this button. if (function_exists($form_id . '_validate')) { $form['buttons']['submit']['#validate'][] = $form_id . '_validate'; } - } + // Create a "Cancel" button. For purely informational forms, label it "OK". $cancel_submit = function_exists($form_id . '_cancel') ? $form_id . '_cancel' : 'views_ui_standard_cancel'; $form['buttons']['cancel'] = array( '#type' => 'submit', @@ -1586,6 +2292,7 @@ function views_ui_standard_form_buttons(&$form, &$form_state, $form_id, $name = '#validate' => array(), ); + // Some forms specify a third button, with a name and submit handler. if ($third) { if (empty($submit)) { $submit = 'third'; @@ -1600,7 +2307,7 @@ function views_ui_standard_form_buttons(&$form, &$form_state, $form_id, $name = ); } - // Compatibility, to be removed later: + // Compatibility, to be removed later: // TODO: When is "later"? // We used to set these items on the form, but now we want them on the $form_state: if (isset($form['#title'])) { $form_state['title'] = $form['#title']; @@ -1632,18 +2339,79 @@ function views_ui_standard_form_buttons(&$form, &$form_state, $form_id, $name = if (!empty($form['#title'])) { drupal_set_title($form['#title']); } - $form['#attached']['css'] = array( - drupal_get_path('module', 'views') . "/css/views-admin.css", - ); } /** - * Basic submit handler applicable to all 'standard' forms + * Basic submit handler applicable to all 'standard' forms. + * + * This submit handler determines whether the user wants the submitted changes + * to apply to the default display or to the current display, and dispatches + * control appropriately. */ function views_ui_standard_submit($form, &$form_state) { + // Determine whether the values the user entered are intended to apply to + // the current display or the default display. + + // Make sure the dropdown exists in the first place. + if (isset($form_state['values']['override']['dropdown'])) { + $was_defaulted = (bool) ($form['override']['dropdown']['#default_value'] === 'defaults'); + $is_defaulted = (bool) ($form_state['values']['override']['dropdown'] === 'default'); + + if ($was_defaulted !== $is_defaulted && isset($form['#section'])) { + // We're changing which display these values apply to. + // Update the #section so it knows what to mark changed. + $form['#section'] = str_replace('default-', $form_state['display_id'] . '-', $form['#section']); + } + } + else { + // The user didn't get the dropdown for overriding the default display. + $was_defaulted = FALSE; + $is_defaulted = FALSE; + } + + // Mark the changed section of the view as changed. + // TODO: Document why we are doing this, and see if we still need it. if (!empty($form['#section'])) { $form_state['view']->changed_sections[$form['#section']] = TRUE; } + + // Based on the user's choice in the display dropdown, determine which display + // these changes apply to. + if ($was_defaulted === $is_defaulted) { + // We're not changing which display these form values apply to. + // Run the regular submit handler for this form. + $submit_handler = $form['#form_id'] . '_submit'; + if (function_exists($submit_handler)) { + $submit_handler($form, $form_state); + } + } + elseif ($was_defaulted && !$is_defaulted) { + // We were using the default display's values, but we're now overriding + // the default display and saving values specific to this display. + // TODO: Document why the regular form submit handler isn't necessary in + // this case. + $display = &$form_state['view']->display[$form_state['display_id']]; + $display->handler->options_override($form, $form_state); + $display->handler->options_submit($form, $form_state); + views_ui_cache_set($form_state['view']); + } + elseif (!$was_defaulted && $is_defaulted) { + // We used to have an override for this display, but the user now wants + // to go back to the default display. + // Overwrite the default display with the current form values, and make + // the current display use the new default values. + $display = &$form_state['view']->display[$form_state['display_id']]; + $display->handler->options_override($form, $form_state); + $display->handler->options_submit($form, $form_state); + + // TODO: This is copy/paste code. Refactor. + $submit_handler = $form['#form_id'] . '_submit'; + if (function_exists($submit_handler)) { + $submit_handler($form, $form_state); + } + + views_ui_cache_set($form_state['view']); + } } /** @@ -1655,9 +2423,99 @@ function views_ui_standard_cancel($form, &$form_state) { views_ui_cache_set($form_state['view']); } - $form_state['redirect'] = 'admin/structure/views/edit/' . $form_state['view']->name; + $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->name . '/edit'; +} + +/** + * Add a <select> dropdown for a given section, allowing the user to + * change whether this info is stored on the default display or on + * the current display. + */ +function views_ui_standard_display_dropdown(&$form, &$form_state, $section) { + $view = &$form_state['view']; + $display_id = $form_state['display_id']; + $displays = $view->display; + $current_display = $view->display[$display_id]; + + // Add the "2 of 3" progress indicator. + // @TODO: Move this to a separate function if it's needed on any forms that + // don't have the display dropdown. + if ($form_progress = views_ui_get_form_progress($view)) { + $form['progress']['#markup'] = '<div id="views-progress-indicator">' . t('@current of @total', array('@current' => $form_progress['current'], '@total' => $form_progress['total'])) . '</div>'; + $form['progress']['#weight'] = -1001; + } + + if ($current_display->handler->is_default_display()) { + return; + } + + // Determine whether any other displays have overrides for this section. + $section_overrides = FALSE; + foreach ($displays as $id => $display) { + if ($id === 'default' || $id === $display_id) { + continue; + } + if ($display->handler && !$display->handler->is_defaulted($section)) { + $section_overrides = TRUE; + } + } + + $display_dropdown['default'] = ($section_overrides ? t('All displays (except overridden)') : t('All displays')); + $display_dropdown[$display_id] = t('This @display_type (override)', array('@display_type' => $current_display->display_plugin)); + + $form['override'] = array( + '#prefix' => '<div class="views-override clearfix container-inline">', + '#suffix' => '</div>', + '#weight' => -1000, + '#tree' => TRUE, + ); + $form['override']['dropdown'] = array( + '#type' => 'select', + '#title' => t('For'), // @TODO: Translators may need more context than this. + '#options' => $display_dropdown, + ); + if ($current_display->handler->is_defaulted($section)) { + $form['override']['dropdown']['#default_value'] = 'defaults'; + } + else { + $form['override']['dropdown']['#default_value'] = $display_id; + } + +} + +/** + * Get the user's current progress through the form stack. + * + * @param $view + * The current view. + * + * @return + * FALSE if the user is not currently in a multiple-form stack. Otherwise, + * an associative array with the following keys: + * - current: The number of the current form on the stack. + * - total: The total number of forms originally on the stack. + */ +function views_ui_get_form_progress($view) { + $progress = FALSE; + if (!empty($view->stack)) { + $stack = $view->stack; + // The forms on the stack have integer keys that don't change as the forms + // are completed, so we can see which ones are still left. + $keys = array_keys($view->stack); + // Add 1 to the array keys for the benefit of humans, who start counting + // from 1 and not 0. + $current = reset($keys) + 1; + $total = end($keys) + 1; + if ($total > 1) { + $progress = array(); + $progress['current'] = $current; + $progress['total'] = $total; + } + } + return $progress; } + // -------------------------------------------------------------------------- // Various subforms for editing the pieces of a view. @@ -1679,6 +2537,10 @@ function views_ui_ajax_forms($key = NULL) { 'form_id' => 'views_ui_rearrange_form', 'args' => array('type'), ), + 'delete-item' => array( + 'form_id' => 'views_ui_item_delete_form', + 'args' => array('type'), + ), 'rearrange-filter' => array( 'form_id' => 'views_ui_rearrange_filter_form', 'args' => array('type'), @@ -1699,14 +2561,14 @@ function views_ui_ajax_forms($key = NULL) { 'form_id' => 'views_ui_config_item_group_form', 'args' => array('type', 'id'), ), - 'change-style' => array( - 'form_id' => 'views_ui_change_style_form', - 'args' => array('type', 'id'), - ), 'config-style' => array( 'form_id' => 'views_ui_config_style_form', 'args' => array('type', 'id'), ), + 'edit-details' => array( + 'form_id' => 'views_ui_edit_details_form', + 'args' => array(), + ), ); if ($key) { @@ -1719,7 +2581,7 @@ function views_ui_ajax_forms($key = NULL) { /** * Build a form identifier that we can use to see if one form * is the same as another. Since the arguments differ slightly - * we do a lot of spiffy concenation here. + * we do a lot of spiffy concatenation here. */ function views_ui_build_identifier($key, $view, $display_id, $args) { $form = views_ui_ajax_forms($key); @@ -1773,8 +2635,8 @@ function views_ui_build_form_url($form_state) { } /** - * Add another form to the stack; clicking 'update' will go to this form - * rather than closing the ajax pad. + * Add another form to the stack; clicking 'apply' will go to this form + * rather than closing the ajax popup. */ function views_ui_add_form_to_stack($key, &$view, $display_id, $args, $top = FALSE) { if (empty($view->stack)) { @@ -1782,11 +2644,30 @@ function views_ui_add_form_to_stack($key, &$view, $display_id, $args, $top = FAL } $stack = array(views_ui_build_identifier($key, $view, $display_id, $args), $key, &$view, $display_id, $args); - if ($top) { - array_unshift($view->stack, $stack); + // If we're being asked to add this form to the bottom of the stack, no + // special logic is required. Our work is equally easy if we were asked to add + // to the top of the stack, but there's nothing in it yet. + if (!$top || empty($view->stack)) { + $view->stack[] = $stack; } + // If we're adding to the top of an existing stack, we have to maintain the + // existing integer keys, so they can be used for the "2 of 3" progress + // indicator (which will now read "2 of 4"). else { - $view->stack[] = $stack; + $keys = array_keys($view->stack); + $first = current($keys); + $last = end($keys); + for ($i = $last; $i >= $first; $i--) { + if (!isset($view->stack[$i])) { + continue; + } + // Move form number $i to the next position in the stack. + $view->stack[$i + 1] = $view->stack[$i]; + unset($view->stack[$i]); + } + // Now that the previously $first slot is free, move the new form into it. + $view->stack[$first] = $stack; + ksort($view->stack); } } @@ -1794,11 +2675,9 @@ function views_ui_add_form_to_stack($key, &$view, $display_id, $args, $top = FAL * Generic entry point to handle forms. * * We do this for consistency and to make it easy to chain forms - * together. This only works for forms that use both $view - * and $display_id, so we have a couple of ajax forms that we don't - * use with this system. + * together. */ -function views_ui_ajax_form($js, $key, $view, $display_id) { +function views_ui_ajax_form($js, $key, $view, $display_id = '') { // Reset the cache of IDs. Drupal rather aggressively prevents id duplication // but this causes it to remember IDs that are no longer even being used. if (isset($_POST['ajax_html_ids'])) { @@ -1821,7 +2700,12 @@ function views_ui_ajax_form($js, $key, $view, $display_id) { // now irrelevant. if (!empty($view->stack)) { $identifier = views_ui_build_identifier($key, $view, $display_id, $args); - $top = array_shift($view->stack); + // Retrieve the first form from the stack without changing the integer keys, + // as they're being used for the "2 of 3" progress indicator. + reset($view->stack); + list($key, $top) = each($view->stack); + unset($view->stack[$key]); + if (array_shift($top) != $identifier) { $view->stack = array(); } @@ -1834,11 +2718,19 @@ function views_ui_ajax_form($js, $key, $view, $display_id) { unset($view->form_cache); } + // With the below logic, we may end up rendering a form twice (or two forms + // each sharing the same element ids), potentially resulting in + // drupal_add_js() being called twice to add the same setting. drupal_get_js() + // is ok with that, but until ajax_render() is (http://drupal.org/node/208611), + // reset the drupal_add_js() static before rendering the second time. + $drupal_add_js_original = drupal_add_js(); + $drupal_add_js = &drupal_static('drupal_add_js'); $output = views_ajax_form_wrapper($form_state['form_id'], $form_state); if ($form_state['submitted'] && empty($form_state['rerender'])) { // Sometimes we need to re-generate the form for multi-step type operations. $object = NULL; if (!empty($view->stack)) { + $drupal_add_js = $drupal_add_js_original; $stack = $view->stack; $top = array_shift($stack); $top[0] = $js; @@ -1852,229 +2744,25 @@ function views_ui_ajax_form($js, $key, $view, $display_id) { } elseif (!$js) { // if nothing on the stack, non-js forms just go back to the main view editor. - return drupal_goto("admin/structure/views/edit/$view->name"); + return drupal_goto("admin/structure/views/view/$view->name/edit"); } else { $output = array(); - $output[] = views_ajax_command_enable_buttons(); $output[] = views_ajax_command_dismiss_form(); + $output[] = views_ajax_command_show_buttons(); $output[] = views_ajax_command_trigger_preview(); - } - views_ui_regenerate_tabs($view, $output); - } - elseif ($js) { - $output[] = views_ajax_command_disable_buttons(); - } - - return $js ? array('#type' => 'ajax', '#commands' => $output) : $output; -} - -/** - * AJAX callback to add a display. - */ -function views_ui_add_display($js, $view) { - views_include('ajax'); - $form_state = array( - 'view' => &$view, - 'ajax' => $js, - ); - - $output = views_ajax_form_wrapper('views_ui_add_display_form', $form_state); - - if ($js) { - if ($form_state['submitted']) { - $id = $form_state['id']; - - // Make sure the new display is active - if (!$view->set_display('default')) { - views_ajax_error(t('Unable to initialize default display')); + if (!empty($form_state['#page_title'])) { + $output[] = views_ajax_command_replace_title($form_state['#page_title']); } - - // Render the new display - list($title, $body) = views_ui_display_tab($view, $view->display[$id]); - - // Instruct the javascript on the browser to render the new tab. - $output = array(); - $output[] = views_ajax_command_add_tab($id, $title, $body); } - $output = array('#type' => 'ajax', '#commands' => $output); - } - - // But the non-js variant will return output if it didn't redirect us. - return $output; -} - -/** - * Form to add a display to a view. - */ -function views_ui_add_display_form($form, &$form_state) { - $view = &$form_state['view']; - - $form['display']['display'] = array( - '#type' => 'select', - '#options' => views_fetch_plugin_names('display'), - '#default_value' => 'page', - ); - - $form['display']['add_display'] = array( - '#type' => 'submit', - '#value' => t('Add display'), - '#ajax' => array( - 'path' => "admin/structure/views/ajax/add-display/$view->name", - ), - '#submit' => array('views_ui_add_display_form_submit'), - ); - - $form['#id'] = 'views-add-display-form'; - $form['#attributes'] = array('class' => array('views-ajax-form')); - $form['#action'] = url("admin/structure/views/nojs/add-display/$view->name"); - - return $form; -} - -/** - * Submit handler to add a display to a view. - */ -function views_ui_add_display_form_submit($form, &$form_state) { - // Create the new display - $plugin = $form_state['values']['display']; - $form_state['id'] = $form_state['view']->add_display($plugin); - - // Store in cache - views_ui_cache_set($form_state['view']); - - // Send it back - $form_state['redirect'] = array('admin/structure/views/edit/' . $form_state['view']->name, array('fragment' => 'views-tab-' . $form_state['id'])); -} - -/** - * AJAX callback to add a display. - */ -function views_ui_clone_display($js, $view, $id) { - views_include('ajax'); - $form_state = array( - 'view' => &$view, - 'ajax' => $js, - 'display_id' => $id, - ); - - $output = views_ajax_form_wrapper('views_ui_clone_display_form', $form_state); - - if ($js) { - // If we don't have an output object, it was submitted. Set up the submission. - if (empty($output)) { - $id = $form_state['id']; - - // Make sure the new display is active - if (!$view->set_display('default')) { - views_ajax_render(t('Unable to initialize default display')); - } - - // Render the new display - list($title, $body) = views_ui_display_tab($view, $view->display[$id]); - - // Instruct the javascript on the browser to render the new tab. - $output = new stdClass; - $output->tab = array('#views-tab-' . $id => array('title' => $title, 'body' => $body)); + // If this form was for view-wide changes, there's no need to regenerate + // the display section of the form. + if ($display_id !== '') { + views_ui_regenerate_tab($view, $output, $display_id); } - // Render the command object. This automatically exits. - views_ajax_render($output); - } - - // But the non-js variant will return output if it didn't redirect us. - return $output; -} - -/** - * From to clone a display from a view. - */ -function views_ui_clone_display_form($form, &$form_state) { - $view = &$form_state['view']; - $display_id = $form_state['display_id']; - - $form['clone_display'] = array( - '#type' => 'submit', - '#value' => t('Clone display'), - '#submit' => array('views_ui_clone_display_form_submit'), - ); - - $form['#id'] = 'views-clone-display-form'; - $form['#action'] = url("admin/build/views/nojs/clone-display/$view->name/$display_id"); - $form['#attributes'] = array('class' => 'views-ajax-form'); - - return $form; -} - -/** - * Submit handler to add a clone to a display from a view. - */ -function views_ui_clone_display_form_submit($form, &$form_state) { - // Create the new display - $id = $form_state['display_id']; - $display = $form_state['view']->display[$id]; - - $new_id = $form_state['view']->add_display($display->display_plugin); - $form_state['id'] = $new_id; - - // Replace the new display by a copy of the old - $form_state['view']->display[$new_id] = clone $display; - $form_state['view']->display[$new_id]->id = $new_id; - - // Store in cache - views_ui_cache_set($form_state['view']); - - // Send it back - $form_state['redirect'] = array('admin/structure/views/edit/' . $form_state['view']->name, array('fragment' => 'views-tab-' . $new_id)); -} - -/** - * Form to remove a display from a view. - */ -function views_ui_remove_display_form($form, &$form_state) { - $view = &$form_state['view']; - $display_id = $form_state['display_id']; - - if (empty($view->display[$display_id]->deleted)) { - $form['display'] = array( - '#prefix' => '<div class="display-button remove-display">', - '#suffix' => '</div>', - ); - $form['remove_display'] = array( - '#type' => 'submit', - '#value' => t('Remove display'), - '#submit' => array('views_ui_remove_display_form_submit'), - ); - } - else { - $form['display'] = array( - '#prefix' => '<div class="display-button restore-display">', - '#suffix' => '</div>', - ); - $form['restore_display'] = array( - '#type' => 'submit', - '#value' => t('Restore display'), - '#submit' => array('views_ui_remove_display_form_restore'), - ); } - $form['#action'] = url("admin/structure/views/nojs/remove-display/$view->name/$display_id"); - $form['#attributes'] = array('class' => array('views-ajax-form')); - - return $form; -} - -/** - * Submit handler to add a remove to a display from a view. - */ -function views_ui_remove_display_form_submit($form, &$form_state) { - // Create the new display - $plugin = views_fetch_plugin_data('display', $form_state['view']->display[$form_state['display_id']]->display_plugin); - if (empty($plugin['no remove'])) { - $id = $form_state['display_id']; - $form_state['view']->display[$id]->deleted = TRUE; - // Store in cache - views_ui_cache_set($form_state['view']); - } + return $js ? array('#type' => 'ajax', '#commands' => $output) : $output; } /** @@ -2093,26 +2781,11 @@ function views_ui_remove_display_form_restore($form, &$form_state) { * Page callback to display analysis information on a view. */ function views_ui_analyze_view($js, $view) { - views_include('ajax'); $form_state = array( 'view' => &$view, - 'ajax' => $js, ); - $output = views_ajax_form_wrapper('views_ui_analyze_view_form', $form_state); - - if ($js) { - // If we don't have an output object, it was submitted. Set up the submission. - if ($form_state['submitted'] && empty($form_state['rerender'])) { - $output = array(); - $output[] = views_ajax_command_enable_buttons(); - $output[] = views_ajax_command_dismiss_form(); - views_ui_regenerate_tabs($view, $output); - } - $commands = $output; - return $js ? array('#type' => 'ajax', '#commands' => $commands) : $commands; - } - return $output; + return drupal_build_form('views_ui_analyze_view_form', $form_state); } /** @@ -2160,43 +2833,11 @@ function views_ui_analyze_view_form($form, &$form_state) { return $form; } -/** - * Submit handler for views_ui_analyze_view_form - */ -function views_ui_analyze_view_form_submit($form, &$form_state) { - $form_state['redirect'] = 'admin/structure/views/edit/' . $form_state['view']->name; -} - -/** - * Page callback to display analysis information on a view. - */ -function views_ui_reorder_view($js, $view) { - views_include('ajax'); - $form_state = array( - 'view' => &$view, - 'ajax' => $js, - ); - - $output = views_ajax_form_wrapper('views_ui_reorder_displays_form', $form_state); - - if ($js) { - if ($form_state['submitted'] && empty($form_state['rerender'])) { - // I don't want preprocess to modify the views -> no references - $vars = array('view' => $view); - template_preprocess_views_ui_edit_view($vars); - $output = array(); - $output[] = ajax_command_replace('.views-tabset', $vars['tabs']); - // Not the right place to have html i know ! - $output[] = ajax_command_replace('.views-quick-links', '<div class="views-quick-links">'. $vars['quick_links'] .'</div>'); - $output[] = views_ajax_command_enable_buttons(); - $output[] = views_ajax_command_dismiss_form(); - // Doesn't work yet, maybe we should reload the page dunno - views_ui_regenerate_tabs($view, $output); - } - $commands = $output; - return $js ? array('#type' => 'ajax', '#commands' => $commands) : $commands; - } - return $output; +/** + * Submit handler for views_ui_analyze_view_form + */ +function views_ui_analyze_view_form_submit($form, &$form_state) { + $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->name . '/edit'; } /** @@ -2254,7 +2895,7 @@ function views_ui_reorder_displays_form($form, &$form_state) { 'limit' => 0, ); - $form['#action'] = url('admin/structure/views/nojs/reorder-displays/'. $view->name); + $form['#action'] = url('admin/structure/views/nojs/reorder-displays/' . $view->name); views_ui_standard_form_buttons($form, $form_state, 'views_ui_reorder_displays_form'); @@ -2314,7 +2955,7 @@ function views_ui_reorder_displays_form_submit($form, &$form_state) { // Store in cache views_ui_cache_set($form_state['view']); - $form_state['redirect'] = array('admin/structure/views/edit/' . $form_state['view']->name, array('fragment' => 'views-tab-default')); + $form_state['redirect'] = array('admin/structure/views/view/' . $form_state['view']->name . '/edit', array('fragment' => 'views-tab-default')); } /** @@ -2395,82 +3036,56 @@ function views_ui_reorder_displays_button($form, &$form_state, $view) { } /** - * Page callback to edit details of a view. - */ -function views_ui_edit_details($property, $js, $view) { - views_include('ajax'); - $form_state = array( - 'view' => &$view, - 'ajax' => $js, - 'property' => $property, - ); - - $output = views_ajax_form_wrapper('views_ui_edit_details_form', $form_state); - - if ($js) { - // If we don't have an output object, it was submitted. Set up the submission. - if ($form_state['submitted'] && empty($form_state['rerender'])) { - $output = array(); - $output[] = views_ajax_command_enable_buttons(); - $output[] = views_ajax_command_dismiss_form(); - views_ui_regenerate_tabs($view, $output); - } - $commands = $output; - return $js ? array('#type' => 'ajax', '#commands' => $commands) : $commands; - } - return $output; -} - -/** - * Form constructor callback to edit details of a view + * Form builder to edit details of a view. */ function views_ui_edit_details_form($form, &$form_state) { $view = &$form_state['view']; - $form['#title'] = t('View details'); + $form['#title'] = t('View name and description'); $form['#section'] = 'details'; - switch ($form_state['property']) { - case 'human_name': - $form['human_name'] = array( - '#type' => 'textfield', - '#title' => t('Human readable name'), - '#description' => t('You can use a more descriptive name for this view here. Spaces are allowed'), - '#default_value' => $view->human_name, - ); - break; - - case 'tag': - $form['tag'] = array( - '#type' => 'textfield', - '#title' => t('View tag'), - '#description' => t('Enter an optional tag for this view; it is used only to help sort views on the administrative page.'), - '#default_value' => $view->tag, - '#autocomplete_path' => 'admin/views/ajax/autocomplete/tag', - ); - break; - - case 'description': - $form['description'] = array( - '#type' => 'textfield', - '#title' => t('View description'), - '#description' => t('This description will appear on the Views administrative UI to tell you what the view is about.'), - '#default_value' => $view->description, - ); - break; - } + $form['details'] = array( + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ); + $form['details']['human_name'] = array( + '#type' => 'textfield', + '#title' => t('Human-readable name'), + '#description' => t('A descriptive human-readable name for this view. Spaces are allowed'), + '#default_value' => $view->get_human_name(), + ); + $form['details']['tag'] = array( + '#type' => 'textfield', + '#title' => t('View tag'), + '#description' => t('Enter an optional tag for this view; it is used only to help sort views on the administrative page.'), + '#default_value' => $view->tag, + '#autocomplete_path' => 'admin/views/ajax/autocomplete/tag', + ); + $form['details']['description'] = array( + '#type' => 'textfield', + '#title' => t('View description'), + '#description' => t('This description will appear on the Views administrative UI to tell you what the view is about.'), + '#default_value' => $view->description, + ); views_ui_standard_form_buttons($form, $form_state, 'views_ui_edit_details_form'); return $form; } /** - * Submit handler for views_ui_edit_details_form + * Submit handler for views_ui_edit_details_form. */ function views_ui_edit_details_form_submit($form, &$form_state) { - $form_state['view']->{$form_state['property']} = $form_state['values'][$form_state['property']]; - views_ui_cache_set($form_state['view']); - $form_state['redirect'] = 'admin/structure/views/edit/' . $form_state['view']->name; + $view = $form_state['view']; + foreach ($form_state['values'] as $key => $value) { + // Only save values onto the view if they're actual view properties + // (as opposed to 'op' or 'form_build_id'). + if (isset($form['details'][$key])) { + $view->$key = $value; + } + } + $form_state['#page_title'] = views_ui_edit_page_title($view); + views_ui_cache_set($view); } /** @@ -2487,7 +3102,23 @@ function views_ui_edit_display_form($form, &$form_state) { $display = &$view->display[$display_id]; // Get form from the handler. - $display->handler->options_form($form, $form_state); + $form['options'] = array( + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ); + $display->handler->options_form($form['options'], $form_state); + + // The handler options form sets $form['#title'], which we need on the entire + // $form instead of just the ['options'] section. + $form['#title'] = $form['options']['#title']; + unset($form['options']['#title']); + + // Move the override dropdown out of the scrollable section of the form. + if (isset($form['options']['override'])) { + $form['override'] = $form['options']['override']; + unset($form['options']['override']); + } + $name = NULL; if (isset($form_state['update_name'])) { $name = $form_state['update_name']; @@ -2521,6 +3152,8 @@ function views_ui_edit_display_form_submit($form, &$form_state) { /** * Override handler for views_ui_edit_display_form + * + * @TODO: Not currently used. Remove unless we implement an override toggle. */ function views_ui_edit_display_form_override($form, &$form_state) { $display = &$form_state['view']->display[$form_state['display_id']]; @@ -2530,23 +3163,6 @@ function views_ui_edit_display_form_override($form, &$form_state) { $form_state['rerender'] = TRUE; $form_state['rebuild'] = TRUE; } -/** - * Override handler and submit views_ui_edit_display_form - */ -function views_ui_edit_display_form_override_update(&$form, &$form_state) { - $display = &$form_state['view']->display[$form_state['display_id']]; - $display->handler->options_override($form, $form_state); - $display->handler->options_submit($form, $form_state); - views_ui_cache_set($form_state['view']); -} - -/** - * Override handler and submit views_ui_edit_display_form - */ -function views_ui_edit_display_form_override_update_section(&$form, &$form_state) { - // Update the #section so it knows what to mark changed. - $form['#section'] = str_replace('default-', $form_state['display_id'] . '-', $form['#section']); -} /** * Form to config items in the views UI. @@ -2561,13 +3177,12 @@ function views_ui_config_type_form($form, &$form_state) { views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); } $display = &$view->display[$display_id]; - $form['#title'] = check_plain($display->display_title) . ': '; - $form['#title'] .= t('Configure @type', array('@type' => $types[$type]['ltitle'])); + $form['#title'] = t('Configure @type', array('@type' => $types[$type]['ltitle'])); $form['#section'] = $display_id . 'config-item'; if ($display->handler->defaultable_sections($types[$type]['plural'])) { $form_state['section'] = $types[$type]['plural']; - $display->handler->add_override_button($form, $form_state, $form_state['section']); + views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); } if (!empty($types[$type]['options']) && function_exists($types[$type]['options'])) { @@ -2596,13 +3211,6 @@ function views_ui_config_type_form_submit($form, &$form_state) { views_ui_cache_set($form_state['view']); } -/** - * Configure settings particular to filters. - */ -function views_ui_config_filters_form(&$form, &$form_state) { - -} - /** * Form to rearrange items in the views UI. */ @@ -2616,13 +3224,12 @@ function views_ui_rearrange_form($form, &$form_state) { views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); } $display = &$view->display[$display_id]; - $form['#title'] = check_plain($display->display_title) . ': '; - $form['#title'] .= t('Rearrange @type', array('@type' => $types[$type]['ltitle'])); + $form['#title'] = t('Rearrange @type', array('@type' => $types[$type]['ltitle'])); $form['#section'] = $display_id . 'rearrange-item'; if ($display->handler->defaultable_sections($types[$type]['plural'])) { $form_state['section'] = $types[$type]['plural']; - $display->handler->add_override_button($form, $form_state, $form_state['section']); + views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); } $count = 0; @@ -2631,11 +3238,29 @@ function views_ui_rearrange_form($form, &$form_state) { $relationships = array(); foreach ($display->handler->get_handlers('relationship') as $id => $handler) { $relationships[$id] = $handler->label(); + $handlers = $display->handler->get_option('relationships'); + if ($handlers) { + foreach ($handlers as $id => $info) { + $handler = $display->handler->get_handler('relationship', $id); + $relationships[$id] = $handler->label(); + } + } + } + + // Filters can now be grouped so we do a little bit extra: + $groups = array(); + $grouping = FALSE; + if ($type == 'filter') { + $group_info = $view->display_handler->get_option('filter_groups'); + if (!empty($group_info['groups']) && count($group_info['groups']) > 1) { + $grouping = TRUE; + $groups = array(0 => array()); + } } foreach ($display->handler->get_option($types[$type]['plural']) as $id => $field) { - $form[$id] = array('#tree' => TRUE); - $form[$id]['weight'] = array( + $form['fields'][$id] = array('#tree' => TRUE); + $form['fields'][$id]['weight'] = array( '#type' => 'textfield', '#default_value' => ++$count, ); @@ -2646,14 +3271,14 @@ function views_ui_rearrange_form($form, &$form_state) { $name = '(' . $relationships[$field['relationship']] . ') ' . $name; } - $form[$id]['name'] = array( + $form['fields'][$id]['name'] = array( '#markup' => $name, ); } else { - $form[$id]['name'] = array('#value' => t('Broken field @id', array('@id' => $id))); + $form['fields'][$id]['name'] = array('#markup' => t('Broken field @id', array('@id' => $id))); } - $form[$id]['removed'] = array( + $form['fields'][$id]['removed'] = array( '#type' => 'checkbox', '#id' => 'views-removed-' . $id, '#attributes' => array('class' => array('views-remove-checkbox')), @@ -2687,13 +3312,13 @@ function theme_views_ui_rearrange_form($variables) { $form = $variables['form']; $rows = array(); - foreach (element_children($form) as $id) { - if (isset($form[$id]['name'])) { + foreach (element_children($form['fields']) as $id) { + if (isset($form['fields'][$id]['name'])) { $row = array(); - $row[] = drupal_render($form[$id]['name']); - $form[$id]['weight']['#attributes']['class'] = array('weight'); - $row[] = drupal_render($form[$id]['weight']); - $row[] = drupal_render($form[$id]['removed']) . l('<span>' . t('Remove') . '</span>', 'javascript:void()', array('attributes' => array('id' => 'views-remove-link-' . $id, 'class' => array('views-hidden', 'views-button-remove', 'views-remove-link'), 'alt' => t('Remove this item'), 'title' => t('Remove this item')), 'html' => TRUE)); + $row[] = drupal_render($form['fields'][$id]['name']); + $form['fields'][$id]['weight']['#attributes']['class'] = array('weight'); + $row[] = drupal_render($form['fields'][$id]['weight']); + $row[] = drupal_render($form['fields'][$id]['removed']) . l('<span>' . t('Remove') . '</span>', 'javascript:void()', array('attributes' => array('id' => 'views-remove-link-' . $id, 'class' => array('views-hidden', 'views-button-remove', 'views-remove-link'), 'alt' => t('Remove this item'), 'title' => t('Remove this item')), 'html' => TRUE)); $rows[] = array('data' => $row, 'class' => array('draggable'), 'id' => 'views-row-' . $id); } } @@ -2703,13 +3328,53 @@ function theme_views_ui_rearrange_form($variables) { $header = array('', t('Weight'), t('Remove')); $output = drupal_render($form['override']); + $output .= '<div class="scroll">'; $output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'arrange'))); + $output .= '</div>'; $output .= drupal_render_children($form); drupal_add_tabledrag('arrange', 'order', 'sibling', 'weight'); return $output; } +/** + * Theme the expose filter form. + */ +function theme_views_ui_expose_filter_form($variables) { + $form = $variables['form']; + $more = drupal_render($form['more']); + + $output = drupal_render($form['form_description']); + $output .= drupal_render($form['expose_button']); + if (isset($form['required'])) { + $output .= drupal_render($form['required']); + } + $output .= drupal_render($form['label']); + + $output .= drupal_render($form['operator']); + $output .= drupal_render($form['value']); + + if (isset($form['use_operator'])) { + $output .= '<div class="views-left-40">'; + $output .= drupal_render($form['use_operator']); + $output .= '</div>'; + } + + // Only output the right column markup if there's a left column to begin with + if (!empty($form['operator']['#type'])) { + $output .= '<div class="views-right-60">'; + $output .= drupal_render_children($form); + $output .= '</div>'; + } + else { + $output .= drupal_render_children($form); + } + + $output .= $more; + + return $output; +} + /** * Submit handler for rearranging form */ @@ -2761,7 +3426,7 @@ function views_ui_rearrange_filter_form($form, &$form_state) { if ($display->handler->defaultable_sections($types[$type]['plural'])) { $form_state['section'] = $types[$type]['plural']; - $display->handler->add_override_button($form, $form_state, $form_state['section']); + views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); } if (!empty($view->form_cache)) { @@ -2803,7 +3468,7 @@ function views_ui_rearrange_filter_form($form, &$form_state) { ), '#default_value' => $groups['operator'], '#attributes' => array( - 'class' => 'warning-on-change', + 'class' => array('warning-on-change'), ), '#title' => t('Operator to use on all groups'), '#description' => t('Either "group 0 AND group 1 AND group 2" or "group 0 OR group 1 OR group 2", etc'), @@ -2814,7 +3479,7 @@ function views_ui_rearrange_filter_form($form, &$form_state) { foreach ($groups['groups'] as $id => $group) { $form['filter_groups']['groups'][$id] = array( - '#title' => t('Group operator'), + '#title' => t('Operator'), '#type' => 'select', '#options' => array( 'AND' => t('And'), @@ -2831,6 +3496,10 @@ function views_ui_rearrange_filter_form($form, &$form_state) { $form['remove_groups'][$id] = array( '#type' => 'submit', '#value' => t('Remove group @group', array('@group' => $id)), + '#id' => "views-remove-group-$id", + '#attributes' => array( + 'class' => array('views-remove-group'), + ), '#group' => $id, ); } @@ -2867,6 +3536,7 @@ function views_ui_rearrange_filter_form($form, &$form_state) { $form['filters'][$id]['weight'] = array( '#type' => 'textfield', '#default_value' => ++$count, + '#size' => 8, ); $form['filters'][$id]['group'] = array( '#type' => 'select', @@ -2899,39 +3569,6 @@ function views_ui_rearrange_filter_form($form, &$form_state) { ); } - // Add javascript settings that will be added via $.extend for tabledragging - // Equivalent: drupal_add_tabledrag('arrange', 'order', 'sibling', 'weight'); - $form['#js']['tableDrag']['arrange']['weight'][0] = array( - 'target' => 'weight', - 'source' => NULL, - 'relationship' => 'sibling', - 'action' => 'order', - 'hidden' => TRUE, - 'limit' => 0, - ); - - $form['#js']['tableDrag']['ungroupable_arrange']['weight'][0] = array( - 'target' => 'weight', - 'source' => NULL, - 'relationship' => 'sibling', - 'action' => 'order', - 'hidden' => TRUE, - 'limit' => 0, - ); - - foreach ($form['#group_renders'] as $group_id => $title) { - // Add javascript settings that will be added via $.extend for tabledragging - // Equivalent: drupal_add_tabledrag('arrange', 'match', 'sibling', 'views-group-select', 'views-group-' . $group_id); - $form['#js']['tableDrag']['arrange']['views-group-select'][] = array( - 'target' => 'views-group-' . $group_id, - 'source' => 'views-group-' . $group_id, - 'relationship' => 'sibling', - 'action' => 'match', - 'hidden' => FALSE, - 'limit' => 0, - ); - } - if (isset($form_state['update_name'])) { $name = $form_state['update_name']; } @@ -2939,7 +3576,7 @@ function views_ui_rearrange_filter_form($form, &$form_state) { views_ui_standard_form_buttons($form, $form_state, 'views_ui_rearrange_filter_form'); $form['buttons']['add_group'] = array( '#type' => 'submit', - '#value' => t('Add new group'), + '#value' => t('Create new filter group'), '#id' => 'views-add-group', '#group' => 'add', ); @@ -2958,16 +3595,30 @@ function theme_views_ui_rearrange_filter_form(&$vars) { foreach ($form['#group_renders'] as $group_id => $contents) { // Header row for the group. - if ($grouping && $group_id !== 'ungroupable') { + if ($group_id !== 'ungroupable') { + // Set up tabledrag so that it changes the group dropdown when rows are + // dragged between groups. + drupal_add_tabledrag('views-rearrange-filters', 'match', 'sibling', 'views-group-select', 'views-group-select-' . $group_id); + + // Title row, spanning all columns. $row = array(); - $row[] = array('class' => array('group', 'group-title'), 'data' => $form['#group_options'][$group_id]); - $row[] = array('class' => array('group', 'container-inline'), 'data' => drupal_render($form['filter_groups']['groups'][$group_id]), 'colspan' => 3); - $rows[] = array('class' => array('views-group'), 'data' => $row, 'id' => 'views-group-' . $group_id); - // Row which will only appear if the group has nothing in it: + // Add a cell to the first row, containing the group operator. + $row[] = array('class' => array('group', 'group-operator', 'container-inline'), 'data' => drupal_render($form['filter_groups']['groups'][$group_id]), 'rowspan' => max(array(2, count($contents) + 1))); + // Title. + $row[] = array('class' => array('group', 'group-title'), 'data' => '<span>' . $form['#group_options'][$group_id] . '</span>', 'colspan' => 4); + $rows[] = array('class' => array('views-group-title'), 'data' => $row, 'id' => 'views-group-title-' . $group_id); + + // Row which will only appear if the group has nothing in it. $row = array(); $class = 'group-' . (count($contents) ? 'populated' : 'empty'); - $row[] = array('colspan' => 4, 'data' => '<span>' . t('This group is empty') . '</span> ' . - drupal_render($form['remove_groups'][$group_id])); + $instructions = '<span>' . t('No filters have been added.') . '</span> <span class="js-only">' . t('Drag to add filters.') . '</span>'; + // When JavaScript is enabled, the button for removing the group (if it's + // present) should be hidden, since it will be replaced by a link on the + // client side. + if (!empty($form['remove_groups'][$group_id]['#type']) && $form['remove_groups'][$group_id]['#type'] == 'submit') { + $form['remove_groups'][$group_id]['#attributes']['class'][] = 'js-hide'; + } + $row[] = array('colspan' => 5, 'data' => $instructions . drupal_render($form['remove_groups'][$group_id])); $rows[] = array('class' => array("group-message", "group-$group_id-message", $class), 'data' => $row, 'id' => 'views-group-' . $group_id); } @@ -2977,9 +3628,10 @@ function theme_views_ui_rearrange_filter_form(&$vars) { $row[] = drupal_render($form['filters'][$id]['name']); $form['filters'][$id]['weight']['#attributes']['class'] = array('weight'); $row[] = drupal_render($form['filters'][$id]['weight']); - $form['filters'][$id]['group']['#attributes']['class'] = array('views-group-select views-group-' . $group_id); + $form['filters'][$id]['group']['#attributes']['class'] = array('views-group-select views-group-select-' . $group_id); $row[] = drupal_render($form['filters'][$id]['group']); - $row[] = drupal_render($form['filters'][$id]['removed']) . l('<span>' . t('Remove') . '</span>', 'javascript:void()', array('attributes' => array('id' => 'views-remove-link-' . $id, 'class' => array('views-hidden', 'views-button-remove', 'views-groups-remove-link'), 'alt' => t('Remove this item'), 'title' => t('Remove this item')), 'html' => true)); + $form['filters'][$id]['removed']['#attributes']['class'][] = 'js-hide'; + $row[] = drupal_render($form['filters'][$id]['removed']) . l('<span>' . t('Remove') . '</span>', 'javascript:void()', array('attributes' => array('id' => 'views-remove-link-' . $id, 'class' => array('views-hidden', 'views-button-remove', 'views-groups-remove-link', 'views-remove-link'), 'alt' => t('Remove this item'), 'title' => t('Remove this item')), 'html' => true)); $row = array('data' => $row, 'class' => array('draggable'), 'id' => 'views-row-' . $id); if ($group_id !== 'ungroupable') { @@ -2996,6 +3648,7 @@ function theme_views_ui_rearrange_filter_form(&$vars) { } $output = drupal_render($form['override']); + $output .= '<div class="scroll">'; if ($grouping) { $output .= drupal_render($form['filter_groups']['operator']); } @@ -3005,17 +3658,23 @@ function theme_views_ui_rearrange_filter_form(&$vars) { } if (!empty($ungroupable_rows)) { - drupal_add_tabledrag('ungroupable_arrange', 'order', 'sibling', 'weight'); + drupal_add_tabledrag('views-rearrange-filters-ungroupable', 'order', 'sibling', 'weight'); $header = array(t('Ungroupable filters'), t('Weight'), array('class' => array('views-hide-label'), 'data' => t('Group')), array('class' => array('views-hide-label'), 'data' => t('Remove'))); - $output .= theme('table', array('header' => $header, 'rows' => $ungroupable_rows, 'attributes' => array('id' => 'ungroupable_arrange', 'class' => array('arrange')))); + $output .= theme('table', array('header' => $header, 'rows' => $ungroupable_rows, 'attributes' => array('id' => 'views-rearrange-filters-ungroupable', 'class' => array('arrange')))); } - drupal_add_tabledrag('arrange', 'order', 'sibling', 'weight'); - $header = array('', t('Weight'), t('Group'), t('Remove')); - $output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'arrange', 'class' => array('arrange')))); + // Set up tabledrag so that the weights are changed when rows are dragged. + drupal_add_tabledrag('views-rearrange-filters', 'order', 'sibling', 'weight'); + $output .= theme('table', array('rows' => $rows, 'attributes' => array('id' => 'views-rearrange-filters', 'class' => array('arrange')))); + $output .= '</div>'; + + // When JavaScript is enabled, the button for adding a new group should be + // hidden, since it will be replaced by a link on the client side. + $form['buttons']['add_group']['#attributes']['class'][] = 'js-hide'; + + // Render the rest of the form and return. $output .= drupal_render_children($form); return $output; - } /** @@ -3062,7 +3721,8 @@ function views_ui_rearrange_filter_form_submit($form, &$form_state) { $new_fields[$field] = $old_fields[$field]; } - // Save if the actual update button was clicked. + // If the #group property is set on the clicked button, that means we are + // either adding or removing a group, not actually updating the filters. if (!empty($form_state['clicked_button']['#group'])) { if ($form_state['clicked_button']['#group'] == 'add') { // Add a new group @@ -3100,7 +3760,19 @@ function views_ui_rearrange_filter_form_submit($form, &$form_state) { views_ui_add_form_to_stack('rearrange-filter', $form_state['view'], $form_state['display_id'], array($form_state['type'])); } else { - // Actually write changed handler values. + // 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)); + // 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)); + foreach ($new_fields as &$new_field) { + $new_field['group'] = $mapping[$new_field['group']]; + } + + // Write the changed handler values. $display->handler->set_option($types[$form_state['type']]['plural'], $new_fields); $display->handler->set_option('filter_groups', $groups); if (isset($form_state['view']->form_cache)) { @@ -3108,10 +3780,154 @@ function views_ui_rearrange_filter_form_submit($form, &$form_state) { } } + // Store in cache. + views_ui_cache_set($form_state['view']); +} + +/** + * Form to delete multiple items at once. + * + * @todo: All this relationship stuff is there three times. This should be abstracted out. + */ +function views_ui_item_delete_form($form, &$form_state) { + $view = &$form_state['view']; + $display_id = $form_state['display_id']; + $type = $form_state['type']; + + $types = views_object_types(); + if (!$view->set_display($display_id)) { + views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); + } + $display = &$view->display[$display_id]; + $form['#title'] = t('Delete @type', array('@type' => $types[$type]['ltitle'])); + $form['#section'] = $display_id . 'delete-item'; + + if ($display->handler->defaultable_sections($types[$type]['plural'])) { + $form_state['section'] = $types[$type]['plural']; + views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); + } + + $count = 0; + + // Get relationship labels + $relationships = array(); + foreach ($display->handler->get_handlers('relationship') as $id => $handler) { + $relationships[$id] = $handler->label(); + $handlers = $display->handler->get_option('relationships'); + if ($handlers) { + foreach ($handlers as $id => $info) { + $handler = $display->handler->get_handler('relationship', $id); + $relationships[$id] = $handler->label(); + } + } + } + + // Filters can now be grouped so we do a little bit extra: + $groups = array(); + $grouping = FALSE; + if ($type == 'filter') { + $group_info = $view->display_handler->get_option('filter_groups'); + if (!empty($group_info['groups']) && count($group_info['groups']) > 1) { + $grouping = TRUE; + $groups = array(0 => array()); + } + } + + foreach ($display->handler->get_option($types[$type]['plural']) as $id => $field) { + $form['fields'][$id] = array('#tree' => TRUE); + $handler = $display->handler->get_handler($type, $id); + if ($handler) { + $name = $handler->ui_name() . ' ' . $handler->admin_summary(); + if (!empty($field['relationship']) && !empty($relationships[$field['relationship']])) { + $name = '(' . $relationships[$field['relationship']] . ') ' . $name; + } + + $form['fields'][$id]['name'] = array( + '#markup' => $name, + ); + } + else { + $form['fields'][$id]['name'] = array('#markup' => t('Broken field @id', array('@id' => $id))); + } + $form['fields'][$id]['removed'] = array( + '#type' => 'checkbox', + '#id' => 'views-removed-' . $id, + '#attributes' => array('class' => array('views-remove-checkbox')), + '#default_value' => 0, + ); + } + + $name = NULL; + if (isset($form_state['update_name'])) { + $name = $form_state['update_name']; + } + + views_ui_standard_form_buttons($form, $form_state, 'views_ui_item_delete_form'); + return $form; +} + +/** + * Submit handler for delete form + */ +function views_ui_item_delete_form_submit($form, &$form_state) { + $types = views_object_types(); + $display = &$form_state['view']->display[$form_state['display_id']]; + + $old_fields = $display->handler->get_option($types[$form_state['type']]['plural']); + $new_fields = $order = array(); + + // Make an array with the weights + foreach ($form_state['values'] as $field => $info) { + // add each value that is a field, but only if + // it has had its 'removed' checkbox checked. + if (isset($form['fields'][$field]) && empty($info['removed'])) { + $order[$field] = $field; + } + } + + // Sort the array + asort($order); + + // Create a new list of fields in the new order. + foreach (array_keys($order) as $field) { + $new_fields[$field] = $old_fields[$field]; + } + $display->handler->set_option($types[$form_state['type']]['plural'], $new_fields); + // Store in cache views_ui_cache_set($form_state['view']); } +/** + * Turn the rearrange form into a proper table + */ +function theme_views_ui_item_delete_form($variables) { + $form = $variables['form']; + + $rows = array(); + foreach (element_children($form['fields']) as $id) { + if (isset($form['fields'][$id]['name'])) { + $row = array(); + $row[] = drupal_render($form['fields'][$id]['name']); + $row[] = drupal_render($form['fields'][$id]['removed']) . l('<span>' . t('Remove') . '</span>', 'javascript:void()', array('attributes' => array('id' => 'views-remove-link-' . $id, 'class' => array('views-hidden', 'views-button-remove', 'views-remove-link'), 'alt' => t('Remove this item'), 'title' => t('Remove this item')), 'html' => TRUE)); + $rows[] = array('data' => $row, 'class' => array('draggable'), 'id' => 'views-row-' . $id); + } + } + if (empty($rows)) { + $rows[] = array(array('data' => t('No fields available.'), 'colspan' => '2')); + } + + $header = array('', t('Remove')); + $output = drupal_render($form['override']); + $output .= '<div class="scroll">'; + $output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'arrange'))); + $output .= '</div>'; + $output .= drupal_render_children($form); + + return $output; +} + + /** * Form to add_item items in the views UI. */ @@ -3120,6 +3936,13 @@ function views_ui_add_item_form($form, &$form_state) { $display_id = $form_state['display_id']; $type = $form_state['type']; + $form = array( + 'options' => array( + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ), + ); + ctools_add_js('dependent'); if (!$view->set_display($display_id)) { @@ -3134,8 +3957,7 @@ function views_ui_add_item_form($form, &$form_state) { $type = $types[$type]['type']; } - $form['#title'] = check_plain($display->display_title) . ': '; - $form['#title'] .= t('Add @type', array('@type' => $ltitle)); + $form['#title'] = t('Add @type', array('@type' => $ltitle)); $form['#section'] = $display_id . 'add-item'; // Figure out all the base tables allowed based upon what the relationships provide. @@ -3143,16 +3965,26 @@ function views_ui_add_item_form($form, &$form_state) { $options = views_fetch_fields(array_keys($base_tables), $type, $display->handler->use_group_by()); if (!empty($options)) { + $form['options']['controls'] = array( + '#theme_wrappers' => array('container'), + '#id' => 'views-filterable-options-controls', + '#attributes' => array('class' => array('container-inline')), + ); + $form['options']['controls']['options_search'] = array( + '#type' => 'textfield', + '#title' => t('Search'), + ); + $groups = array('all' => t('- All -')); - $form['group'] = array( + $form['options']['controls']['group'] = array( '#type' => 'select', - '#title' => t('Groups'), + '#title' => t('Filter'), '#options' => array(), '#attributes' => array('class' => array('ctools-master-dependent')), ); - $form['name'] = array( - '#prefix' => '<div class="views-radio-box form-checkboxes">', + $form['options']['name'] = array( + '#prefix' => '<div class="views-radio-box form-checkboxes views-filterable-options">', '#suffix' => '</div>', '#tree' => TRUE, '#default_value' => 'all', @@ -3168,27 +4000,40 @@ function views_ui_add_item_form($form, &$form_state) { } foreach ($grouped_options as $group => $group_options) { - $form['name'][$group . '_start']['#markup'] = '<div class="ctools-dependent-all ctools-dependent-' . $group . '">'; + $form['options']['name'][$group . '_start']['#markup'] = '<div class="ctools-dependent-all ctools-dependent-' . $group . '">'; + $zebra = 0; foreach ($group_options as $key => $option) { - $form['name'][$key] = array( + $zebra_class = ($zebra % 2) ? 'odd' : 'even'; + $form['options']['name'][$key] = array( '#type' => 'checkbox', '#title' => t('!group: !field', array('!group' => $option['group'], '!field' => $option['title'])), '#description' => $option['help'], '#return_value' => $key, + '#prefix' => "<div class='$zebra_class filterable-option'>", + '#suffix' => '</div>', ); + $zebra++; } - $form['name'][$group . '_end']['#markup'] = '</div>'; + $form['options']['name'][$group . '_end']['#markup'] = '</div>'; } - $form['group']['#options'] = $groups; + $form['options']['controls']['group']['#options'] = $groups; } else { - $form['markup'] = array( + $form['options']['markup'] = array( '#markup' => '<div class="form-item">' . t('There are no @types available to add.', array('@types' => $types[$type]['ltitle'])) . '</div>', ); } + // Add a div to show the selected items + $form['selected'] = array( + '#type' => 'item', + '#markup' => '<div class="views-selected-options"></div>', + '#title' => t('Selected') . ':', + '#theme_wrappers' => array('form_element', 'views_container'), + '#attributes' => array('class' => array('container-inline', 'views-add-form-selected')), + ); ctools_include('dependent'); - views_ui_standard_form_buttons($form, $form_state, 'views_ui_add_item_form', t('Add')); + views_ui_standard_form_buttons($form, $form_state, 'views_ui_add_item_form', t('Add and configure @types', array('@types' => $types[$type]['ltitle']))); return $form; } @@ -3239,7 +4084,13 @@ function views_ui_config_item_form($form, &$form_state) { $type = $form_state['type']; $id = $form_state['id']; - $form = array('options' => array('#tree' => TRUE)); + $form = array( + 'options' => array( + '#tree' => TRUE, + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ), + ); if (!$view->set_display($display_id)) { views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); } @@ -3248,14 +4099,16 @@ function views_ui_config_item_form($form, &$form_state) { if ($item) { $handler = $view->display_handler->get_handler($type, $id); if (empty($handler)) { - $form['markup'] = array('#value' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); + $form['markup'] = array('#markup' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); } else { $types = views_object_types(); + // If this item can come from the default display, show a dropdown + // that lets the user choose which display the changes should apply to. if ($view->display_handler->defaultable_sections($types[$type]['plural'])) { $form_state['section'] = $types[$type]['plural']; - $view->display_handler->add_override_button($form['options'], $form_state, $form_state['section']); + views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); } // A whole bunch of code to figure out what relationships are valid for @@ -3308,6 +4161,7 @@ function views_ui_config_item_form($form, &$form_state) { '#title' => t('Relationship'), '#options' => $relationship_options, '#default_value' => $rel, + '#weight' => -500, ); } else { @@ -3317,16 +4171,16 @@ function views_ui_config_item_form($form, &$form_state) { ); } - $form['#title'] = check_plain($view->display[$display_id]->display_title) . ': '; - $form['#title'] .= t('Configure @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->ui_name())); + $form['#title'] = t('Configure @type: @item', array('@type' => $types[$type]['lstitle'], '@item' => $handler->ui_name())); - $form['form_description'] = array( - '#type' => 'markup', - '#weight' => -1000, - '#prefix' => '<div class="form-item description">', - '#suffix' => '</div>', - '#value' => $handler->definition['help'], - ); + if (!empty($handler->definition['help'])) { + $form['options']['form_description'] = array( + '#markup' => $handler->definition['help'], + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('form-item description')), + '#weight' => -1000, + ); + } $form['#section'] = $display_id . '-' . $type . '-' . $id; @@ -3341,6 +4195,8 @@ function views_ui_config_item_form($form, &$form_state) { } views_ui_standard_form_buttons($form, $form_state, 'views_ui_config_item_form', $name, t('Remove'), 'remove'); + // Don't execute validations for the remove button. + $form['buttons']['remove']['#limit_validation_errors'] = array(); } return $form; } @@ -3356,6 +4212,44 @@ function views_ui_config_item_form_validate($form, &$form_state) { } } +/** + * A submit handler that is used for storing temporary items when using + * multi-step changes, such as ajax requests. + */ +function views_ui_config_item_form_submit_temporary($form, &$form_state) { + // Run it through the handler's submit function. + $form_state['handler']->options_submit($form['options'], $form_state); + $item = $form_state['handler']->options; + $types = views_object_types(); + + $type = $form_state['type']; + if (!empty($types[$type]['type'])) { + $type = $types[$type]['type']; + } + + // 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); + $handler->init($form_state['view'], $item); + + + // Add the incoming options to existing options because items using + // the extra form may not have everything in the form here. + $options = $form_state['values']['options'] + $form_state['handler']->options; + + // This unpacks only options that are in the definition, ensuring random + // extra stuff on the form is not sent through. + $handler->unpack_options($handler->options, $options, NULL, FALSE); + + // Store the item back on the view + $form_state['view']->temporary_options[$type][$form_state['id']] = $handler->options; + + $form_state['rerender'] = TRUE; + $form_state['rebuild'] = TRUE; + // Write to cache + views_ui_cache_set($form_state['view']); +} + /** * Submit handler for configing new item(s) to a view. */ @@ -3386,8 +4280,10 @@ function views_ui_config_item_form_submit($form, &$form_state) { // Store the item back on the view $form_state['view']->set_item($form_state['display_id'], $form_state['type'], $form_state['id'], $handler->options); - if ($form_state['handler'] && $form_state['handler']->needs_style_plugin()) { - views_ui_add_form_to_stack('change-style', $form_state['view'], $form_state['display_id'], array($form_state['type'], $form_state['id']), TRUE); + + // Ensure any temporary options are removed. + if (isset($form_state['view']->temporary_options[$type][$form_state['id']])) { + unset($form_state['view']->temporary_options[$type][$form_state['id']]); } // Write to cache @@ -3403,7 +4299,13 @@ function views_ui_config_item_group_form($type, &$form_state) { $type = $form_state['type']; $id = $form_state['id']; - $form = array('options' => array('#tree' => TRUE)); + $form = array( + 'options' => array( + '#tree' => TRUE, + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ), + ); if (!$view->set_display($display_id)) { views_ajax_render(t('Invalid display id @display', array('@display' => $display_id))); } @@ -3415,11 +4317,15 @@ function views_ui_config_item_group_form($type, &$form_state) { if ($item) { $handler = $view->display_handler->get_handler($type, $id); if (empty($handler)) { - $form['markup'] = array('#value' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); + $form['markup'] = array('#markup' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); } else { $handler->init($view, $item); - $handler->groupby_form($form, $form_state); + $types = views_object_types(); + + $form['#title'] = t('Configure group settings for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->ui_name())); + + $handler->groupby_form($form['options'], $form_state); $form_state['handler'] = &$handler; } @@ -3489,7 +4395,13 @@ function views_ui_config_item_extra_form($form, &$form_state) { $type = $form_state['type']; $id = $form_state['id']; - $form = array('options' => array('#tree' => TRUE)); + $form = array( + 'options' => array( + '#tree' => TRUE, + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ), + ); if (!$view->set_display($display_id)) { views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); } @@ -3498,14 +4410,13 @@ function views_ui_config_item_extra_form($form, &$form_state) { if ($item) { $handler = views_get_handler($item['table'], $item['field'], $type); if (empty($handler)) { - $form['markup'] = array('#value' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); + $form['markup'] = array('#markup' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); } else { $handler->init($view, $item); $types = views_object_types(); - $form['#title'] = check_plain($view->display[$display_id]->display_title) . ': '; - $form['#title'] .= t('Configure extra settings for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->ui_name())); + $form['#title'] = t('Configure extra settings for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->ui_name())); $form['#section'] = $display_id . '-' . $type . '-' . $id; @@ -3546,91 +4457,6 @@ function views_ui_config_item_extra_form_submit($form, &$form_state) { views_ui_cache_set($form_state['view']); } -/** - * Form to change_style items in the views UI. - */ -function views_ui_change_style_form($form, &$form_state) { - $view = &$form_state['view']; - $display_id = $form_state['display_id']; - $type = $form_state['type']; - $id = $form_state['id']; - - $form = array('options' => array('#tree' => TRUE)); - if (!$view->set_display($display_id)) { - views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); - } - $item = $view->get_item($display_id, $type, $id); - - if ($item) { - $handler = views_get_handler($item['table'], $item['field'], $type); - if (empty($handler)) { - $form['markup'] = array('#value' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); - } - else { - $handler->init($view, $item); - $types = views_object_types(); - $form['#title'] = t('Change summary style for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->ui_name())); - - $form['#section'] = $display_id . '-' . $type . '-' . $id . '-style-plugin'; - - $form['style_plugin'] = array( - '#type' => 'radios', - '#options' => views_fetch_plugin_names('style', 'summary'), - '#default_value' => $item['style_plugin'], - ); - - $form_state['handler'] = &$handler; - } - views_ui_standard_form_buttons($form, $form_state, 'views_ui_change_style_form'); - } - return $form; -} - -function views_ui_change_style_form_validate($form, &$form_state) { - // Run it through the handler's submit function. - $form_state['handler']->options_validate($form['options'], $form_state); - - $plugin = views_get_plugin('style', $form_state['values']['style_plugin']); - if (!$plugin) { - form_error($form['style_plugin'], t('Internal error: broken plugin.')); - } -} - -/** - * Submit handler for configing new item(s) to a view. - */ -function views_ui_change_style_form_submit($form, &$form_state) { - // Run it through the handler's submit function. - $form_state['handler']->options_submit($form['options'], $form_state); - $item = $form_state['handler']->options; - - $plugin = views_get_plugin('style', $form_state['values']['style_plugin']); - if (!$plugin) { - drupal_set_message(t('Internal error: broken plugin.'), 'error'); - return; - } - - $plugin->init($form_state['view'], $form_state['view']->display[$form_state['display_id']]); - - // If changing style plugin, reset options to defaults. - if (empty($item['style_plugin']) || $item['style_plugin'] != $form_state['values']['style_plugin']) { - $item['style_options'] = $plugin->options; - } - - // Store the data we're given. - $item['style_plugin'] = $form_state['values']['style_plugin']; - - // Store the item back on the view - $form_state['view']->set_item($form_state['display_id'], $form_state['type'], $form_state['id'], $item); - - if (!empty($plugin->definition['uses options'])) { - views_ui_add_form_to_stack('config-style', $form_state['view'], $form_state['display_id'], array($form_state['type'], $form_state['id']), TRUE); - } - - // Write to cache - views_ui_cache_set($form_state['view']); -} - /** * Form to config_style items in the views UI. */ @@ -3640,7 +4466,13 @@ function views_ui_config_style_form($form, &$form_state) { $type = $form_state['type']; $id = $form_state['id']; - $form = array('options' => array('#tree' => TRUE)); + $form = array( + 'options' => array( + '#tree' => TRUE, + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ), + ); if (!$view->set_display($display_id)) { views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); } @@ -3649,14 +4481,13 @@ function views_ui_config_style_form($form, &$form_state) { if ($item) { $handler = views_get_handler($item['table'], $item['field'], $type); if (empty($handler)) { - $form['markup'] = array('#value' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); + $form['markup'] = array('#markup' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); } else { $handler->init($view, $item); $types = views_object_types(); - $form['#title'] = check_plain($view->display[$display_id]->display_title) . ': '; - $form['#title'] .= t('Configure summary style for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->ui_name())); + $form['#title'] = t('Configure summary style for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->ui_name())); $form['#section'] = $display_id . '-' . $type . '-style-options'; @@ -3713,103 +4544,166 @@ function views_ui_get_roles() { } /** - * Page callback for the Views enable page. + * Form builder for the admin display defaults page. */ -function views_ui_enable_page($view) { - $views_status = variable_get('views_defaults', array()); - $views_status[$view->name] = FALSE; // FALSE is enabled - variable_set('views_defaults', $views_status); - views_invalidate_cache(); - menu_rebuild(); - drupal_goto('admin/structure/views'); -} +function views_ui_admin_settings_basic() { + $form = array(); + $form['#attached']['css'] = views_ui_get_admin_css(); -/** - * Page callback for the Views enable page - */ -function views_ui_disable_page($view) { - $views_status = variable_get('views_defaults', array()); - $views_status[$view->name] = TRUE; // True is disabled - variable_set('views_defaults', $views_status); - views_invalidate_cache(); - menu_rebuild(); - drupal_goto('admin/structure/views'); -} + // This is not currently a fieldset but we may want it to be later, + // so this will make it easier to change if we do. + $form['basic'] = array(); -/** - * Page callback for the tools - other page - */ -function views_ui_admin_tools() { - $form['clear_cache'] = array( - '#type' => 'submit', - '#value' => t("Clear Views' cache"), - '#submit' => array('views_ui_tools_clear_cache'), + $form['basic']['views_ui_show_listing_filters'] = array( + '#type' => 'checkbox', + '#title' => t('Show filters on the list of views'), + '#default_value' => variable_get('views_ui_show_listing_filters', FALSE), + ); + $form['basic']['views_ui_show_advanced_help_warning'] = array( + '#type' => 'checkbox', + '#title' => t('Show advanced help warning'), + '#default_value' => variable_get('views_ui_show_advanced_help_warning', TRUE), ); - $form['views_sql_signature'] = array( + $form['basic']['views_ui_show_master_display'] = 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."), - '#default_value' => variable_get('views_sql_signature', FALSE), + '#title' => t('Always show the master display'), + '#description' => t('Advanced users of views may choose to see the master (i.e. default) display.'), + '#default_value' => variable_get('views_ui_show_master_display', FALSE), ); - $form['views_skip_cache'] = array( + $form['basic']['views_ui_show_advanced_column'] = array( '#type' => 'checkbox', - '#title' => t('Disable views data caching'), - '#description' => t("Views caches data about tables, modules and views available, to increase performance. By checking this box, Views will skip this cache and always rebuild this data when needed. This can have a serious performance impact on your site."), - '#default_value' => variable_get('views_skip_cache', FALSE), + '#title' => t('Always show advanced display settings'), + '#description' => t('Default to showing advanced display settings, such as relationships and contextual filters.'), + '#default_value' => variable_get('views_ui_show_advanced_column', FALSE), ); - $form['views_hide_help_message'] = array( + $form['basic']['views_exposed_filter_any_label'] = array( + '#type' => 'select', + '#title' => t('Label for "Any" value on non-required single-select exposed filters'), + '#options' => array('old_any' => '<Any>', 'new_any' => t('- Any -')), + '#default_value' => variable_get('views_exposed_filter_any_label', 'new_any'), + ); + + $form['live_preview'] = array( + '#type' => 'fieldset', + '#title' => t('Live preview settings'), + ); + + $form['live_preview']['views_ui_always_live_preview'] = array( + '#type' => 'checkbox', + '#title' => t('Automatically update preview on changes'), + '#default_value' => variable_get('views_ui_always_live_preview', TRUE), + ); + $form['live_preview']['views_ui_always_live_preview_button'] = array( '#type' => 'checkbox', - '#title' => t('Ignore missing advanced help module'), - '#description' => t("Views uses the advanced help module to provide help text; if this module is not present Views will complain, unless this setting is checked."), - '#default_value' => variable_get('views_hide_help_message', FALSE), + '#title' => t('Always show the preview button, even the automatically update is checked.'), + '#default_value' => variable_get('views_ui_always_live_preview_button', FALSE), ); - $form['views_ui_query_on_top'] = array( + $form['live_preview']['views_ui_show_preview_information'] = array( '#type' => 'checkbox', - '#title' => t('Show query above live preview'), - '#description' => t("The live preview feature will show you the output of the view you're creating, as well as the view. Check here to show the query and other information above the view; leave this unchecked to show that information below the view."), - '#default_value' => variable_get('views_ui_query_on_top', FALSE), + '#title' => t('Show information and statistics about the view during live preview'), + '#default_value' => variable_get('views_ui_show_preview_information', TRUE), + ); + + $form['live_preview']['views_ui_show_sql_query_where'] = array( + '#type' => 'radios', + '#options' => array( + 'above' => t('Above the preview'), + 'below' => t('Below the preview'), + ), + '#id' => 'edit-show-sql', + '#default_value' => variable_get('views_ui_show_sql_query_where', 'above'), + '#dependency' => array('edit-views-ui-show-preview-information' => array(TRUE)), + '#prefix' => '<div id="edit-show-sql-wrapper" class="views-dependent">', + '#suffix' => '</div>', ); - $form['views_ui_disable_live_preview'] = array( + $form['live_preview']['views_ui_show_sql_query'] = array( + '#type' => 'checkbox', + '#title' => t('Show the SQL query'), + '#default_value' => variable_get('views_ui_show_sql_query', FALSE), + '#dependency' => array('edit-views-ui-show-preview-information' => array(TRUE)), + ); + $form['live_preview']['views_ui_show_performance_statistics'] = array( '#type' => 'checkbox', - '#title' => t('Disable automatic live preview'), - '#description' => t("Don't automatically update the preview. This can speed up the editing of views a bit.'"), - '#default_value' => variable_get('views_ui_disable_live_preview', 0), + '#title' => t('Show performance statistics'), + '#default_value' => variable_get('views_ui_show_performance_statistics', FALSE), + '#dependency' => array('edit-views-ui-show-preview-information' => array(TRUE)), ); - $form['views_show_additional_queries'] = array( + $form['live_preview']['views_show_additional_queries'] = array( '#type' => 'checkbox', '#title' => t('Show other queries run during render during live preview'), '#description' => t("Drupal has the potential to run many queries while a view is being rendered. Checking this box will display every query run during view render as part of the live preview."), '#default_value' => variable_get('views_show_additional_queries', FALSE), + '#dependency' => array('edit-views-ui-show-preview-information' => array(TRUE)), + ); + +// $form['live_preview']['views_ui_show_performance_statistics_where'] = array( + + return system_settings_form($form); +} + +/** + * Form builder for the advanced admin settings page. + */ +function views_ui_admin_settings_advanced() { + $form = array(); + $form['#attached']['css'] = views_ui_get_admin_css(); + + $form['cache'] = array( + '#type' => 'fieldset', + '#title' => t('Caching'), + ); + + $form['cache']['views_skip_cache'] = array( + '#type' => 'checkbox', + '#title' => t('Disable views data caching'), + '#description' => t("Views caches data about tables, modules and views available, to increase performance. By checking this box, Views will skip this cache and always rebuild this data when needed. This can have a serious performance impact on your site."), + '#default_value' => variable_get('views_skip_cache', FALSE), + ); + + $form['cache']['clear_cache'] = array( + '#type' => 'submit', + '#value' => t("Clear Views' cache"), + '#submit' => array('views_ui_tools_clear_cache'), + ); + + $form['debug'] = array( + '#type' => 'fieldset', + '#title' => t('Debugging'), ); - $form['views_no_hover_links'] = array( + $form['debug']['views_sql_signature'] = array( '#type' => 'checkbox', - '#title' => t('Do not show hover links over views'), - '#description' => t("To make it easier to administrate your views, Views provides 'hover' links to take you to the edit and export screen of a view whenever the view is used. This can be distracting on some themes, though; if it is problematic, you can turn it off here."), - '#default_value' => variable_get('views_no_hover_links', FALSE), + '#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."), + '#default_value' => variable_get('views_sql_signature', FALSE), + ); + + $form['debug']['views_no_javascript'] = array( + '#type' => 'checkbox', + '#title' => t('Disable JavaScript with Views'), + '#description' => t("If you are having problems with the JavaScript, you can disable it here. The Views UI should degrade and still be usable without javascript; it's just not as good."), + '#default_value' => variable_get('views_no_javascript', FALSE), ); - $form['views_devel_output'] = array( + $form['debug']['views_devel_output'] = array( '#type' => 'checkbox', '#title' => t('Enable views performance statistics via the Devel module'), '#description' => t("Check this to enable some Views query and performance statistics <em>if Devel is installed</em>."), '#default_value' => variable_get('views_devel_output', FALSE), ); - $form['views_no_javascript'] = array( - '#type' => 'checkbox', - '#title' => t('Disable javascript with Views'), - '#description' => t("If you are having problems with the javascript, you can disable it here; the Views UI should degrade and still be usable without javascript, it just not as good."), - '#default_value' => variable_get('views_no_javascript', FALSE), + $form['locale'] = array( + '#type' => 'fieldset', + '#title' => t('Localization'), ); - $form['views_localization_plugin'] = array( + $form['locale']['views_localization_plugin'] = array( '#type' => 'radios', '#title' => t('Translation method'), '#options' => views_fetch_plugin_names('localization', NULL, array(), TRUE), @@ -3820,18 +4714,12 @@ function views_ui_admin_tools() { $regions = system_region_list(variable_get('theme_default', 'garland')); $regions['watchdog'] = t('Watchdog'); - $form['views_devel_region'] = array( + $form['debug']['views_devel_region'] = array( '#type' => 'select', '#title' => t('Page region to output performance statistics'), '#default_value' => variable_get('views_devel_region', 'footer'), '#options' => $regions, - ); - - $form['views_exposed_filter_any_label'] = array( - '#type' => 'select', - '#title' => t('Label for "Any" value on optional single-select exposed filters'), - '#options' => array('old_any' => '<Any>', 'new_any' => t('- Any -')), - '#default_value' => variable_get('views_exposed_filter_any_label', 'old_any'), + '#dependency' => array('edit-views-devel-output' => array(1)), ); return system_settings_form($form); @@ -3884,20 +4772,13 @@ function views_ui_autocomplete_tag($string = '') { $matches = array(); // get matches from default views: views_include('view'); - $views = views_discover_default_views(); + $views = views_get_all_views(); foreach ($views as $view) { if (!empty($view->tag) && strpos($view->tag, $string) === 0) { $matches[$view->tag] = $view->tag; - } - } - - $count = 10 - count($matches); - if ($string) { - $result = db_query_range("SELECT DISTINCT tag FROM {views_view} WHERE LOWER(tag) LIKE LOWER(:tag)", - 0, $count, - array(':tag' => $string . '%')); - foreach ($result as $view) { - $matches[$view->tag] = check_plain($view->tag); + if (count($matches) >= 10) { + break; + } } } @@ -3934,7 +4815,7 @@ function views_fetch_base_tables() { if (!empty($info['table']['base'])) { $tables[$table] = array( 'title' => $info['table']['base']['title'], - 'description' => $info['table']['base']['help'], + 'description' => !empty($info['table']['base']['help']) ? $info['table']['base']['help'] : '', 'weight' => !empty($info['table']['base']['weight']) ? $info['table']['base']['weight'] : 0, ); } @@ -4009,6 +4890,10 @@ function views_fetch_fields($base, $type, $grouping = FALSE) { $skip_bases[$field][$key][$base_name] = TRUE; } } + // Don't show old fields. The real field will be added right. + if (isset($info[$key]['moved to'])) { + continue; + } foreach (array('title', 'group', 'help', 'base') as $string) { // First, try the lowest possible level if (!empty($info[$key][$string])) { @@ -4065,43 +4950,6 @@ function views_fetch_fields($base, $type, $grouping = FALSE) { return array(); } -/** - * Fetch a list of all base tables available - * - * @param $type - * Either 'display', 'style' or 'row' - * @param $key - * For style plugins, this is an optional type to restrict to. May be 'normal', - * 'summary', 'feed' or others based on the neds of the display. - * @param $base - * An array of possible base tables. - * - * @return - * A keyed array of in the form of 'base_table' => 'Description'. - */ -function views_fetch_plugin_names($type, $key = NULL, $base = array()) { - $data = views_fetch_plugin_data(); - - $plugins[$type] = array(); - - foreach ($data[$type] as $id => $plugin) { - // Skip plugins that don't conform to our key. - if ($key && (empty($plugin['type']) || $plugin['type'] != $key)) { - continue; - } - if (empty($plugin['no ui']) && (empty($base) || empty($plugin['base']) || array_intersect($base, $plugin['base']))) { - $plugins[$type][$id] = $plugin['title']; - } - } - - if (!empty($plugins[$type])) { - asort($plugins[$type]); - return $plugins[$type]; - } - // fall-through - return array(); -} - /** * Theme the form for the table style plugin @@ -4165,3 +5013,79 @@ function theme_views_ui_style_plugin_table($variables) { $output .= drupal_render_children($form); return $output; } + +/** + * Placeholder function for overriding $display->display_title. + * + * @todo Remove this function once editing the display title is possible. + */ +function views_ui_get_display_label($view, $display_id, $check_changed = TRUE) { + $title = $display_id == 'default' ? t('Master') : check_plain($view->display[$display_id]->display_title); + + if ($check_changed && !empty($view->changed_display[$display_id])) { + $changed = '*'; + $title = $title . $changed; + } + + return $title; +} + +function views_ui_add_template_page() { + $templates = views_get_all_templates(); + + if (empty($templates)) { + return t('There are no templates available.'); + } + + $header = array( + t('Name'), + t('Description'), + t('Operation'), + ); + + $rows = array(); + foreach ($templates as $name => $template) { + $rows[] = array( + array('data' => check_plain($template->get_human_name())), + array('data' => check_plain($template->description)), + array('data' => l('add', 'admin/structure/views/template/' . $template->name . '/add')), + ); + } + + $output = theme('table', array('header' => $header, 'rows' => $rows)); + return $output; +} + +/** + * #process callback for a button; determines if a button is the form's triggering element. + * + * The Form API has logic to determine the form's triggering element based on + * the data in $_POST. However, it only checks buttons based on a single #value + * per button. This function may be added to a button's #process callbacks to + * extend button click detection to support multiple #values per button. If the + * data in $_POST matches any value in the button's #values array, then the + * button is detected as having been clicked. This can be used when the value + * (label) of the same logical button may be different based on context (e.g., + * "Apply" vs. "Apply and continue"). + * + * @see _form_builder_handle_input_element() + * @see _form_button_was_clicked() + */ +function views_ui_form_button_was_clicked($element, &$form_state) { + $process_input = empty($element['#disabled']) && ($form_state['programmed'] || ($form_state['process_input'] && (!isset($element['#access']) || $element['#access']))); + if ($process_input && !isset($form_state['triggering_element']) && isset($element['#button_type']) && isset($form_state['input'][$element['#name']]) && isset($element['#values']) && in_array($form_state['input'][$element['#name']], $element['#values'], TRUE)) { + $form_state['triggering_element'] = $element; + } + return $element; +} + +/** + * #process callback for a button; makes implicit form submissions trigger as this button. + * + * @see Drupal.behaviors.viewsImplicitFormSubmission + */ +function views_ui_default_button($element, &$form_state, $form) { + $setting['viewsImplicitFormSubmission'][$form['#id']]['defaultButton'] = $element['#id']; + $element['#attached']['js'][] = array('type' => 'setting', 'data' => $setting); + return $element; +} diff --git a/sites/all/modules/views/includes/ajax.inc b/sites/all/modules/views/includes/ajax.inc index ac006f983570c8c03fc81da0979a3b7e67d87d88..96cdc8dc2099a0e792f910e3ad13a2aa74b4946a 100644 --- a/sites/all/modules/views/includes/ajax.inc +++ b/sites/all/modules/views/includes/ajax.inc @@ -1,5 +1,4 @@ <?php -// $Id: ajax.inc,v 1.20.4.17 2011/01/03 22:56:39 merlinofchaos Exp $ /** * @file ajax.inc @@ -26,6 +25,19 @@ function views_ajax() { $arg = explode('/', $_REQUEST['view_path']); + // Remove all of this stuff from $_GET so it doesn't end up in pagers and tablesort URLs. + foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', 'ajax_html_ids', 'ajax_page_state') as $key) { + if (isset($_GET[$key])) { + unset($_GET[$key]); + } + if (isset($_REQUEST[$key])) { + unset($_REQUEST[$key]); + } + if (isset($_POST[$key])) { + unset($_POST[$key]); + } + } + // Load the view. $view = views_get_view($name); if ($view && $view->access($display_id)) { @@ -137,40 +149,42 @@ function views_ajax_command_add_tab($id, $title, $body) { } /** - * Disables Save, Cancel, and Delete buttons. + * Shows Save and Cancel buttons. * * @return * An array suitable for use with the ajax_render() function. */ -function views_ajax_command_disable_buttons() { +function views_ajax_command_show_buttons() { $command = array( - 'command' => 'viewsDisableButtons', + 'command' => 'viewsShowButtons', ); return $command; } /** - * Enables Save, Cancel, and Delete buttons. + * Trigger the Views live preview. * * @return * An array suitable for use with the ajax_render() function. */ -function views_ajax_command_enable_buttons() { +function views_ajax_command_trigger_preview() { $command = array( - 'command' => 'viewsEnableButtons', + 'command' => 'viewsTriggerPreview', ); return $command; } /** - * Trigger the Views live preview. + * Replace the page title. * * @return * An array suitable for use with the ajax_render() function. */ -function views_ajax_command_trigger_preview() { +function views_ajax_command_replace_title($title) { $command = array( - 'command' => 'viewsTriggerPreview', + 'command' => 'viewsReplaceTitle', + 'title' => $title, + 'siteName' => variable_get('site_name', 'Drupal'), ); return $command; } @@ -207,6 +221,7 @@ function views_ajax_form_wrapper($form_id, &$form_state) { // These forms have the title built in, so set the title here: if (empty($form_state['ajax']) && !empty($form_state['title'])) { drupal_set_title($form_state['title']); + drupal_add_css(drupal_get_path('module', 'views_ui') . '/css/views-admin.css'); } if (!empty($form_state['ajax']) && (empty($form_state['executed']) || !empty($form_state['rerender']))) { diff --git a/sites/all/modules/views/includes/analyze.inc b/sites/all/modules/views/includes/analyze.inc index 4d9256fff64d4b8213b3e63c5e67ffb3a2b8a61c..725aed91f7a9f6acee0ef8f2166b6a3396f2f96a 100644 --- a/sites/all/modules/views/includes/analyze.inc +++ b/sites/all/modules/views/includes/analyze.inc @@ -1,5 +1,4 @@ <?php -// $Id: analyze.inc,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * @file diff --git a/sites/all/modules/views/includes/base.inc b/sites/all/modules/views/includes/base.inc index 3388163dadc2c966e2aa4fc8fd07293b7bf4c65a..d53fd8655eab70a5d66820b98090f72bb6d66f77 100644 --- a/sites/all/modules/views/includes/base.inc +++ b/sites/all/modules/views/includes/base.inc @@ -1,5 +1,4 @@ <?php -// $Id: base.inc,v 1.3.4.6 2010/12/01 20:05:06 dereine Exp $ /** * @file * @@ -14,6 +13,14 @@ class views_object { * Except for displays, options for the object will be held here. */ var $options = array(); + + /** + * The top object of a view. + * + * @var view + */ + var $view = NULL; + /** * Information about options for all kinds of purposes will be held here. * @code @@ -88,6 +95,18 @@ class views_object { if (!empty($this->view)) { // Ensure we have a localization plugin. $this->view->init_localization(); + + // Set up default localization keys. Handlers and such set this for us + if (empty($localization_keys) && isset($this->localization_keys)) { + $localization_keys = $this->localization_keys; + } + // but plugins don't because there isn't a common init() these days. + else if (!empty($this->is_plugin)) { + if ($this->plugin_type != 'display') { + $localization_keys = array($this->view->current_display); + $localization_keys[] = $this->plugin_type; + } + } } foreach ($options as $key => $value) { @@ -280,7 +299,7 @@ class views_object { foreach ($options as $key => $value) { $translation_keys = array_merge($keys, array($key)); if (is_array($value)) { - $this->unpack_translatable($translatable, $storage, $key, $definition, $parents, $translation_keys); + $this->unpack_translatable($translatable, $options, $key, $definition, $parents, $translation_keys); } else if (!empty($definition[$key]['translatable']) && !empty($value)) { // Build source data and add to the array diff --git a/sites/all/modules/views/includes/cache.inc b/sites/all/modules/views/includes/cache.inc index de438888bd1d11d6c364ba9e1750ba1cffaf11f7..aad87845a79d533d5b2fed538f74dbc215512441 100644 --- a/sites/all/modules/views/includes/cache.inc +++ b/sites/all/modules/views/includes/cache.inc @@ -1,5 +1,4 @@ <?php -// $Id: cache.inc,v 1.25.4.8 2010/10/26 19:06:26 dereine Exp $ /** * @file cache.inc * @@ -7,25 +6,16 @@ * build queries from. */ -/** - * Load views files on behalf of modules. - */ -function _views_include_handlers() { - views_module_include('views.inc'); -} - -/** - * Load default views files on behalf of modules. - */ -function _views_include_default_views() { - views_module_include('views_default.inc'); -} - /** * Fetch Views' data from the cache + * + * @param $move + * Under certain circumstances it makes sense to not get the moved table, but the old one. + * One example is views_get_handler. */ -function _views_fetch_data($table = NULL, $reset = FALSE) { +function _views_fetch_data($table = NULL, $move = TRUE, $reset = FALSE) { static $cache = NULL; + static $recursion_protection = array(); if (!isset($cache) || $reset) { $start = microtime(TRUE); // NOTE: This happens whether we retrieve them from cache or otherwise. @@ -51,7 +41,21 @@ function _views_fetch_data($table = NULL, $reset = FALSE) { return $cache; } if (isset($cache[$table])) { - return $cache[$table]; + // Support old views_data entries conversion. + if (isset($cache[$table]['moved to']) && $move) { + $moved_table = $cache[$table]['moved to']; + if (!empty($recursion_protection[$table])) { + // recursion detected! + return NULL; + } + $recursion_protection[$table] = TRUE; + $data = _views_fetch_data($moved_table); + $recursion_protection = array(); + return $data; + } + else { + return $cache[$table]; + } } // Return an empty array if there is no match. @@ -89,68 +93,6 @@ function _views_fetch_plugin_data($type = NULL, $plugin = NULL, $reset = FALSE) return array(); } -/** - * Scan all modules for default views and rebuild the default views cache. - * - * @return An associative array of all known default views. - */ -function _views_discover_default_views($reset = FALSE) { - static $cache = NULL; - - if (!isset($cache) || $reset) { - $index = views_cache_get('views_default_views_index', TRUE); - - // Retrieve each cached default view - if (!$reset && isset($index->data) && is_array($index->data)) { - $cache = array(); - foreach ($index->data as $view_name) { - $data = views_cache_get('views_default:' . $view_name, TRUE); - if (isset($data->data) && is_object($data->data)) { - $cache[$view_name] = $data->data; - } - } - } - // If missing index, rebuild the cache - else { - views_include_default_views(); - $cache = array(); - - foreach (module_implements('views_default_views') as $module) { - $results = call_user_func($module . "_views_default_views"); - if (!empty($results) && is_array($results)) { - foreach($results as $name => $view) { - // Only views with a sufficiently high api version are eligible. - if (!empty($view->api_version) && $view->api_version >= 2) { - // Do not cache dead handlers. - $view->destroy(); - if (!isset($cache[$name])) { - $cache[$name] = $view; - } - else { - watchdog('view', "View name '@name' is already taken", array('@name' => $name), WATCHDOG_ERROR); - } - } - } - } - } - - // Allow modules to modify default views before they are cached. - drupal_alter('views_default_views', $cache); - - // Cache the index - $index = array_keys($cache); - views_cache_set('views_default_views_index', $index, TRUE); - - // Cache each view - foreach ($cache as $name => $view) { - views_cache_set('views_default:' . $name, $view, TRUE); - } - } - } - - return $cache; -} - /** * Set a cached item in the views cache. * diff --git a/sites/all/modules/views/includes/convert.inc b/sites/all/modules/views/includes/convert.inc index 0cc58f39d7ca07c7c2427b53a0d4bb8711341cb5..4ad145f8ceaa06a62dbe4f535dec47fd6308b5c6 100644 --- a/sites/all/modules/views/includes/convert.inc +++ b/sites/all/modules/views/includes/convert.inc @@ -1,5 +1,4 @@ <?php -// $Id: convert.inc,v 1.17.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * @file convert.inc * @@ -367,7 +366,7 @@ function views1_import($imported) { // Use the count to emulate the old, hardcoded filter naming. $item['expose']['identifier'] = 'filter' . $count; $item['expose']['label'] = $field['label']; - $item['expose']['operator'] = $field['operator'] ? 'op' . $count : ''; + $item['expose']['operator_id'] = $field['operator'] ? 'op' . $count : ''; $item['expose']['optional'] = $field['optional']; $item['expose']['single'] = $field['single']; $view->set_item('default', 'filter', $id, $item); diff --git a/sites/all/modules/views/includes/form.inc b/sites/all/modules/views/includes/form.inc index 5517f1fbe8db1af88f01a23840e2fbe5feb77e65..9152ae94ab2d9c3df4487a1f9a64f30f45310a64 100644 --- a/sites/all/modules/views/includes/form.inc +++ b/sites/all/modules/views/includes/form.inc @@ -1,5 +1,4 @@ <?php -// $Id: form.inc,v 1.11.4.3 2010/04/12 21:59:58 dereine Exp $ /** * @file form.inc diff --git a/sites/all/modules/views/includes/handlers.inc b/sites/all/modules/views/includes/handlers.inc index fe8acea17e9d7b7ddc73e772901329a9f3bdf3ce..3c5633ccc625cb5e690f3659e2e12f35b1d942c6 100644 --- a/sites/all/modules/views/includes/handlers.inc +++ b/sites/all/modules/views/includes/handlers.inc @@ -1,5 +1,4 @@ <?php -// $Id: handlers.inc,v 1.119.4.22 2011/01/05 22:40:08 dereine Exp $ /** * @file handlers.inc * Defines the various handler objects to help build and display views. @@ -8,7 +7,7 @@ /** * Instantiate and construct a new handler */ -function _views_create_handler($definition, $type = 'handler') { +function _views_create_handler($definition, $type = 'handler', $handler_type = NULL) { // debug('Instantiating handler ' . $definition['handler']); if (empty($definition['handler'])) { return; @@ -32,6 +31,15 @@ function _views_create_handler($definition, $type = 'handler') { } $handler->set_definition($definition); + if ($type == 'handler') { + $handler->is_handler = TRUE; + $handler->handler_type = $handler_type; + } + else { + $handler->is_plugin = TRUE; + $handler->plugin_type = $type; + } + // let the handler have something like a constructor. $handler->construct(); @@ -41,7 +49,7 @@ function _views_create_handler($definition, $type = 'handler') { /** * Prepare a handler's data by checking defaults and such. */ -function _views_prepare_handler($definition, $data, $field) { +function _views_prepare_handler($definition, $data, $field, $type) { foreach (array('group', 'title', 'title short', 'help', 'real field') as $key) { if (!isset($definition[$key])) { // First check the field level @@ -55,7 +63,7 @@ function _views_prepare_handler($definition, $data, $field) { } } - return _views_create_handler($definition); + return _views_create_handler($definition, 'handler', $type); } /** @@ -91,6 +99,7 @@ function views_get_table_join($table, $base_table) { return $handler; } + // DEBUG -- identify missing handlers vpr("Missing join: $table $base_table"); } @@ -122,6 +131,20 @@ function views_get_table_join($table, $base_table) { * - access arguments: An array of arguments for the access callback. */ class views_handler extends views_object { + /** + * The top object of a view. + * + * @var view + */ + var $view = NULL; + + /** + * Where the $query object will reside: + * + * @var views_plugin_query + */ + var $query = NULL; + /** * init the handler with necessary data. * @param $view @@ -132,6 +155,36 @@ class views_handler extends views_object { */ function init(&$view, &$options) { $this->view = &$view; + $display_id = $this->view->current_display; + // Check to see if this handler type is defaulted. Note that + // we have to do a lookup because the type is singular but the + // option is stored as the plural. + + // If the 'moved to' keyword moved our handler, let's fix that now. + if (isset($this->actual_table)) { + $options['table'] = $this->actual_table; + } + + if (isset($this->actual_field)) { + $options['field'] = $this->actual_field; + } + + $types = views_object_types(); + $plural = $this->handler_type; + if (isset($types[$this->handler_type]['plural'])) { + $plural = $types[$this->handler_type]['plural']; + } + if ($this->view->display_handler->is_defaulted($plural)) { + $display_id = 'default'; + } + + $this->localization_keys = array( + $display_id, + $this->handler_type, + $options['table'], + $options['field'] + ); + $this->unpack_options($this->options, $options); // This exist on most handlers, but not all. So they are still optional. @@ -210,17 +263,75 @@ class views_handler extends views_object { return $field; } + /** + * Get the value that's supposed to be rendered. + * + * @param $values + * An object containing all retrieved values. + * @param $field + * Optional name of the field where the value is stored. + */ + function get_value($values, $field = NULL) { + $alias = isset($field) ? $this->aliases[$field] : $this->field_alias; + if (isset($values->{$alias})) { + return $values->{$alias}; + } + } + + /** + * Sanitize the value for output. + * + * @param $value + * The value being rendered. + * @param $type + * The type of sanitization needed. If not provided, check_plain() is used. + */ + function sanitize_value($value, $type = NULL) { + switch ($type) { + case 'xss': + $value = filter_xss($value); + break; + case 'url': + $value = check_url($value); + break; + default: + $value = check_plain($value); + break; + } + return $value; + } + /** * Validate the options form. */ function options_validate(&$form, &$form_state) { } + /** + * Build the options form. + */ function options_form(&$form, &$form_state) { + // Some form elements belong in a fieldset for presentation, but can't + // be moved into one because of the form_state['values'] hierarchy. Those + // elements can add a #fieldset => 'fieldset_name' property, and they'll + // be moved to their fieldset during pre_render. + $form['#pre_render'][] = 'views_ui_pre_render_add_fieldset_markup'; + $form['ui_name'] = array( '#type' => 'textfield', - '#title' => t('Administrative Title'), + '#title' => t('Administrative title'), '#description' => t('This title will be displayed on the views edit page instead of the default one. This might be useful if you have the same item twice.'), '#default_value' => $this->options['ui_name'], + '#fieldset' => 'more', + ); + + // This form is long and messy enough that the "Administrative title" option + // belongs in a "more options" fieldset at the bottom of the form. + $form['more'] = array( + '#type' => 'fieldset', + '#title' => t('More'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#weight' => 150, ); } @@ -266,7 +377,7 @@ class views_handler extends views_object { function groupby_form_submit(&$form, &$form_state) { $item =& $form_state['handler']->options; - $item['group_type'] = $form_state['values']['group_type']; + $item['group_type'] = $form_state['values']['options']['group_type']; } /** @@ -328,39 +439,9 @@ class views_handler extends views_object { function exposed_submit(&$form, &$form_state) { } /** - * Overridable form for exposed handler options. - * - * If overridden, it is best to call the parent or re-implement - * the stuff here. - * - * Many handlers will need to override this in order to provide options - * that are nicely tailored to the given filter. + * Form for exposed handler options. */ - function expose_form(&$form, &$form_state) { - $form['expose']['start_left'] = array( - '#markup' => '<div class="views-left-50">', - ); - - $this->expose_form_left($form, $form_state); - - $form['expose']['end_left'] = array( - '#markup' => '</div>', - ); - - $form['expose']['start_checkboxes'] = array( - '#markup' => '<div class="form-checkboxes views-left-40 clearfix">', - ); - - $this->expose_form_right($form, $form_state); - - $form['expose']['end_checkboxes'] = array( - '#markup' => '</div>', - ); - } - - function expose_form_left(&$form, &$form_state) { } - - function expose_form_right(&$form, &$form_state){ } + function expose_form(&$form, &$form_state) { } /** * Validate the options form. @@ -373,34 +454,10 @@ class views_handler extends views_object { */ function expose_submit($form, &$form_state) { } - /** + /** * Shortcut to display the expose/hide button. */ - function show_expose_button(&$form, &$form_state) { - $form['expose_button'] = array( - '#prefix' => '<div class="views-expose clearfix">', - '#suffix' => '</div>', - ); - if (empty($this->options['exposed'])) { - $form['expose_button']['button'] = array( - '#type' => 'submit', - '#value' => t('Expose'), - '#submit' => array('views_ui_config_item_form_expose'), - ); - $form['expose_button']['markup'] = array( - '#markup' => '<div class="description">' . t('This item is currently not exposed. If you <strong>expose</strong> it, users will be able to change the filter as they view it.') . '</div>', - ); - } - else { - $form['expose_button']['button'] = array( - '#type' => 'submit', - '#value' => t('Hide'), - '#submit' => array('views_ui_config_item_form_expose'), - ); - $form['expose_button']['markup'] = array( - '#markup' => '<div class="description">' . t('This item is currently exposed. If you <strong>hide</strong> it, users will not be able to change the filter as they view it.') . '</div>', ); - } - } + function show_expose_button(&$form, &$form_state) { } /** * Shortcut to display the exposed options form. @@ -410,10 +467,6 @@ class views_handler extends views_object { return; } - $form['expose'] = array( - '#prefix' => '<div class="views-expose-options clearfix">', - '#suffix' => '</div>', - ); $this->expose_form($form, $form_state); // When we click the expose button, we add new gadgets to the form but they @@ -596,7 +649,7 @@ class views_many_to_one_helper { $this->handler = &$handler; } - function option_definition(&$options) { + static function option_definition(&$options) { $options['reduce_duplicates'] = array('default' => FALSE); } @@ -829,9 +882,14 @@ class views_many_to_one_helper { $options = $this->handler->options; $operator = $this->handler->operator; $formula = !empty($this->formula); + $value = $this->handler->value; if (empty($options['group'])) { $options['group'] = 0; } + else { + $value = $this->handler->value; + $operator = 'IN'; + } $add_condition = TRUE; if ($operator == 'not') { @@ -851,28 +909,30 @@ class views_many_to_one_helper { $add_condition = FALSE; } - if ($formula) { - $placeholder = $this->placeholder(); - if ($operator == 'IN') { - $operator = "$operator IN($placeholder)"; + if (!$add_condition) { + if ($formula) { + $placeholder = $this->placeholder(); + if ($operator == 'IN') { + $operator = "$operator IN($placeholder)"; + } + else { + $operator = "$operator $placeholder"; + } + $placeholders = array( + $placeholder => $value, + ) + $this->placeholders; + $this->handler->query->add_where_expression($options['group'], "$field $operator", $placeholders); } else { - $operator = "$operator $placeholder"; + $this->handler->query->add_where($options['group'], $field, $value, $operator); } - $placeholders = array( - $placeholder => $value, - ) + $this->placeholders; - $this->handler->query->add_where_expression($options['group'], "$field $operator", $placeholders); - } - else { - $this->handler->query->add_where($options['group'], $field, $value, $operator); } if ($add_condition) { $field = $this->handler->real_field; $clause = $operator == 'or' ? db_or() : db_and(); foreach ($this->handler->table_aliases as $value => $alias) { - $clause->condition("$alias.$field", $this->handler->value); + $clause->condition("$alias.$field", $value); } // implode on either AND or OR. @@ -881,6 +941,58 @@ class views_many_to_one_helper { } } +/* + * Break x,y,z and x+y+z into an array. Numeric only. + * + * @param $str + * The string to parse. + * @param $handler + * The handler object to use as a base. + * + * @return $handler + * The new handler object. + */ +function views_break_phrase_string($str, &$handler) { + if (!$handler) { + $handler = new stdClass(); + } + + // Set up defaults: + if (!isset($handler->value)) { + $handler->value = array(); + } + + if (!isset($handler->operator)) { + $handler->operator = 'or'; + } + + if ($str == '') { + return $handler; + } + + if (preg_match('/^(\w+[+ ])+\w+$/', $str)) { + // The '+' character in a query string may be parsed as ' '. + $handler->operator = 'or'; + $handler->value = preg_split('/[+ ]/', $str); + } + else if (preg_match('/^(\w+,)*\w+$/', $str)) { + $handler->operator = 'and'; + $handler->value = explode(',', $str); + } + + // Keep an 'error' value if invalid strings were given. + if (!empty($str) && (empty($handler->value) || !is_array($handler->value))) { + $handler->value = array(-1); + return $handler; + } + + // Doubly ensure that all values are strings only. + foreach ($handler->value as $id => $value) { + $handler->value[$id] = (string) $value; + } + + return $handler; +} /* * Break x,y,z and x+y+z into an array. Numeric only. * @@ -893,47 +1005,47 @@ class views_many_to_one_helper { * @return $filter * The new filter object. */ -function views_break_phrase($str, $filter = NULL) { - if (!$filter) { - $filter = new stdClass(); +function views_break_phrase($str, $handler = NULL) { + if (!$handler) { + $handler = new stdClass(); } // Set up defaults: - if (!isset($filter->value)) { - $filter->value = array(); + if (!isset($handler->value)) { + $handler->value = array(); } - if (!isset($filter->operator)) { - $filter->operator = 'or'; + if (!isset($handler->operator)) { + $handler->operator = 'or'; } if (empty($str)) { - return $filter; + return $handler; } if (preg_match('/^([0-9]+[+ ])+[0-9]+$/', $str)) { // The '+' character in a query string may be parsed as ' '. - $filter->operator = 'or'; - $filter->value = preg_split('/[+ ]/', $str); + $handler->operator = 'or'; + $handler->value = preg_split('/[+ ]/', $str); } elseif (preg_match('/^([0-9]+,)*[0-9]+$/', $str)) { - $filter->operator = 'and'; - $filter->value = explode(',', $str); + $handler->operator = 'and'; + $handler->value = explode(',', $str); } // Keep an 'error' value if invalid strings were given. - if (!empty($str) && (empty($filter->value) || !is_array($filter->value))) { - $filter->value = array(-1); - return $filter; + if (!empty($str) && (empty($handler->value) || !is_array($handler->value))) { + $handler->value = array(-1); + return $handler; } // Doubly ensure that all values are numeric only. - foreach ($filter->value as $id => $value) { - $filter->value[$id] = intval($value); + foreach ($handler->value as $id => $value) { + $handler->value[$id] = intval($value); } - return $filter; + return $handler; } // -------------------------------------------------------------------------- @@ -1329,52 +1441,3 @@ class views_join { /** * @} */ - -// Declare API compatibility on behalf of core modules: - -/** - * Implements hook_views_api(). - * - * This one is used as the base to reduce errors when updating. - */ -function views_views_api() { - return array( - // in your modules do *not* use views_api_version()!!! - 'api' => views_api_version(), - 'path' => drupal_get_path('module', 'views') . '/modules', - ); -} - -function aggregator_views_api() { return views_views_api(); } - -function book_views_api() { return views_views_api(); } - -function comment_views_api() { return views_views_api(); } - -function locale_views_api() { return views_views_api(); } - -function field_views_api() { return views_views_api(); } - -function filter_views_api() { return views_views_api(); } - -function node_views_api() { return views_views_api(); } - -function poll_views_api() { return views_views_api(); } - -function profile_views_api() { return views_views_api(); } - -function search_views_api() { return views_views_api(); } - -function statistics_views_api() { return views_views_api(); } - -function system_views_api() { return views_views_api(); } - -function taxonomy_views_api() { return views_views_api(); } - -function translation_views_api() { return views_views_api(); } - -function upload_views_api() { return views_views_api(); } - -function user_views_api() { return views_views_api(); } - -function contact_views_api() { return views_views_api(); } diff --git a/sites/all/modules/views/includes/plugins.inc b/sites/all/modules/views/includes/plugins.inc index 6b01af91c760ce937ff0b124bbce894df06892e1..87cb38bf32980eee6c9a6f6a0f317fc90bce2ba5 100644 --- a/sites/all/modules/views/includes/plugins.inc +++ b/sites/all/modules/views/includes/plugins.inc @@ -1,11 +1,13 @@ <?php -// $Id: plugins.inc,v 1.156.4.14 2010/12/04 07:39:35 dereine Exp $ /** * @file plugins.inc * Built in plugins for Views output handling. * */ +// @todo: Remove this once update.php can use the registry +views_include('base'); + /** * Implements hook_views_plugins */ @@ -16,7 +18,7 @@ function views_views_plugins() { 'display' => array( // Default settings for all display plugins. 'default' => array( - 'title' => t('Defaults'), + 'title' => t('Master'), 'help' => t('Default settings for this view.'), 'handler' => 'views_plugin_display_default', 'theme' => 'views_view', @@ -35,6 +37,7 @@ function views_views_plugins() { 'handler' => 'views_plugin_display_page', 'theme' => 'views_view', 'uses hook menu' => TRUE, + 'contextual links locations' => array('page'), 'use ajax' => TRUE, 'use pager' => TRUE, 'accept attachments' => TRUE, @@ -47,6 +50,7 @@ function views_views_plugins() { 'handler' => 'views_plugin_display_block', 'theme' => 'views_view', 'uses hook block' => TRUE, + 'contextual links locations' => array('block'), 'use ajax' => TRUE, 'use pager' => TRUE, 'use more' => TRUE, @@ -61,6 +65,7 @@ function views_views_plugins() { 'theme' => 'views_view', 'use ajax' => TRUE, 'use pager' => FALSE, + 'use more' => TRUE, 'accept attachments' => FALSE, 'help topic' => 'display-attachment', ), @@ -79,7 +84,7 @@ function views_views_plugins() { 'style' => array( // Default settings for all style plugins. 'default' => array( - 'title' => t('Unformatted'), + 'title' => t('Unformatted list'), 'help' => t('Displays rows one after another.'), 'handler' => 'views_plugin_style_default', 'theme' => 'views_view_unformatted', @@ -91,7 +96,7 @@ function views_views_plugins() { 'help topic' => 'style-unformatted', ), 'list' => array( - 'title' => t('HTML List'), + 'title' => t('HTML list'), 'help' => t('Displays rows as an HTML list.'), 'handler' => 'views_plugin_style_list', 'theme' => 'views_view_list', @@ -172,7 +177,7 @@ function views_views_plugins() { 'parent' => '', ), 'fixed' => array( - 'title' => t('Fixed entry'), + 'title' => t('Fixed value'), 'handler' => 'views_plugin_argument_default_fixed', ), 'php' => array( @@ -289,6 +294,7 @@ function views_views_plugins() { ), 'full' => array( 'title' => t('Paged output, full pager'), + 'short title' => t('Full'), 'help' => t('Paged output, full Drupal style'), 'handler' => 'views_plugin_pager_full', 'help topic' => 'pager-full', @@ -296,6 +302,7 @@ function views_views_plugins() { ), 'mini' => array( 'title' => t('Paged output, mini pager'), + 'short title' => t('Mini'), 'help' => t('Use the mini pager output.'), 'handler' => 'views_plugin_pager_mini', 'help topic' => 'pager-mini', @@ -417,6 +424,20 @@ function views_discover_plugins() { * Abstract base class to provide interface common to all plugins. */ class views_plugin extends views_object { + /** + * The top object of a view. + * + * @var view + */ + var $view = NULL; + + /** + * The current used display plugin. + * + * @var views_plugin_display + */ + var $display = NULL; + /** * Init will be called after construct, when the plugin is attached to a * view and a display. @@ -470,5 +491,22 @@ class views_plugin extends views_object { * plugin. */ function validate() { return array(); } -} + /** + * Returns the summary of the settings in the display. + */ + function summary_title() { + return t('Settings'); + } + /** + * Return the human readable name of the display. + * + * This appears on the ui beside each plugin and beside the settings link. + */ + function plugin_title() { + if (isset($this->definition['short title'])) { + return check_plain($this->definition['short title']); + } + return check_plain($this->definition['title']); + } +} diff --git a/sites/all/modules/views/includes/view.inc b/sites/all/modules/views/includes/view.inc index 4e665987e762fa73959700d1027691117244e6ab..80182826578da7fdf27c0b11146da5628cbf9899 100644 --- a/sites/all/modules/views/includes/view.inc +++ b/sites/all/modules/views/includes/view.inc @@ -1,5 +1,4 @@ <?php -// $Id: view.inc,v 1.167.4.40 2011/01/05 21:20:09 dereine Exp $ /** * @file view.inc * Provides the view object type and associated methods. @@ -51,9 +50,30 @@ class view extends views_db_object { // Used to store views that were previously running if we recurse. var $old_view = array(); - // Where the $query object will reside: + // To avoid recursion in views embebed into areas + var $parent_views = array(); + + /** + * Where the $query object will reside: + * + * @var views_plugin_query + */ var $query = NULL; + /** + * The current used display plugin. + * + * @var views_plugin_display + */ + var $display_handler; + + /** + * The current used style plugin. + * + * @var views_plugin_style + */ + var $style_plugin; + /** * Constructor */ @@ -218,6 +238,7 @@ class view extends views_db_object { } $this->display[$id]->handler = views_get_plugin('display', $this->display[$id]->display_plugin); if (!empty($this->display[$id]->handler)) { + $this->display[$id]->handler->localization_keys = array($id); // Initialize the new display handler with data. $this->display[$id]->handler->init($this, $this->display[$id]); // If this is NOT the default display handler, let it know which is @@ -287,7 +308,7 @@ class view extends views_db_object { if (empty($this->display[$display_id])) { $display_id = 'default'; if (empty($this->display[$display_id])) { - debug(t('set_display() called with invalid display id @display.', array('@display' => $display_id))); + vpr('set_display() called with invalid display id @display.', array('@display' => $display_id)); return FALSE; } } @@ -468,6 +489,8 @@ class view extends views_db_object { 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. @@ -476,8 +499,8 @@ class view extends views_db_object { break; } - if ($argument->is_wildcard()) { - $arg_title = $argument->wildcard_title(); + if ($argument->is_exception()) { + $arg_title = $argument->exception_title(); } else { $arg_title = $argument->get_title(); @@ -492,7 +515,12 @@ class view extends views_db_object { if ($this->display_handler->uses_breadcrumb() && $argument->uses_breadcrumb()) { $path = $this->get_url($breadcrumb_args); if (strpos($path, '%') === FALSE) { - $breadcrumb = !empty($argument->options['breadcrumb'])? $argument->options['breadcrumb'] : $title; + if (!empty($argument->options['breadcrumb_enable']) && !empty($argument->options['breadcrumb'])) { + $breadcrumb = $argument->options['breadcrumb']; + } + else { + $breadcrumb = $title; + } $this->build_info['breadcrumb'][$path] = str_replace(array_keys($substitutions), $substitutions, $breadcrumb); } } @@ -501,7 +529,7 @@ class view extends views_db_object { $argument->set_breadcrumb($this->build_info['breadcrumb']); // Test to see if we should use this argument's title - if (!empty($argument->options['title'])) { + if (!empty($argument->options['title_enable']) && !empty($argument->options['title'])) { $title = $argument->options['title']; } @@ -759,6 +787,11 @@ class view extends views_db_object { $cache = $this->display_handler->get_plugin('cache'); } if ($cache && $cache->cache_get('results')) { + if($this->query->pager->use_pager()) { + $this->query->pager->total_items = $this->total_rows; + $this->query->pager->update_page_info(); + } + vpr('Used cached results'); } else { $this->query->execute($this); @@ -1086,6 +1119,24 @@ class view extends views_db_object { return $title; } + /** + * Return the human readable name for a view. + * + * When a certain view doesn't have a human readable name return the machine readable name. + */ + function get_human_name() { + if (!empty($this->human_name)) { + $human_name = $this->human_name; + } + else { + $human_name = $this->get_title(); + if (empty($human_name)) { + $human_name = $this->name; + } + } + return $human_name; + } + /** * Force the view to build a title. */ @@ -1112,6 +1163,17 @@ class view extends views_db_object { } if (!isset($args)) { $args = $this->args; + + // Exclude arguments that were computed, not passed on the URL. + $position = 0; + if (!empty($this->argument)) { + foreach ($this->argument as $argument_id => $argument) { + if (!empty($argument->is_default) && !empty($argument->options['default_argument_skip_url'])) { + unset($args[$position]); + } + $position++; + } + } } // Don't bother working if there's nothing to do: if (empty($path) || (empty($args) && strpos($path, '%') === FALSE)) { @@ -1275,7 +1337,8 @@ class view extends views_db_object { * The name of the view or its internal view id (vid) * @param $reset * If TRUE, reset this entry in the load cache. - * @return A view object or NULL if it was not available. + * @return view + * A view object or NULL if it was not available. */ static function &load($arg, $reset = FALSE) { static $cache = array(); @@ -1286,42 +1349,39 @@ class view extends views_db_object { ->fields('v') ->condition(is_numeric($arg) ? 'vid' : 'name', $arg) ->execute(); - foreach ($result as $data) { - if (empty($data)) { - $cache[$arg] = NULL; - } - else { - $view = new view(); - $view->load_row($data); - $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; - } + 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; } @@ -1340,7 +1400,6 @@ class view extends views_db_object { static function load_views() { $result = db_query("SELECT DISTINCT v.* FROM {views_view} v"); $views = array(); - $vids = array(); // Load all the views. foreach ($result as $data) { @@ -1357,7 +1416,6 @@ class view extends views_db_object { return array(); } - $vids = implode(', ', array_keys($names)); // Now load all the subtables: foreach (view::db_objects() as $key) { $object_name = "views_$key"; @@ -1411,6 +1469,8 @@ class view extends views_db_object { $this->_save_rows($key); } + $this->save_locale_strings(); + cache_clear_all('views_urls', 'cache_views'); cache_clear_all(); // clear the page cache as well. } @@ -1467,7 +1527,7 @@ class view extends views_db_object { foreach ($this->display as $id => $display) { $output .= "\n" . $indent . "/* Display: $display->display_title */\n"; - $output .= $indent . '$handler = $view->new_display(' . views_var_export($display->display_plugin, $indent) . ', ' . views_var_export($display->display_title, $indent) . ', \'' . $id . "');\n"; + $output .= $indent . '$handler = $view->new_display(' . ctools_var_export($display->display_plugin, $indent) . ', ' . ctools_var_export($display->display_title, $indent) . ', \'' . $id . "');\n"; if (empty($display->handler)) { // @todo -- probably need a method of exporting broken displays as // they may simply be broken because a module is not installed. That @@ -1512,6 +1572,9 @@ class view extends views_db_object { * view. This gets ugly fast. * * This will completely wipe a view clean so it can be considered fresh. + * + * @return view + * The cloned view. */ function clone_view() { $clone = version_compare(phpversion(), '5.0') < 0 ? $this : clone($this); @@ -1552,46 +1615,46 @@ class view extends views_db_object { $this->display[$display_id]->handler->destroy(); unset($this->display[$display_id]->handler); } + } - foreach (views_object_types() as $type => $info) { - if (isset($this->$type)) { - $handlers = &$this->$type; - foreach ($handlers as $id => $item) { - $handlers[$id]->destroy(); - } - unset($handlers); + foreach (views_object_types() as $type => $info) { + if (isset($this->$type)) { + $handlers = &$this->$type; + foreach ($handlers as $id => $item) { + $handlers[$id]->destroy(); } + unset($handlers); } + } - if (isset($this->style_plugin)) { - $this->style_plugin->destroy(); - unset($this->style_plugin); - } + if (isset($this->style_plugin)) { + $this->style_plugin->destroy(); + unset($this->style_plugin); + } - // Clear these to make sure the view can be processed/used again. - if (isset($this->display_handler)) { - unset($this->display_handler); - } + // Clear these to make sure the view can be processed/used again. + if (isset($this->display_handler)) { + unset($this->display_handler); + } - if (isset($this->current_display)) { - unset($this->current_display); - } + if (isset($this->current_display)) { + unset($this->current_display); + } - if (isset($this->query)) { - unset($this->query); - } + if (isset($this->query)) { + unset($this->query); + } - $keys = array('current_display', 'display_handler', 'build_info', 'built', 'executed', 'attachment_before', 'attachment_after', 'field', 'argument', 'filter', 'sort', 'relationship', 'header', 'footer', 'empty', 'query', 'result', 'inited', 'style_plugin', 'plugin_name', 'exposed_data', 'exposed_input', 'many_to_one_tables'); - foreach ($keys as $key) { - if (isset($this->$key)) { - unset($this->$key); - } + $keys = array('current_display', 'display_handler', 'build_info', 'built', 'executed', 'attachment_before', 'attachment_after', 'field', 'argument', 'filter', 'sort', 'relationship', 'header', 'footer', 'empty', 'query', 'result', 'inited', 'style_plugin', 'plugin_name', 'exposed_data', 'exposed_input', 'many_to_one_tables'); + foreach ($keys as $key) { + if (isset($this->$key)) { + unset($this->$key); } - $this->built = $this->executed = FALSE; - $this->build_info = array(); - $this->attachment_before = ''; - $this->attachment_after = ''; } + $this->built = $this->executed = FALSE; + $this->build_info = array(); + $this->attachment_before = ''; + $this->attachment_after = ''; } /** @@ -1804,6 +1867,8 @@ class views_db_object { * An optional indentation for prettifying nested code. */ function export_row($identifier = NULL, $indent = '') { + ctools_include('export'); + if (!$identifier) { $identifier = $this->db_table; } @@ -1838,7 +1903,7 @@ class views_db_object { } } - $output .= $indent . '$' . $identifier . '->' . $field . ' = ' . views_var_export($value, $indent) . ";\n"; + $output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ";\n"; } return $output; } @@ -1868,12 +1933,22 @@ class views_db_object { if (empty($id)) { - $title = $plugin['title']; - $id = $this->generate_display_id($type); - $count = str_replace($type . '_', '', $id); + if ($id !== 'default') { + preg_match("/[0-9]/", $id, $count); + $count = $count[0]; + } + else { + $count = ''; + } + if (empty($title)) { - $title = $plugin['title'] . ' ' . $count; + if ($count > 1) { + $title = $plugin['title'] . ' ' . $count; + } + else { + $title = $plugin['title']; + } } } @@ -1911,6 +1986,30 @@ class views_db_object { return $id; } + /** + * Generates a unique ID for an item. + * + * These items are typically fields, filters, sort criteria, or arguments. + * + * @param $requested_id + * The requested ID for the item. + * @param $existing_items + * An array of existing items, keyed by their IDs. + * + * @return + * A unique ID. This will be equal to $requested_id if no item with that ID + * already exists. Otherwise, it will be appended with an integer to make + * it unique, e.g. "{$requested_id}_1", "{$requested_id}_2", etc. + */ + public static function generate_item_id($requested_id, $existing_items) { + $count = 0; + $id = $requested_id; + while (!empty($existing_items[$id])) { + $id = $requested_id . '_' . ++$count; + } + return $id; + } + /** * Create a new display and a display handler for it. * @param $type @@ -1919,7 +2018,7 @@ class views_db_object { * The title of the display; optional, may be filled in from default. * @param $id * The id to use. - * @return + * @return views_plugin_display * A reference to the new handler object. */ function &new_display($type = 'page', $title = NULL, $id = NULL) { @@ -1957,11 +2056,7 @@ class views_db_object { $fields = $this->display[$display_id]->handler->get_option($types[$type]['plural']); if (empty($id)) { - $count = 0; - $id = $field; - while (!empty($fields[$id])) { - $id = $field . '_' . ++$count; - } + $id = $this->generate_item_id($field, $fields); } $new_item = array( @@ -2092,10 +2187,10 @@ function views_object_types() { 'plural' => 'fields', ), 'argument' => array( - 'title' => t('Arguments'), - 'ltitle' => t('arguments'), - 'stitle' => t('Argument'), - 'lstitle' => t('Argument'), + 'title' => t('Contextual filters'), + 'ltitle' => t('contextual filters'), + 'stitle' => t('Contextual filter'), + 'lstitle' => t('contextual filter'), 'plural' => 'arguments', ), 'sort' => array( @@ -2106,12 +2201,11 @@ function views_object_types() { 'plural' => 'sorts', ), 'filter' => array( - 'title' => t('Filters'), - 'ltitle' => t('filters'), - 'stitle' => t('Filter'), - 'lstitle' => t('filter'), + 'title' => t('Filter criteria'), + 'ltitle' => t('filter criteria'), + 'stitle' => t('Filter criterion'), + 'lstitle' => t('filter criterion'), 'plural' => 'filters', - 'options' => 'views_ui_config_filters_form', ), 'relationship' => array( 'title' => t('Relationships'), @@ -2137,10 +2231,10 @@ function views_object_types() { 'type' => 'area', ), 'empty' => array( - 'title' => t('Empty text'), - 'ltitle' => t('empty text'), - 'stitle' => t('Empty text'), - 'lstitle' => t('Empty text'), + 'title' => t('No results behavior'), + 'ltitle' => t('no results behavior'), + 'stitle' => t('No results behavior'), + 'lstitle' => t('No results behavior'), 'plural' => 'empty', 'type' => 'area', ), diff --git a/sites/all/modules/views/js/ajax.js b/sites/all/modules/views/js/ajax.js index 3fa17cd689c93bd3afef145f1a2d21588fe298d0..45d43e02a518452dd339269b6842636bac8e59cf 100644 --- a/sites/all/modules/views/js/ajax.js +++ b/sites/all/modules/views/js/ajax.js @@ -1,4 +1,3 @@ -// $Id: ajax.js,v 1.26.4.12 2010/08/03 05:54:01 dereine Exp $ /** * @file ajax_admin.js * @@ -6,36 +5,48 @@ */ (function ($) { - Drupal.ajax.prototype.commands.viewsSetForm = function(ajax, response, status) { + Drupal.ajax.prototype.commands.viewsSetForm = function (ajax, response, status) { var ajax_title = Drupal.settings.views.ajax.title; - var ajax_area = Drupal.settings.views.ajax.id; + var ajax_body = Drupal.settings.views.ajax.id; + var ajax_popup = Drupal.settings.views.ajax.popup; $(ajax_title).html(response.title); - $(ajax_area).html(response.output); - Drupal.attachBehaviors($(ajax_area).add($(ajax_title)), ajax.settings); + $(ajax_body).html(response.output); + $(ajax_popup).dialog('open'); + Drupal.attachBehaviors($(ajax_popup), ajax.settings); if (response.url) { - var submit = $('input[type=submit]', ajax_area).unbind('click').click(function() { - $('form', ajax_area).append('<input type="hidden" name="' + $(this).attr('name') + '" value="' + $(this).val() + '">'); - $(this).after('<span class="views-throbbing"> </span>'); - }) - $('form', ajax_area).once('views-ajax-submit-processed').each(function() { + // Identify the button that was clicked so that .ajaxSubmit() can use it. + // We need to do this for both .click() and .mousedown() since JavaScript + // code might trigger either behavior. + var $submit_buttons = $('input[type=submit], button', ajax_body); + $submit_buttons.click(function(event) { + this.form.clk = this; + }); + $submit_buttons.mousedown(function(event) { + this.form.clk = this; + }); + + $('form', ajax_body).once('views-ajax-submit-processed').each(function() { var element_settings = { 'url': response.url, 'event': 'submit', 'progress': { 'type': 'throbber' } }; - var form = $(this)[0]; - form.form = form; - Drupal.ajax[$(this).attr('id')] = new Drupal.ajax($(this).attr('id'), form, element_settings); + var $form = $(this); + var id = $form.attr('id'); + Drupal.ajax[id] = new Drupal.ajax(id, this, element_settings); + Drupal.ajax[id].form = $form; }); } + Drupal.viewsUi.resizeModal(); }; - Drupal.ajax.prototype.commands.viewsDismissForm = function(ajax, response, status) { + Drupal.ajax.prototype.commands.viewsDismissForm = function (ajax, response, status) { Drupal.ajax.prototype.commands.viewsSetForm({}, {'title': '', 'output': Drupal.settings.views.ajax.defaultForm}); + $(Drupal.settings.views.ajax.popup).dialog('close'); } - Drupal.ajax.prototype.commands.viewsHilite = function(ajax, response, status) { + Drupal.ajax.prototype.commands.viewsHilite = function (ajax, response, status) { $('.hilited').removeClass('hilited'); $(response.selector).addClass('hilited'); }; - Drupal.ajax.prototype.commands.viewsAddTab = function(ajax, response, status) { + Drupal.ajax.prototype.commands.viewsAddTab = function (ajax, response, status) { var id = '#views-tab-' + response.id; $('#views-tabset').viewsAddTab(id, response.title, 0); $(id).html(response.body).addClass('views-tab'); @@ -43,25 +54,39 @@ // Update the preview widget to preview the new tab. var display_id = id.replace('#views-tab-', ''); $("#preview-display-id").append('<option selected="selected" value="' + display_id + '">' + response.title + '</option>'); - + Drupal.attachBehaviors(id); var instance = $.viewsUi.tabs.instances[$('#views-tabset').get(0).UI_TABS_UUID]; $('#views-tabset').viewsClickTab(instance.$tabs.length); }; - Drupal.ajax.prototype.commands.viewsDisableButtons = function(ajax, response, status) { - $('#views-ui-edit-view-form input').attr('disabled', 'disabled'); - } - - Drupal.ajax.prototype.commands.viewsEnableButtons = function(ajax, response, status) { - $('#views-ui-edit-view-form input').removeAttr('disabled'); - } + Drupal.ajax.prototype.commands.viewsShowButtons = function (ajax, response, status) { + $('div.views-edit-view div.form-actions').removeClass('js-hide'); + $('div.views-edit-view div.view-changed.messages').removeClass('js-hide'); + }; - Drupal.ajax.prototype.commands.viewsTriggerPreview = function(ajax, response, status) { - if ($('#views-live-preview div.form-item-live-preview input').is(':checked')) { - $('#views-live-preview input[type=submit]').trigger('click'); + Drupal.ajax.prototype.commands.viewsTriggerPreview = function (ajax, response, status) { + if ($('input#edit-displays-live-preview').is(':checked')) { + $('#preview-submit').trigger('mousedown'); } - } + }; + + Drupal.ajax.prototype.commands.viewsReplaceTitle = function (ajax, response, status) { + // In case we're in the overlay, get a reference to the underlying window. + var doc = parent.document; + // For the <title> element, make a best-effort attempt to replace the page + // title and leave the site name alone. If the theme doesn't use the site + // name in the <title> element, this will fail. + var oldTitle = doc.title; + // Escape the site name, in case it has special characters in it, so we can + // use it in our regex. + var escapedSiteName = response.siteName.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + var re = new RegExp('.+ (.) ' + escapedSiteName); + doc.title = oldTitle.replace(re, response.title + ' $1 ' + response.siteName); + + $('h1.page-title').text(response.title); + $('h1#overlay-title').text(response.title); + }; /** * Get rid of irritating tabledrag messages @@ -70,11 +95,27 @@ return []; } + /** + * Trigger preview when the "live preview" checkbox is checked. + */ + Drupal.behaviors.livePreview = { + attach: function (context) { + $('input#edit-displays-live-preview', context).once('views-ajax-processed').click(function() { + if ($(this).is(':checked')) { + $('#preview-submit').trigger('mousedown'); + } + else { + $('#views-live-preview').empty(); + } + }); + } + } + /** * Sync preview display. */ Drupal.behaviors.syncPreviewDisplay = { - attach: function(context) { + attach: function (context) { $("#views-tabset a").once('views-ajax-processed').click(function() { var href = $(this).attr('href'); // Cut of #views-tabset. @@ -86,7 +127,22 @@ } Drupal.behaviors.viewsAjax = { - attach: function(context) { + collapseReplaced: false, + attach: function (context, settings) { + if (!settings.views) { + return; + } + // Create a jQuery UI dialog, but leave it closed. + var dialog_area = $(settings.views.ajax.popup, context); + dialog_area.dialog({ + 'autoOpen': false, + 'dialogClass': 'views-ui-dialog', + 'modal': true, + 'position': 'center', + 'resizable': false, + 'width': 750 + }); + var base_element_settings = { 'event': 'click', 'progress': { 'type': 'throbber' } @@ -102,7 +158,7 @@ Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); }); - $('div#views-live-preview form input[type=submit], div#views-live-preview a') + $('div#views-live-preview a') .once('views-ajax-processed').each(function () { var element_settings = base_element_settings; // Set the URL to go to the anchor. @@ -112,17 +168,55 @@ return true; } } - else if ($(this).attr('action')) { - element_settings.url = $(this).attr('action'); - } - else if (this.form && $(this.form).attr('action')) { - element_settings.url = $(this.form).attr('action'); - } + element_settings.wrapper = 'views-live-preview'; + element_settings.method = 'html'; var base = $(this).attr('id'); Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); }); + // Within a live preview, make exposed widget form buttons re-trigger the + // Preview button. + // @todo Revisit this after fixing Views UI to display a Preview outside + // of the main Edit form. + $('div#views-live-preview input[type=submit]') + .once('views-ajax-processed').each(function () { + $(this).click(function(event) { + event.preventDefault(); + $('#preview-submit').mousedown(); + }); + }); + + if (!this.collapseReplaced && Drupal.collapseScrollIntoView) { + this.collapseReplaced = true; + Drupal.collapseScrollIntoView = function (node) { + for (var $parent = $(node); $parent.get(0) != document && $parent.size() != 0; $parent = $parent.parent()) { + if ($parent.css('overflow') == 'scroll' || $parent.css('overflow') == 'auto') { + if (Drupal.viewsUi.resizeModal) { + // If the modal is already at the max height, don't bother with + // this since the only reason to do it is to grow the modal. + if ($('.views-ui-dialog').height() < parseInt($(window).height() * .8)) { + Drupal.viewsUi.resizeModal('', true); + } + } + return; + } + } + + var h = document.documentElement.clientHeight || document.body.clientHeight || 0; + var offset = document.documentElement.scrollTop || document.body.scrollTop || 0; + var posY = $(node).offset().top; + var fudge = 55; + if (posY + node.offsetHeight + fudge > h + offset) { + if (node.offsetHeight > h) { + window.scrollTo(0, posY); + } + else { + window.scrollTo(0, posY + node.offsetHeight - h + fudge); + } + } + }; + } } }; diff --git a/sites/all/modules/views/js/ajax_view.js b/sites/all/modules/views/js/ajax_view.js index 8ed6466a53c50d2954d924b6f9e01322d425a64c..76a58b98f074eb3d3645d22de76ac48c58f0179f 100644 --- a/sites/all/modules/views/js/ajax_view.js +++ b/sites/all/modules/views/js/ajax_view.js @@ -1,5 +1,3 @@ -// $Id: ajax_view.js,v 1.19.4.4 2011/01/03 22:56:39 merlinofchaos Exp $ - /** * @file ajaxView.js * @@ -37,7 +35,7 @@ Drupal.behaviors.ViewsAjaxView.attach = function() { .filter(':not(.views-processed)') .each(function () { var button = $('input[type=submit]', this); - button.form = this; + button = button[0]; var ajax = new Drupal.ajax($(button).attr('id'), button, element_settings); }) diff --git a/sites/all/modules/views/js/base.js b/sites/all/modules/views/js/base.js index c1373a3dd9f9e88d183af615fa8a02576a5b3489..3e40d8943602042b6b8e2c74b64993ed9631bda4 100644 --- a/sites/all/modules/views/js/base.js +++ b/sites/all/modules/views/js/base.js @@ -1,4 +1,3 @@ -// $Id: base.js,v 1.11.4.5 2010/11/20 23:49:29 dereine Exp $ /** * @file base.js * @@ -19,11 +18,11 @@ Drupal.behaviors.viewsTabs = { }); } - $('a.views-remove-link').once('views-processed').click(function() { + $('a.views-remove-link').once('views-processed').click(function(event) { var id = $(this).attr('id').replace('views-remove-link-', ''); $('#views-row-' + id).hide(); $('#views-removed-' + id).attr('checked', true); - return false; + event.preventDefault(); }); /** * Here is to handle display deletion @@ -40,34 +39,6 @@ Drupal.behaviors.viewsTabs = { } }; -/** - * For IE, attach some javascript so that our hovers do what they're supposed - * to do. - */ -Drupal.behaviors.viewsHoverlinks = function() { - if ($.browser.msie) { - // If IE, attach a hover event so we can see our admin links. - $("div.view:not(.views-hover-processed)").addClass('views-hover-processed').hover( - function() { - $('div.views-hide', this).addClass("views-hide-hover"); return true; - }, - function(){ - $('div.views-hide', this).removeClass("views-hide-hover"); return true; - } - ); - $("div.views-admin-links:not(.views-hover-processed)") - .addClass('views-hover-processed') - .hover( - function() { - $(this).addClass("views-admin-links-hover"); return true; - }, - function(){ - $(this).removeClass("views-admin-links-hover"); return true; - } - ); - } -} - /** * Helper function to parse a querystring. */ diff --git a/sites/all/modules/views/js/jquery.ui.dialog.patch.js b/sites/all/modules/views/js/jquery.ui.dialog.patch.js new file mode 100644 index 0000000000000000000000000000000000000000..52b2f12162b6287c5535241058183132c427aa48 --- /dev/null +++ b/sites/all/modules/views/js/jquery.ui.dialog.patch.js @@ -0,0 +1,27 @@ +/** + * This is part of a patch to address a jQueryUI bug. The bug is responsible + * for the inability to scroll a page when a modal dialog is active. If the content + * of the dialog extends beyond the bottom of the viewport, the user is only able + * to scroll with a mousewheel or up/down keyboard keys. + * + * @see http://bugs.jqueryui.com/ticket/4671 + * @see https://bugs.webkit.org/show_bug.cgi?id=19033 + * @see /views_ui.module + * @see /js/jquery.ui.dialog.min.js + * + * This javascript patch overwrites the $.ui.dialog.overlay.events object to remove + * the mousedown, mouseup and click events from the list of events that are bound + * in $.ui.dialog.overlay.create + * + * The original code for this object: + * $.ui.dialog.overlay.events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','), + * function(event) { return event + '.dialog-overlay'; }).join(' '), + * + */ + +(function ($, undefined) { + if ($.ui && $.ui.dialog) { + $.ui.dialog.overlay.events = $.map('focus,keydown,keypress'.split(','), + function(event) { return event + '.dialog-overlay'; }).join(' '); + } +}(jQuery)); diff --git a/sites/all/modules/views/js/views-admin.js b/sites/all/modules/views/js/views-admin.js new file mode 100644 index 0000000000000000000000000000000000000000..8a8aab34317cc379d046b1a3b9930254fbc496ca --- /dev/null +++ b/sites/all/modules/views/js/views-admin.js @@ -0,0 +1,954 @@ +Drupal.viewsUi = {}; + + +Drupal.behaviors.viewsUiAddView = {}; + +/** + * In the add view wizard, use the view name to prepopulate form fields such as + * page title and menu link. + */ +Drupal.behaviors.viewsUiAddView.attach = function (context, settings) { + var $ = jQuery; + var exclude, replace, suffix; + // Set up regular expressions to allow only numbers, letters, and dashes. + exclude = new RegExp('[^a-z0-9\\-]+', 'g'); + replace = '-'; + + // The page title, block title, and menu link fields can all be prepopulated + // with the view name - no regular expression needed. + var $fields = $(context).find('[id^="edit-page-title"], [id^="edit-block-title"], [id^="edit-page-link-properties-title"]'); + if ($fields.length) { + if (!this.fieldsFiller) { + this.fieldsFiller = new Drupal.viewsUi.FormFieldFiller($fields); + } + else { + // After an AJAX response, this.fieldsFiller will still have event + // handlers bound to the old version of the form fields (which don't exist + // anymore). The event handlers need to be unbound and then rebound to the + // new markup. Note that jQuery.live is difficult to make work in this + // case because the IDs of the form fields change on every AJAX response. + this.fieldsFiller.rebind($fields); + } + } + + // Prepopulate the path field with a URLified version of the view name. + var $pathField = $(context).find('[id^="edit-page-path"]'); + if ($pathField.length) { + if (!this.pathFiller) { + this.pathFiller = new Drupal.viewsUi.FormFieldFiller($pathField, exclude, replace); + } + else { + this.pathFiller.rebind($pathField); + } + } + + // Populate the RSS feed field with a URLified version of the view name, and + // an .xml suffix (to make it unique). + var $feedField = $(context).find('[id^="edit-page-feed-properties-path"]'); + if ($feedField.length) { + if (!this.feedFiller) { + suffix = '.xml'; + this.feedFiller = new Drupal.viewsUi.FormFieldFiller($feedField, exclude, replace, suffix); + } + else { + this.feedFiller.rebind($feedField); + } + } +}; + +/** + * Constructor for the Drupal.viewsUi.FormFieldFiller object. + * + * Prepopulates a form field based on the view name. + * + * @param $target + * A jQuery object representing the form field to prepopulate. + * @param exclude + * Optional. A regular expression representing characters to exclude from the + * target field. + * @param replace + * Optional. A string to use as the replacement value for disallowed + * characters. + * @param suffix + * Optional. A suffix to append at the end of the target field content. + */ +Drupal.viewsUi.FormFieldFiller = function ($target, exclude, replace, suffix) { + var $ = jQuery; + this.source = $('#edit-human-name'); + this.target = $target; + this.exclude = exclude || false; + this.replace = replace || ''; + this.suffix = suffix || ''; + + // Create bound versions of this instance's object methods to use as event + // handlers. This will let us easily unbind those specific handlers later on. + // NOTE: jQuery.proxy will not work for this because it assumes we want only + // one bound version of an object method, whereas we need one version per + // object instance. + var self = this; + this.populate = function () {return self._populate.call(self);}; + this.unbind = function () {return self._unbind.call(self);}; + + this.bind(); + // Object constructor; no return value. +}; + +/** + * Bind the form-filling behavior. + */ +Drupal.viewsUi.FormFieldFiller.prototype.bind = function () { + this.unbind(); + // Populate the form field when the source changes. + this.source.bind('keyup.viewsUi change.viewsUi', this.populate); + // Quit populating the field as soon as it gets focus. + this.target.bind('focus.viewsUi', this.unbind); +}; + +/** + * Get the source form field value as altered by the passed-in parameters. + */ +Drupal.viewsUi.FormFieldFiller.prototype.getTransliterated = function () { + var from = this.source.val(); + if (this.exclude) { + from = from.toLowerCase().replace(this.exclude, this.replace); + } + return from + this.suffix; +}; + +/** + * Populate the target form field with the altered source field value. + */ +Drupal.viewsUi.FormFieldFiller.prototype._populate = function () { + var transliterated = this.getTransliterated(); + this.target.val(transliterated); +}; + +/** + * Stop prepopulating the form fields. + */ +Drupal.viewsUi.FormFieldFiller.prototype._unbind = function () { + this.source.unbind('keyup.viewsUi change.viewsUi', this.populate); + this.target.unbind('focus.viewsUi', this.unbind); +}; + +/** + * Bind event handlers to the new form fields, after they're replaced via AJAX. + */ +Drupal.viewsUi.FormFieldFiller.prototype.rebind = function ($fields) { + this.target = $fields; + this.bind(); +} + +Drupal.behaviors.addItemForm = {}; +Drupal.behaviors.addItemForm.attach = function (context) { + var $ = jQuery; + // The add item form may have an id of views-ui-add-item-form--n. + var $form = $(context).find('form[id^="views-ui-add-item-form"]').first(); + // Make sure we don't add more than one event handler to the same form. + $form = $form.once('views-ui-add-item-form'); + if ($form.length) { + new Drupal.viewsUi.addItemForm($form); + } +} + +Drupal.viewsUi.addItemForm = function($form) { + this.$form = $form; + this.$form.find('.views-filterable-options :checkbox').click(jQuery.proxy(this.handleCheck, this)); + // Find the wrapper of the displayed text. + this.$selected_div = this.$form.find('.views-selected-options').parent(); + this.$selected_div.hide(); + this.checkedItems = []; +} + +Drupal.viewsUi.addItemForm.prototype.handleCheck = function (event) { + var $target = jQuery(event.target); + var label = jQuery.trim($target.next().text()); + // Add/remove the checked item to the list. + if ($target.is(':checked')) { + this.$selected_div.show(); + this.checkedItems.push(label); + } + else { + var length = this.checkedItems.length; + var position = jQuery.inArray(label, this.checkedItems); + // Delete the item from the list and take sure that the list doesn't have undefined items left. + for (var i = 0; i < this.checkedItems.length; i++) { + if (i == position) { + this.checkedItems.splice(i, 1); + i--; + break; + } + } + // Hide it again if none item is selected. + if (this.checkedItems.length == 0) { + this.$selected_div.hide(); + } + } + this.refreshCheckedItems(); +} + + +/** + * Refresh the display of the checked items. + */ +Drupal.viewsUi.addItemForm.prototype.refreshCheckedItems = function() { + // Perhaps we should precache the text div, too. + this.$selected_div.find('.views-selected-options').html(this.checkedItems.join(', ')); + Drupal.viewsUi.resizeModal('', true); +} + + +/** + * The input field items that add displays must be rendered as <input> elements. + * The following behavior detaches the <input> elements from the DOM, wraps them + * in an unordered list, then appends them to the list of tabs. + */ +Drupal.behaviors.viewsUiRenderAddViewButton = {}; + +Drupal.behaviors.viewsUiRenderAddViewButton.attach = function (context, settings) { + var $ = jQuery; + // Build the add display menu and pull the display input buttons into it. + var $menu = $('#views-ui-edit-form .secondary', context).once('views-ui-render-add-view-button-processed'); + if (!$menu.length) { + return; + } + var $addDisplayDropdown = $('<li class="add"><a href="#"><span class="icon add"></span>Add</a><ul class="action-list" style="display:none;"></ul></li>'); + var $displayButtons = $menu.nextAll('input.add-display').detach(); + $displayButtons.appendTo($addDisplayDropdown.find('.action-list')).wrap('<li>') + .parent().first().addClass('first').end().last().addClass('last'); + // Remove the 'Add ' prefix from the button labels since they're being palced + // in an 'Add' dropdown. + // @todo This assumes English, but so does $addDisplayDropdown above. Add + // support for translation. + $displayButtons.each(function () { + var label = $(this).val(); + if (label.substr(0, 4) == 'Add ') { + $(this).val(label.substr(4)); + } + }); + $addDisplayDropdown.appendTo($menu); + + // Add the click handler for the add display button + $('li.add > a', $menu).bind('click', function (event) { + event.preventDefault(); + var $trigger = $(this); + Drupal.behaviors.viewsUiRenderAddViewButton.toggleMenu($trigger); + }); + // Add a mouseleave handler to close the dropdown when the user mouses + // away from the item. We use mouseleave instead of mouseout because + // the user is going to trigger mouseout when she moves from the trigger + // link to the sub menu items. + // We use the live binder because the open class on this item will be + // toggled on and off and we want the handler to take effect in the cases + // that the class is present, but not when it isn't. + $('li.add', $menu).live('mouseleave', function (event) { + var $this = $(this); + var $trigger = $this.children('a[href="#"]'); + if ($this.children('.action-list').is(':visible')) { + Drupal.behaviors.viewsUiRenderAddViewButton.toggleMenu($trigger); + } + }); +}; + +/** + * @note [@jessebeach] I feel like the following should be a more generic function and + * not written specifically for this UI, but I'm not sure where to put it. + */ +Drupal.behaviors.viewsUiRenderAddViewButton.toggleMenu = function ($trigger) { + $trigger.parent().toggleClass('open'); + $trigger.next().slideToggle('fast'); +} + + +Drupal.behaviors.viewsUiSearchOptions = {}; + +Drupal.behaviors.viewsUiSearchOptions.attach = function (context) { + var $ = jQuery; + // The add item form may have an id of views-ui-add-item-form--n. + var $form = $(context).find('form[id^="views-ui-add-item-form"]').first(); + // Make sure we don't add more than one event handler to the same form. + $form = $form.once('views-ui-filter-options'); + if ($form.length) { + new Drupal.viewsUi.OptionsSearch($form); + } +}; + +/** + * Constructor for the viewsUi.OptionsSearch object. + * + * The OptionsSearch object filters the available options on a form according + * to the user's search term. Typing in "taxonomy" will show only those options + * containing "taxonomy" in their label. + */ +Drupal.viewsUi.OptionsSearch = function ($form) { + this.$form = $form; + // Add a keyup handler to the search box. + this.$searchBox = this.$form.find('#edit-options-search'); + this.$searchBox.keyup(jQuery.proxy(this.handleKeyup, this)); + // Get a list of option labels and their corresponding divs and maintain it + // in memory, so we have as little overhead as possible at keyup time. + this.options = this.getOptions(this.$form.find('.filterable-option')); + // Restripe on initial loading. + this.handleKeyup(); + // Trap the ENTER key in the search box so that it doesn't submit the form. + this.$searchBox.keypress(function(event) { + if (event.which == 13) { + event.preventDefault(); + } + }); +}; + +/** + * Assemble a list of all the filterable options on the form. + * + * @param $allOptions + * A jQuery object representing the rows of filterable options to be + * shown and hidden depending on the user's search terms. + */ +Drupal.viewsUi.OptionsSearch.prototype.getOptions = function ($allOptions) { + var $ = jQuery; + var i, $label, $option; + var options = []; + var length = $allOptions.length; + for (i = 0; i < length; i++) { + $option = $($allOptions[i]); + $label = $option.find('label'); + options[i] = { + // Search on the lowercase version of the label text. + 'labelText': $label.text().toLowerCase(), + // Maintain a reference to the jQuery object for each row, so we don't + // have to create a new object inside the performance-sensitive keyup + // handler. + '$div': $option + } + } + return options; +}; + +/** + * Keyup handler for the search box that hides or shows the relevant options. + */ +Drupal.viewsUi.OptionsSearch.prototype.handleKeyup = function (event) { + var found, i, j, option, search, words, wordsLength, zebraClass, zebraCounter; + + // Determine the user's search query. The label text has been converted to + // lowercase. + search = this.$searchBox.val().toLowerCase(); + words = search.split(' '); + wordsLength = words.length; + + // Start the counter for restriping rows. + zebraCounter = 0; + + // Search through the labels in the form for matching text. + var length = this.options.length; + for (i = 0; i < length; i++) { + // Use a local variable for the option being searched, for performance. + option = this.options[i]; + found = true; + // Each word in the search string has to match the label in order for the + // label to be shown. + for (j = 0; j < wordsLength; j++) { + if (option.labelText.indexOf(words[j]) === -1) { + found = false; + } + } + if (found) { + // Show the checkbox row, and restripe it. + zebraClass = (zebraCounter % 2) ? 'odd' : 'even'; + option.$div.show(); + option.$div.removeClass('even odd'); + option.$div.addClass(zebraClass); + zebraCounter++; + } + else { + // The search string wasn't found; hide this item. + option.$div.hide(); + } + } +}; + + +Drupal.behaviors.viewsUiPreview = {}; +Drupal.behaviors.viewsUiPreview.attach = function (context, settings) { + var $ = jQuery; + + // Only act on the edit view form. + var contextualFiltersBucket = $('.views-display-column .views-ui-display-tab-bucket.contextual-filters', context); + if (contextualFiltersBucket.length == 0) { + return; + } + + // If the display has no contextual filters, hide the form where you enter + // the contextual filters for the live preview. If it has contextual filters, + // show the form. + var contextualFilters = $('.views-display-setting a', contextualFiltersBucket); + if (contextualFilters.length) { + $('.form-item-displays-settings-settings-content-preview-controls-view-args').show(); + } + else { + $('.form-item-displays-settings-settings-content-preview-controls-view-args').hide(); + } +}; + + +Drupal.behaviors.viewsUiRearrangeFilter = {}; +Drupal.behaviors.viewsUiRearrangeFilter.attach = function (context, settings) { + var $ = jQuery; + // Only act on the rearrange filter form. + if (typeof Drupal.tableDrag == 'undefined' || typeof Drupal.tableDrag['views-rearrange-filters'] == 'undefined') { + return; + } + + var table = $('#views-rearrange-filters', context).once('views-rearrange-filters'); + var operator = $('.form-item-filter-groups-operator', context).once('views-rearrange-filters'); + if (table.length) { + new Drupal.viewsUi.rearrangeFilterHandler(table, operator); + } +}; + +/** + * Improve the UI of the rearrange filters dialog box. + */ +Drupal.viewsUi.rearrangeFilterHandler = function (table, operator) { + var $ = jQuery; + // Keep a reference to the <table> being altered and to the div containing + // the filter groups operator dropdown (if it exists). + this.table = table; + this.operator = operator; + this.hasGroupOperator = this.operator.length > 0; + + // Keep a reference to all draggable rows within the table. + this.draggableRows = $('.draggable', table); + + // Keep a reference to the buttons for adding and removing filter groups. + this.addGroupButton = $('input#views-add-group'); + this.removeGroupButtons = $('input.views-remove-group', table); + + // Add links that duplicate the functionality of the (hidden) add and remove + // buttons. + this.insertAddRemoveFilterGroupLinks(); + + // When there is a filter groups operator dropdown on the page, create + // duplicates of the dropdown between each pair of filter groups. + if (this.hasGroupOperator) { + this.dropdowns = this.duplicateGroupsOperator(); + this.syncGroupsOperators(); + } + + // Add methods to the tableDrag instance to account for operator cells (which + // span multiple rows), the operator labels next to each filter (e.g., "And" + // or "Or"), the filter groups, and other special aspects of this tableDrag + // instance. + this.modifyTableDrag(); + + // Initialize the operator labels (e.g., "And" or "Or") that are displayed + // next to the filters in each group, and bind a handler so that they change + // based on the values of the operator dropdown within that group. + this.redrawOperatorLabels(); + $('.views-group-title select', table) + .once('views-rearrange-filter-handler') + .bind('change.views-rearrange-filter-handler', $.proxy(this, 'redrawOperatorLabels')); + + // Bind handlers so that when a "Remove" link is clicked, we: + // - Update the rowspans of cells containing an operator dropdown (since they + // need to change to reflect the number of rows in each group). + // - Redraw the operator labels next to the filters in the group (since the + // filter that is currently displayed last in each group is not supposed to + // have a label display next to it). + $('a.views-groups-remove-link', this.table) + .once('views-rearrange-filter-handler') + .bind('click.views-rearrange-filter-handler', $.proxy(this, 'updateRowspans')) + .bind('click.views-rearrange-filter-handler', $.proxy(this, 'redrawOperatorLabels')); +}; + +/** + * Insert links that allow filter groups to be added and removed. + */ +Drupal.viewsUi.rearrangeFilterHandler.prototype.insertAddRemoveFilterGroupLinks = function () { + var $ = jQuery; + + // Insert a link for adding a new group at the top of the page, and make it + // match the action links styling used in a typical page.tpl.php. Note that + // Drupal does not provide a theme function for this markup, so this is the + // best we can do. + $('<ul class="action-links"><li><a id="views-add-group-link" href="#">' + this.addGroupButton.val() + '</a></li></ul>') + .prependTo(this.table.parent()) + // When the link is clicked, dynamically click the hidden form button for + // adding a new filter group. + .once('views-rearrange-filter-handler') + .bind('click.views-rearrange-filter-handler', $.proxy(this, 'clickAddGroupButton')); + + // Find each (visually hidden) button for removing a filter group and insert + // a link next to it. + var length = this.removeGroupButtons.length; + for (i = 0; i < length; i++) { + var $removeGroupButton = $(this.removeGroupButtons[i]); + var buttonId = $removeGroupButton.attr('id'); + $('<a href="#" class="views-remove-group-link">' + Drupal.t('Remove group') + '</a>') + .insertBefore($removeGroupButton) + // When the link is clicked, dynamically click the corresponding form + // button. + .once('views-rearrange-filter-handler') + .bind('click.views-rearrange-filter-handler', {buttonId: buttonId}, $.proxy(this, 'clickRemoveGroupButton')); + } +}; + +/** + * Dynamically click the button that adds a new filter group. + */ +Drupal.viewsUi.rearrangeFilterHandler.prototype.clickAddGroupButton = function () { + // Due to conflicts between Drupal core's AJAX system and the Views AJAX + // system, the only way to get this to work seems to be to trigger both the + // .mousedown() and .submit() events. + this.addGroupButton.mousedown(); + this.addGroupButton.submit(); + return false; +}; + +/** + * Dynamically click a button for removing a filter group. + * + * @param event + * Event being triggered, with event.data.buttonId set to the ID of the + * form button that should be clicked. + */ +Drupal.viewsUi.rearrangeFilterHandler.prototype.clickRemoveGroupButton = function (event) { + // For some reason, here we only need to trigger .submit(), unlike for + // Drupal.viewsUi.rearrangeFilterHandler.prototype.clickAddGroupButton() + // where we had to trigger .mousedown() also. + jQuery('input#' + event.data.buttonId, this.table).submit(); + return false; +}; + +/** + * Move the groups operator so that it's between the first two groups, and + * duplicate it between any subsequent groups. + */ +Drupal.viewsUi.rearrangeFilterHandler.prototype.duplicateGroupsOperator = function () { + var $ = jQuery; + var dropdowns, newRow; + + var titleRows = $('tr.views-group-title'), titleRow; + + // Get rid of the explanatory text around the operator; its placement is + // explanatory enough. + this.operator.find('label').add('div.description').addClass('element-invisible'); + this.operator.find('select').addClass('form-select'); + + // Keep a list of the operator dropdowns, so we can sync their behavior later. + dropdowns = this.operator; + + // Move the operator to a new row just above the second group. + titleRow = $('tr#views-group-title-1'); + newRow = $('<tr class="filter-group-operator-row"><td colspan="5"></td></tr>'); + newRow.find('td').append(this.operator); + newRow.insertBefore(titleRow); + var i, length = titleRows.length; + // Starting with the third group, copy the operator to a new row above the + // group title. + for (i = 2; i < length; i++) { + titleRow = $(titleRows[i]); + // Make a copy of the operator dropdown and put it in a new table row. + var fakeOperator = this.operator.clone(); + fakeOperator.attr('id', ''); + newRow = $('<tr class="filter-group-operator-row"><td colspan="5"></td></tr>'); + newRow.find('td').append(fakeOperator); + newRow.insertBefore(titleRow); + dropdowns = dropdowns.add(fakeOperator); + } + + return dropdowns; +}; + +/** + * Make the duplicated groups operators change in sync with each other. + */ +Drupal.viewsUi.rearrangeFilterHandler.prototype.syncGroupsOperators = function () { + if (this.dropdowns.length < 2) { + // We only have one dropdown (or none at all), so there's nothing to sync. + return; + } + + this.dropdowns.change(jQuery.proxy(this, 'operatorChangeHandler')); +}; + +/** + * Click handler for the operators that appear between filter groups. + * + * Forces all operator dropdowns to have the same value. + */ +Drupal.viewsUi.rearrangeFilterHandler.prototype.operatorChangeHandler = function (event) { + var $ = jQuery; + var $target = $(event.target); + var operators = this.dropdowns.find('select').not($target); + + // Change the other operators to match this new value. + operators.val($target.val()); +}; + +Drupal.viewsUi.rearrangeFilterHandler.prototype.modifyTableDrag = function () { + var tableDrag = Drupal.tableDrag['views-rearrange-filters']; + var filterHandler = this; + + /** + * Override the row.onSwap method from tabledrag.js. + * + * When a row is dragged to another place in the table, several things need + * to occur. + * - The row needs to be moved so that it's within one of the filter groups. + * - The operator cells that span multiple rows need their rowspan attributes + * updated to reflect the number of rows in each group. + * - The operator labels that are displayed next to each filter need to be + * redrawn, to account for the row's new location. + */ + tableDrag.row.prototype.onSwap = function () { + if (filterHandler.hasGroupOperator) { + // Make sure the row that just got moved (this.group) is inside one of + // the filter groups (i.e. below an empty marker row or a draggable). If + // it isn't, move it down one. + var thisRow = jQuery(this.group); + var previousRow = thisRow.prev('tr'); + if (previousRow.length && !previousRow.hasClass('group-message') && !previousRow.hasClass('draggable')) { + // Move the dragged row down one. + var next = thisRow.next(); + if (next.is('tr')) { + this.swap('after', next); + } + } + filterHandler.updateRowspans(); + } + // Redraw the operator labels that are displayed next to each filter, to + // account for the row's new location. + filterHandler.redrawOperatorLabels(); + }; + + /** + * Override the onDrop method from tabledrag.js. + */ + tableDrag.onDrop = function () { + var $ = jQuery; + + // If the tabledrag change marker (i.e., the "*") has been inserted inside + // a row after the operator label (i.e., "And" or "Or") rearrange the items + // so the operator label continues to appear last. + var changeMarker = $(this.oldRowElement).find('.tabledrag-changed'); + if (changeMarker.length) { + // Search for occurrences of the operator label before the change marker, + // and reverse them. + var operatorLabel = changeMarker.prevAll('.views-operator-label'); + if (operatorLabel.length) { + operatorLabel.insertAfter(changeMarker); + } + } + + // Make sure the "group" dropdown is properly updated when rows are dragged + // into an empty filter group. This is borrowed heavily from the block.js + // implementation of tableDrag.onDrop(). + var groupRow = $(this.rowObject.element).prevAll('tr.group-message').get(0); + var groupName = groupRow.className.replace(/([^ ]+[ ]+)*group-([^ ]+)-message([ ]+[^ ]+)*/, '$2'); + var groupField = $('select.views-group-select', this.rowObject.element); + if ($(this.rowObject.element).prev('tr').is('.group-message') && !groupField.is('.views-group-select-' + groupName)) { + var oldGroupName = groupField.attr('class').replace(/([^ ]+[ ]+)*views-group-select-([^ ]+)([ ]+[^ ]+)*/, '$2'); + groupField.removeClass('views-group-select-' + oldGroupName).addClass('views-group-select-' + groupName); + groupField.val(groupName); + } + }; +}; + + +/** + * Redraw the operator labels that are displayed next to each filter. + */ +Drupal.viewsUi.rearrangeFilterHandler.prototype.redrawOperatorLabels = function () { + var $ = jQuery; + for (i = 0; i < this.draggableRows.length; i++) { + // Within the row, the operator labels are displayed inside the first table + // cell (next to the filter name). + var $draggableRow = $(this.draggableRows[i]); + var $firstCell = $('td:first', $draggableRow); + if ($firstCell.length) { + // The value of the operator label ("And" or "Or") is taken from the + // first operator dropdown we encounter, going backwards from the current + // row. This dropdown is the one associated with the current row's filter + // group. + var operatorValue = $draggableRow.prevAll('.views-group-title').find('option:selected').html(); + var operatorLabel = '<span class="views-operator-label">' + operatorValue + '</span>'; + // If the next visible row after this one is a draggable filter row, + // display the operator label next to the current row. (Checking for + // visibility is necessary here since the "Remove" links hide the removed + // row but don't actually remove it from the document). + var $nextRow = $draggableRow.nextAll(':visible').eq(0); + var $existingOperatorLabel = $firstCell.find('.views-operator-label'); + if ($nextRow.hasClass('draggable')) { + // If an operator label was already there, replace it with the new one. + if ($existingOperatorLabel.length) { + $existingOperatorLabel.replaceWith(operatorLabel); + } + // Otherwise, append the operator label to the end of the table cell. + else { + $firstCell.append(operatorLabel); + } + } + // If the next row doesn't contain a filter, then this is the last row + // in the group. We don't want to display the operator there (since + // operators should only display between two related filters, e.g. + // "filter1 AND filter2 AND filter3"). So we remove any existing label + // that this row has. + else { + $existingOperatorLabel.remove(); + } + } + } +}; + +/** + * Update the rowspan attribute of each cell containing an operator dropdown. + */ +Drupal.viewsUi.rearrangeFilterHandler.prototype.updateRowspans = function () { + var $ = jQuery; + var i, $row, $currentEmptyRow, draggableCount, $operatorCell; + var rows = $(this.table).find('tr'); + var length = rows.length; + for (i = 0; i < length; i++) { + $row = $(rows[i]); + if ($row.hasClass('views-group-title')) { + // This row is a title row. + // Keep a reference to the cell containing the dropdown operator. + $operatorCell = $($row.find('td.group-operator')); + // Assume this filter group is empty, until we find otherwise. + draggableCount = 0; + $currentEmptyRow = $row.next('tr'); + $currentEmptyRow.removeClass('group-populated').addClass('group-empty'); + // The cell with the dropdown operator should span the title row and + // the "this group is empty" row. + $operatorCell.attr('rowspan', 2); + } + else if (($row).hasClass('draggable') && $row.is(':visible')) { + // We've found a visible filter row, so we now know the group isn't empty. + draggableCount++; + $currentEmptyRow.removeClass('group-empty').addClass('group-populated'); + // The operator cell should span all draggable rows, plus the title. + $operatorCell.attr('rowspan', draggableCount + 1); + } + } +}; + +Drupal.behaviors.viewsFilterConfigSelectAll = {}; + +/** + * Add a select all checkbox, which checks each checkbox at once. + */ +Drupal.behaviors.viewsFilterConfigSelectAll.attach = function(context) { + var $ = jQuery; + // Show the select all checkbox. + $('#views-ui-config-item-form div.form-item-options-value-all', context).once(function() { + $(this).show(); + }) + .find('input[type=checkbox]') + .click(function() { + var checked = $(this).is(':checked'); + // Update all checkbox beside the select all checkbox. + $(this).parents('.form-checkboxes').find('input[type=checkbox]').each(function() { + $(this).attr('checked', checked); + }); + }); +}; + +/** + * Ensure the desired default button is used when a form is implicitly submitted via an ENTER press on textfields, radios, and checkboxes. + * + * @see http://www.w3.org/TR/html5/association-of-controls-and-forms.html#implicit-submission + */ +Drupal.behaviors.viewsImplicitFormSubmission = {}; +Drupal.behaviors.viewsImplicitFormSubmission.attach = function (context, settings) { + var $ = jQuery; + $(':text, :password, :radio, :checkbox', context).once('viewsImplicitFormSubmission', function() { + $(this).keypress(function(event) { + if (event.which == 13) { + var formId = this.form.id; + if (formId && settings.viewsImplicitFormSubmission && settings.viewsImplicitFormSubmission[formId] && settings.viewsImplicitFormSubmission[formId].defaultButton) { + event.preventDefault(); + var buttonId = settings.viewsImplicitFormSubmission[formId].defaultButton; + var $button = $('#' + buttonId, this.form); + if ($button.length == 1 && $button.is(':enabled')) { + if (Drupal.ajax && Drupal.ajax[buttonId]) { + $button.trigger(Drupal.ajax[buttonId].element_settings.event); + } + else { + $button.click(); + } + } + } + } + }); + }); +}; + +/** + * Remove icon class from elements that are themed as buttons or dropbuttons. + */ +Drupal.behaviors.viewsRemoveIconClass = {}; +Drupal.behaviors.viewsRemoveIconClass.attach = function (context, settings) { + jQuery('.ctools-button', context).once('RemoveIconClass', function () { + var $ = jQuery; + var $this = $(this); + $('.icon', $this).removeClass('icon'); + $('.horizontal', $this).removeClass('horizontal'); + }); +} + +/** + * Change "Expose filter" buttons into checkboxes. + */ +Drupal.behaviors.viewsUiCheckboxify = {}; +Drupal.behaviors.viewsUiCheckboxify.attach = function (context, settings) { + var $ = jQuery; + var $buttons = $('#edit-options-expose-button-button').once('views-ui-checkboxify'); + var length = $buttons.length; + var i; + for (i = 0; i < length; i++) { + new Drupal.viewsUi.Checkboxifier($buttons[i]); + } +}; + +/** + * Attaches an expose filter button to a checkbox that triggers its click event. + * + * @param button + * The DOM object representing the button to be checkboxified. + */ +Drupal.viewsUi.Checkboxifier = function (button) { + var $ = jQuery; + this.$button = $(button); + this.$parent = this.$button.parent('div.views-expose'); + this.$checkbox = this.$parent.find('input:checkbox'); + // Hide the button and its description. + this.$button.hide(); + this.$parent.find('.exposed-description').hide(); + + this.$checkbox.click($.proxy(this, 'clickHandler')); +}; + +/** + * When the checkbox is checked or unchecked, simulate a button press. + */ +Drupal.viewsUi.Checkboxifier.prototype.clickHandler = function (e) { + this.$button.mousedown(); + this.$button.submit(); +}; + +/** + * Add extra dependency behavior, in addition to CTools visibility management. + * + * @todo Abstract this and perhaps add to CTools. + */ +Drupal.behaviors.viewsUiDependent = {}; +Drupal.behaviors.viewsUiDependent.attach = function (context, settings) { + var $ = jQuery; + $('#views-ui-config-item-form #edit-options-custom-label').once('views-ui-dependent', function () { + var $checkbox = $(this); + $checkbox.click(function (event) { + if (!$checkbox.is(':checked')) { + $('#views-ui-config-item-form #edit-options-label').val(''); + $('#views-ui-config-item-form #edit-options-element-label-colon').attr('checked', false); + } + }); + }); +}; + +Drupal.viewsUi.resizeModal = function (e, no_shrink) { + var $ = jQuery; + var $modal = $('.views-ui-dialog'); + var $scroll = $('.scroll', $modal); + if ($modal.size() == 0 || $modal.css('display') == 'none') { + return; + } + + var maxWidth = parseInt($(window).width() * .85); // 70% of window + var minWidth = parseInt($(window).width() * .6); // 70% of window + + // Set the modal to the minwidth so that our width calculation of + // children works. + $modal.css('width', minWidth); + var width = minWidth; + + // Don't let the window get more than 80% of the display high. + var maxHeight = parseInt($(window).height() * .8); + var minHeight = 200; + if (no_shrink) { + minHeight = $modal.height(); + } + + if (minHeight > maxHeight) { + minHeight = maxHeight; + } + + var height = 0; + + // Calculate the height of the 'scroll' region. + var scrollHeight = 0; + + scrollHeight += parseInt($scroll.css('padding-top')); + scrollHeight += parseInt($scroll.css('padding-bottom')); + + $scroll.children().each(function() { + var w = $(this).innerWidth(); + if (w > width) { + width = w; + } + scrollHeight += $(this).outerHeight(true); + }); + + // Now, calculate what the difference between the scroll and the modal + // will be. + + var difference = 0; + difference += parseInt($scroll.css('padding-top')); + difference += parseInt($scroll.css('padding-bottom')); + difference += $('.views-override').outerHeight(true); + difference += $('.views-messages').outerHeight(true); + difference += $('#views-ajax-title').outerHeight(true); + difference += $('.views-add-form-selected').outerHeight(true); + difference += $('.form-buttons', $modal).outerHeight(true); + + height = scrollHeight + difference; + + if (height > maxHeight) { + height = maxHeight; + scrollHeight = maxHeight - difference; + } + else if (height < minHeight) { + height = minHeight; + scrollHeight = minHeight - difference; + } + + if (width > maxWidth) { + width = maxWidth; + } + + // Get where we should move content to + var top = ($(window).height() / 2) - (height / 2); + var left = ($(window).width() / 2) - (width / 2); + + $modal.css({ + 'top': top + 'px', + 'left': left + 'px', + 'width': width + 'px', + 'height': height + 'px' + }); + + // Ensure inner popup height matches. + $(Drupal.settings.views.ajax.popup).css('height', height + 'px'); + + $scroll.css({ + 'height': scrollHeight + 'px', + 'max-height': scrollHeight + 'px' + }); + +}; + +jQuery(function() { + jQuery(window).bind('resize', Drupal.viewsUi.resizeModal); + jQuery(window).bind('scroll', Drupal.viewsUi.resizeModal); +}); diff --git a/sites/all/modules/views/js/views-contextual.js b/sites/all/modules/views/js/views-contextual.js new file mode 100644 index 0000000000000000000000000000000000000000..2e9dcf7a61191c5f477050f82273c20c4ca07843 --- /dev/null +++ b/sites/all/modules/views/js/views-contextual.js @@ -0,0 +1,16 @@ +/** + * @file + * Javascript related to contextual links. + */ +(function ($) { + +Drupal.behaviors.viewsContextualLinks = { + attach: function (context) { + // If there are views-related contextual links attached to the main page + // content, find the smallest region that encloses both the links and the + // view, and display it as a contextual links region. + $('.views-contextual-links-page', context).closest(':has(.view)').addClass('contextual-links-region'); + } +}; + +})(jQuery); diff --git a/sites/all/modules/views/js/views-list.js b/sites/all/modules/views/js/views-list.js new file mode 100644 index 0000000000000000000000000000000000000000..9c6c5f06e6e0e5745ff6d8afba87320511f41a9f --- /dev/null +++ b/sites/all/modules/views/js/views-list.js @@ -0,0 +1,21 @@ +/** + * @file + * Javascript related to the main view list. + */ +(function ($) { + +Drupal.behaviors.viewsUIList = { + attach: function (context) { + $('#ctools-export-ui-list-items thead a').once('views-ajax-processed').each(function() { + $(this).click(function() { + var query = $.deparam.querystring(this.href); + $('#ctools-export-ui-list-form select[name=order]').val(query['order']); + $('#ctools-export-ui-list-form select[name=sort]').val(query['sort']); + $('#ctools-export-ui-list-form input.ctools-auto-submit-click').trigger('click'); + return false; + }); + }); + } +}; + +})(jQuery); diff --git a/sites/all/modules/views/modules/aggregator.views.inc b/sites/all/modules/views/modules/aggregator.views.inc index 014b426a23f837e8ae2b80f5892cd3dc1c011028..d4f31146344eabef1f3b823fd7c16a322f4cac8a 100644 --- a/sites/all/modules/views/modules/aggregator.views.inc +++ b/sites/all/modules/views/modules/aggregator.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: aggregator.views.inc,v 1.3.4.7 2010/11/16 00:01:25 merlinofchaos Exp $ /** * @file * Provide views data and handlers for aggregator.module 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 084f954ff5e9a3fb88aef52e783392a266af3ee6..7d64f3ef2685874471735af2460e0071ba2c7efc 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_aggregator_category_cid.inc,v 1.1.6.2 2009/11/13 12:36:05 dereine Exp $ /** * Argument handler to accept an aggregator category id. 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 5da5b13c26af30aa6b41c901bdcedeb7296c55e8..6a3a9d8187e35914d638eec948b596309de7e1d6 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_aggregator_fid.inc,v 1.1.6.2 2010/10/23 06:30:12 dereine Exp $ /** * Argument handler to accept an aggregator feed id. 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 cf3e5a8176d1a30b0f581160ce219f2a11241c64..575e74307d41b0b096641facffbc1385ae9b7d61 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_aggregator_iid.inc,v 1.1.6.2 2010/10/16 08:19:05 dereine Exp $ /** * Argument handler to accept an aggregator item id. 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 c7a72e955b48c821512b1d547c1e944eb0f6b04b..b0ca9c5d6fa50afca89421fcc8c3ceb537c86533 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_aggregator_category.inc,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * Field handler to provide simple renderer that allows linking to aggregator @@ -24,13 +23,13 @@ class views_handler_field_aggregator_category extends views_handler_field { * Provide link to category option */ function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['link_to_category'] = array( '#title' => t('Link this field to its aggregator category page'), '#description' => t('This will override any other link you have set.'), '#type' => 'checkbox', '#default_value' => !empty($this->options['link_to_category']), ); + parent::options_form($form, $form_state); } /** @@ -39,8 +38,8 @@ class views_handler_field_aggregator_category extends views_handler_field { * Data should be made XSS safe prior to calling this function. */ function render_link($data, $values) { - if (!empty($this->options['link_to_category']) && !empty($values->{$this->aliases['cid']}) && $data !== NULL && $data !== '') { - $cid = $values->{$this->aliases['cid']}; + $cid = $this->get_value($values, 'cid'); + if (!empty($this->options['link_to_category']) && !empty($cid) && $data !== NULL && $data !== '') { $this->options['alter']['make_link'] = TRUE; $this->options['alter']['path'] = "aggregator/category/$cid"; } @@ -48,6 +47,7 @@ class views_handler_field_aggregator_category extends views_handler_field { } function render($values) { - return $this->render_link(check_plain($values->{$this->field_alias}), $values); + $value = $this->get_value($values); + return $this->render_link($this->sanitize_value($value), $values); } } 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 1399c52ba2ec040c55bc8852a3d019a2a61d027f..26235d41ad241a6a1de717d5f090d8998abd8bff 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_aggregator_title_link.inc,v 1.1.6.1 2010/11/18 07:29:03 dereine Exp $ /** * Field handler that turns an item's title into a clickable link to the original @@ -23,21 +22,21 @@ class views_handler_field_aggregator_title_link extends views_handler_field { * Provide link to the page being visited. */ function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['display_as_link'] = array( '#title' => t('Display as link'), '#type' => 'checkbox', '#default_value' => !empty($this->options['display_as_link']), ); + parent::options_form($form, $form_state); } function render($values) { - return $this->render_link(check_plain($values->{$this->field_alias}), $values); + $value = $this->get_value($values); + return $this->render_link($this->sanitize_value($value), $values); } function render_link($data, $values) { - $value = $values->{$this->field_alias}; - $link = $values->{$this->aliases['link']}; + $link = $this->get_value($values, 'link'); if (!empty($this->options['display_as_link'])) { $this->options['alter']['make_link'] = TRUE; $this->options['alter']['path'] = $link; 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 b7cb9bf4141d50ef229415d9a59db69c3b83a1e5..3fa87c48fee3a50bf0cb6adf9c3ca45304345ebf 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,5 +1,4 @@ <?php -// $Id: views_handler_field_aggregator_xss.inc,v 1.1.2.2 2010/11/16 00:01:25 merlinofchaos Exp $ /** * @file * Filters htmls tags from item. @@ -7,8 +6,7 @@ class views_handler_field_aggregator_xss extends views_handler_field { function render($values) { - $value = $values->{$this->field_alias}; + $value = $this->get_value($values); return aggregator_filter_xss($value); } - -} \ No newline at end of file +} 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 3c995b5a03a94a9b1b80bb252530b81863d5b19c..2f797a80bac5b786f64f3296fb6d9bd9f4511b52 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,4 @@ <?php -// $Id: views_handler_filter_aggregator_category_cid.inc,v 1.2.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ - /** * Filter by aggregator category cid */ diff --git a/sites/all/modules/views/modules/aggregator/views_plugin_row_aggregator_rss.inc b/sites/all/modules/views/modules/aggregator/views_plugin_row_aggregator_rss.inc index 87258d46d67b4ace79fa5ef686bf4206d73b6650..b2ef964d04c26a1793a2f8d38e774d35d770f1c9 100644 --- a/sites/all/modules/views/modules/aggregator/views_plugin_row_aggregator_rss.inc +++ b/sites/all/modules/views/modules/aggregator/views_plugin_row_aggregator_rss.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_row_aggregator_rss.inc,v 1.1.6.2 2010/01/27 23:28:35 dereine Exp $ /** * @file * Contains the Aggregator Item RSS row style plugin. diff --git a/sites/all/modules/views/modules/book.views.inc b/sites/all/modules/views/modules/book.views.inc index 4736ec68eed286fa977af7cb2001b8110456e092..2b1a82a47074be57d3be1498a590de979ad45b68 100644 --- a/sites/all/modules/views/modules/book.views.inc +++ b/sites/all/modules/views/modules/book.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: book.views.inc,v 1.5.6.4 2009/12/03 20:57:04 merlinofchaos Exp $ /** * @file * Provide views data and handlers for book.module diff --git a/sites/all/modules/views/modules/book.views_convert.inc b/sites/all/modules/views/modules/book.views_convert.inc index 9e2e52f47105bfbe52bae5520d7fe038e942c983..8cf37fc9b6f291d1c150f4b4c96501d1ce14bf33 100644 --- a/sites/all/modules/views/modules/book.views_convert.inc +++ b/sites/all/modules/views/modules/book.views_convert.inc @@ -1,6 +1,4 @@ <?php -// $Id: book.views_convert.inc,v 1.3.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ - /** * @file * Field conversion for fields handled by this module. diff --git a/sites/all/modules/views/modules/comment.views.inc b/sites/all/modules/views/modules/comment.views.inc index 8c1ad8024c988f832e4172e90a30fb0a05c22306..82fa612751b7f66264240caec23723d2aa3a9041 100644 --- a/sites/all/modules/views/modules/comment.views.inc +++ b/sites/all/modules/views/modules/comment.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: comment.views.inc,v 1.33.4.17 2010/11/25 20:56:40 dereine Exp $ /** * @file * Provide views data and handlers for comment.module @@ -17,6 +16,9 @@ */ function comment_views_data() { + $data['comments']['moved to'] = 'comment'; + $data['comments']['comment']['moved to'] = array('field_data_comment_body', 'comment_body'); + $data['comments']['comment']['field']['moved to'] = array('field_data_comment_body', 'comment_body'); // Define the base group of this table. Fields that don't // have a group defined will go into this field by default. $data['comment']['table']['group'] = t('Comment'); @@ -169,6 +171,7 @@ function comment_views_data() { ), ); + $data['comments']['timestamp']['moved to'] = array('comment', 'changed'); // changed (when comment was last updated) $data['comment']['changed'] = array( 'title' => t('Post date'), @@ -184,57 +187,63 @@ function comment_views_data() { 'handler' => 'views_handler_filter_date', ), ); - - $data['comments']['timestamp_fulldate'] = array( + + $data['comments']['timestamp_fulldate']['moved to'] = array('comment', 'changed_fulldata'); + $data['comment']['changed_fulldata'] = array( 'title' => t('Created date'), 'help' => t('In the form of CCYYMMDD.'), 'argument' => array( - 'field' => 'timestamp', + 'field' => 'changed', 'handler' => 'views_handler_argument_node_created_fulldate', ), ); - $data['comments']['timestamp_year_month'] = array( + $data['comments']['timestamp_year_month']['moved to'] = array('comment', 'changed_year_month'); + $data['comment']['changed_year_month'] = array( 'title' => t('Created year + month'), 'help' => t('In the form of YYYYMM.'), 'argument' => array( - 'field' => 'timestamp', + 'field' => 'changed', 'handler' => 'views_handler_argument_node_created_year_month', ), ); - $data['comments']['timestamp_year'] = array( + $data['comments']['timestamp_year']['moved to'] = array('comment', 'changed_year'); + $data['comment']['changed_year'] = array( 'title' => t('Created year'), 'help' => t('In the form of YYYY.'), 'argument' => array( - 'field' => 'timestamp', + 'field' => 'changed', 'handler' => 'views_handler_argument_node_created_year', ), ); - $data['comments']['timestamp_month'] = array( + $data['comments']['timestamp_month']['moved to'] = array('comment', 'changed_month'); + $data['comment']['changed_month'] = array( 'title' => t('Created month'), 'help' => t('In the form of MM (01 - 12).'), 'argument' => array( - 'field' => 'timestamp', + 'field' => 'changed', 'handler' => 'views_handler_argument_node_created_month', ), ); - $data['comments']['timestamp_day'] = array( + $data['comments']['timestamp_day']['moved to'] = array('comment', 'changed_day'); + $data['comment']['changed_day'] = array( 'title' => t('Created day'), 'help' => t('In the form of DD (01 - 31).'), 'argument' => array( - 'field' => 'timestamp', + 'field' => 'changed', 'handler' => 'views_handler_argument_node_created_day', ), ); - $data['comments']['timestamp_week'] = array( + $data['comments']['timestamp_week']['moved to'] = array('comment', 'changed_week'); + $data['comment']['changed_week'] = array( 'title' => t('Created week'), 'help' => t('In the form of WW (01 - 53).'), 'argument' => array( - 'field' => 'timestamp', + 'field' => 'changed', 'handler' => 'views_handler_argument_node_created_week', ), ); @@ -307,13 +316,13 @@ function comment_views_data() { ); $data['comment']['nid'] = array( - 'title' => t('Node'), - 'help' => t('The node the comment is a reply to.'), + 'title' => t('Content'), + 'help' => t('The content to which the comment is a reply to.'), 'relationship' => array( 'base' => 'node', 'base field' => 'nid', 'handler' => 'views_handler_relationship', - 'label' => t('Node'), + 'label' => t('Content'), ), ); @@ -348,7 +357,7 @@ function comment_views_data() { // node_comment_statistics table // define the group - $data['node_comment_statistics']['table']['group'] = t('Node'); + $data['node_comment_statistics']['table']['group'] = t('Content'); // joins $data['node_comment_statistics']['table']['join'] = array( @@ -543,7 +552,18 @@ function template_preprocess_views_view_row_comment(&$vars) { // Put the view on the node so we can retrieve it in the preprocess. $node->view = &$view; - $vars['comment'] = drupal_render(comment_view_multiple(array($comment->cid => $comment), $node)); + $build = comment_view_multiple(array($comment->cid => $comment), $node); + // If we're displaying the comments without links, remove them from the + // renderable array. There is no way to avoid building them in the first + // place (see comment_build_content()). + if (empty($options['links'])) { + foreach ($build as $cid => &$comment_build) { + if (isset($comment_build['links'])) { + unset($comment_build['links']); + } + } + } + $vars['comment'] = drupal_render($build); } /** diff --git a/sites/all/modules/views/modules/comment.views_convert.inc b/sites/all/modules/views/modules/comment.views_convert.inc index d6222115265a2ac7ce9b94ff3178488b32f84490..f4f8d0f620d9ae529b292ee4673de78b4d1b0e1f 100644 --- a/sites/all/modules/views/modules/comment.views_convert.inc +++ b/sites/all/modules/views/modules/comment.views_convert.inc @@ -1,6 +1,4 @@ <?php -//$Id: comment.views_convert.inc,v 1.4.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ - /** * @file * Field conversion for fields handled by this module. diff --git a/sites/all/modules/views/modules/comment.views_default.inc b/sites/all/modules/views/modules/comment.views_default.inc index 6641c47d0e36d72db8a4ac6067878f0f0db5d38f..41ce8b3d36237915fc01453b8881461fa59dcd2f 100644 --- a/sites/all/modules/views/modules/comment.views_default.inc +++ b/sites/all/modules/views/modules/comment.views_default.inc @@ -1,5 +1,4 @@ <?php -// $Id: comment.views_default.inc,v 1.7.6.7 2011/01/05 23:14:39 dereine Exp $ /** * @file * Contains default views on behalf of the comment module. @@ -14,12 +13,13 @@ function comment_views_default_views() { $view->description = 'Contains a block and a page to list recent comments; the block will automatically link to the page, which displays the comment body as well as a link to the node.'; $view->tag = 'default'; $view->base_table = 'comment'; + $view->human_name = 'Recent comments'; $view->api_version = 2; $view->version = 7; $view->disabled = TRUE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* Display: Master */ + $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['title'] = 'Recent comments'; $handler->display->display_options['use_more'] = TRUE; $handler->display->display_options['access']['type'] = 'none'; @@ -50,7 +50,7 @@ function comment_views_default_views() { $handler->display->display_options['sorts']['timestamp']['table'] = 'comment'; $handler->display->display_options['sorts']['timestamp']['field'] = 'changed'; $handler->display->display_options['sorts']['timestamp']['order'] = 'DESC'; - /* Filter: Node: Published or admin */ + /* Filter: Content: Published or admin */ $handler->display->display_options['filters']['status_extra']['id'] = 'status_extra'; $handler->display->display_options['filters']['status_extra']['table'] = 'node'; $handler->display->display_options['filters']['status_extra']['field'] = 'status_extra'; @@ -72,7 +72,7 @@ function comment_views_default_views() { $handler->display->display_options['row_options']['separator'] = ' '; $handler->display->display_options['defaults']['row_options'] = FALSE; $handler->display->display_options['defaults']['fields'] = FALSE; - /* Field: Node: Title */ + /* Field: Content: Title */ $handler->display->display_options['fields']['title']['id'] = 'title'; $handler->display->display_options['fields']['title']['table'] = 'node'; $handler->display->display_options['fields']['title']['field'] = 'title'; @@ -108,10 +108,11 @@ function comment_views_default_views() { $view->description = 'Shows all new activity on system.'; $view->tag = 'default'; $view->base_table = 'node'; + $view->human_name = 'Tracker'; $view->api_version = 2; $view->version = 7; $view->disabled = TRUE; /* Edit this to true to make a default view disabled initially */ - $handler = $view->new_display('default', 'Defaults', 'default'); + $handler = $view->new_display('default', 'Master', 'default'); $handler->override_option('fields', array( 'type' => array( 'id' => 'type', 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 af3bd52f0f9740e57635175be285c25c1d61914f..39a689d6fc14b96b9f033b732f07d5c678f44ce4 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_comment_user_uid.inc,v 1.2.4.4 2010/12/09 23:36:00 dereine Exp $ /** * Argument handler to accept a user id to check for nodes that @@ -34,7 +33,7 @@ class views_handler_argument_comment_user_uid extends views_handler_argument { } } - function query() { + function query($group_by = FALSE) { $this->ensure_my_table(); $nid_alias = $this->query->add_field('node', 'nid'); @@ -53,4 +52,8 @@ class views_handler_argument_comment_user_uid extends views_handler_argument { $this->query->add_where(0, $condition); } + + function get_sort_name() { + return t('Numerical', array(), array('context' => 'Sort order')); + } } 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 4542da79216eca038132a6f58c39906981ba8de1..66ead3d06964853ff9979d218149a92cbdacd0cf 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,5 +1,4 @@ <?php -// $Id: views_handler_field_comment.inc,v 1.5 2009/02/10 20:37:49 merlinofchaos Exp $ /** * Field handler to allow linking to a comment */ @@ -25,26 +24,27 @@ class views_handler_field_comment extends views_handler_field { * Provide link-to-comment option */ function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['link_to_comment'] = array( '#title' => t('Link this field to its comment'), - '#description' => t('This will override any other link you have set.'), + '#description' => t("Enable to override this field's links."), '#type' => 'checkbox', '#default_value' => $this->options['link_to_comment'], ); + parent::options_form($form, $form_state); } function render_link($data, $values) { if (!empty($this->options['link_to_comment']) && $data !== NULL && $data !== '') { $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = "node/". $values->{$this->aliases['nid']}; - $this->options['alter']['fragment'] = "comment-" . $values->{$this->aliases['cid']}; + $this->options['alter']['path'] = "node/". $this->get_value($values, 'nid'); + $this->options['alter']['fragment'] = "comment-" . $this->get_value($values, 'cid'); } return $data; } function render($values) { - return $this->render_link(check_plain($values->{$this->field_alias}), $values); + $value = $this->get_value($values); + return $this->render_link($this->sanitize_value($value), $values); } } 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 272d689baeb96ca1a0afda538c6317f70fd93ce8..e86cddac8ef53e407aeae4363edabcc0e4fe8783 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,5 +1,4 @@ <?php -// $Id: views_handler_field_comment_depth.inc,v 1.1 2008/09/03 19:21:29 merlinofchaos Exp $ /** * Field handler to display the depth of a comment */ 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 77eb6456d570f401e7d265b5d413014342bbb24a..f8fe18c5649174d2a8701327abc6a6ef6f5103b1 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,5 +1,4 @@ <?php -// $Id: views_handler_field_comment_link.inc,v 1.2.6.2 2010/11/30 20:36:00 merlinofchaos Exp $ /** * Base field handler to present a link. */ @@ -17,12 +16,12 @@ class views_handler_field_comment_link extends views_handler_field { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['text'] = array( '#type' => 'textfield', '#title' => t('Text to display'), '#default_value' => $this->options['text'], ); + parent::options_form($form, $form_state); } function query() { @@ -31,16 +30,19 @@ class views_handler_field_comment_link extends views_handler_field { } function render($values) { - return $this->render_link(check_plain($values->{$this->aliases['nid']}), $values); + $value = $this->get_value($values, 'nid'); + return $this->render_link($this->sanitize_value($value), $values); } 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'); $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = "node/" . $values->{$this->aliases['nid']}; + $this->options['alter']['path'] = "comment/" . $cid; $this->options['alter']['html'] = TRUE; - $this->options['alter']['fragment'] = "comment-" . $values->{$this->aliases['cid']}; + $this->options['alter']['fragment'] = "comment-" . $cid; return $text; } 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 7d0256f8101cb1743dcc5867721fd66227e6d366..1efb2743493f0a3f30249c3418f83897bb65f7f0 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,5 +1,4 @@ <?php -// $Id: views_handler_field_comment_link_delete.inc,v 1.1.6.1 2010/11/18 07:29:03 dereine Exp $ /** * Field handler to present a link to delete a node. */ @@ -11,9 +10,10 @@ class views_handler_field_comment_link_delete extends views_handler_field_commen function render_link($data, $values) { $text = !empty($this->options['text']) ? $this->options['text'] : t('delete'); + $cid = $this->get_value($values, 'cid'); $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = "comment/delete/" . $values->{$this->aliases['cid']}; + $this->options['alter']['path'] = "comment/delete/" . $cid; $this->options['alter']['query'] = drupal_get_destination(); return $text; 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 8ed994d58db47657291814ebc3c3d94e55b70837..e2aaa4d31d0b4d99cb058d5b5c999c3344321b12 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,5 +1,4 @@ <?php -// $Id: views_handler_field_comment_link_edit.inc,v 1.1.6.2 2010/11/18 07:29:03 dereine Exp $ /** * Field handler to present a link node edit. */ @@ -24,6 +23,7 @@ class views_handler_field_comment_link_edit extends views_handler_field_comment_ '#title' => t('Use destination'), '#description' => t('Add destination to the link'), '#default_value' => $this->options['destination'], + '#fieldset' => 'more', ); } @@ -31,8 +31,8 @@ class views_handler_field_comment_link_edit extends views_handler_field_comment_ parent::render_link($data, $values); // ensure user has access to edit this comment. $comment = new stdClass(); - $comment->cid = $values->{$this->aliases['cid']}; - $comment->uid = $values->{$this->aliases['uid']}; + $comment->cid = $this->get_value($values, 'cid'); + $comment->uid = $this->get_value($values, 'uid'); if (!comment_access('edit', $comment)) { return; } @@ -44,6 +44,8 @@ class views_handler_field_comment_link_edit extends views_handler_field_comment_ $this->options['alter']['query'] = drupal_get_destination(); } + $this->options['alter']['path'] = "comment/edit/" . $comment->cid; + return $text; } } 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 8bf1fc4de3d02341bafe5071e0099dc0c451c4be..1b922c7168d816c197647b0b943b2aaf89aa8f77 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_comment_link_reply.inc,v 1.1.6.1 2010/11/18 07:29:03 dereine Exp $ /** * Field handler to present a link to delete a node. @@ -12,9 +11,11 @@ class views_handler_field_comment_link_reply extends views_handler_field_comment function render_link($data, $values) { $text = !empty($this->options['text']) ? $this->options['text'] : t('reply'); + $nid = $this->get_value($values, 'nid'); + $cid = $this->get_value($values, 'cid'); $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = "comment/reply/" . $values->{$this->aliases['nid']} . '/' . $values->{$this->aliases['cid']}; + $this->options['alter']['path'] = "comment/reply/" . $nid . '/' . $cid; return $text; } 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 549f5815e8f846350e3cfff6d7c2f2bb00e88ce5..e8c5b0d53fe743a035b5419ce97bcd667cd882ef 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,5 +1,4 @@ <?php -// $Id: views_handler_field_comment_node_link.inc,v 1.1.6.4 2010/11/16 17:01:44 dereine Exp $ /** * Handler for showing comment module's node link. */ @@ -26,15 +25,15 @@ class views_handler_field_comment_node_link extends views_handler_field { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); - $form['teaser'] = array( '#type' => 'checkbox', '#title' => t('Show teaser-style link'), '#default_value' => $this->options['teaser'], '#description' => t('Show the comment link in the form used on standard node teasers, rather than the full node form.'), + '#fieldset' => 'more', ); + parent::options_form($form, $form_state); } function query() { @@ -45,9 +44,9 @@ class views_handler_field_comment_node_link extends views_handler_field { function render($values) { // Build fake $node. $node = new stdClass(); - $node->nid = $values->{$this->aliases['nid']}; - $node->type = $values->{$this->aliases['type']}; - $node->comment = $values->{$this->aliases['comment']}; + $node->nid = $this->get_value($values, 'nid'); + $node->type = $this->get_value($values, 'type'); + $node->comment = $this->get_value($values, 'comment'); // 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 39df0d89313f3dd571b5a267644cf5fc66a1f341..0a3537e1b349765beb4381204dccc28090722382 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,5 +1,4 @@ <?php -// $Id: views_handler_field_comment_username.inc,v 1.2.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * Field handler to allow linking to a user account or homepage */ @@ -20,19 +19,19 @@ class views_handler_field_comment_username extends views_handler_field { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['link_to_user'] = array( '#title' => t("Link this field to its user or an author's homepage"), '#type' => 'checkbox', '#default_value' => $this->options['link_to_user'], ); + parent::options_form($form, $form_state); } function render_link($data, $values) { if (!empty($this->options['link_to_user'])) { - $account->uid = $values->{$this->aliases['uid']}; - $account->name = $values->{$this->field_alias}; - $account->homepage = $values->{$this->aliases['homepage']}; + $account->uid = $this->get_value($values, 'uid'); + $account->name = $this->get_value($values); + $account->homepage = $this->get_value($values, 'homepage'); return theme('username', array( 'account' => $account @@ -44,7 +43,7 @@ class views_handler_field_comment_username extends views_handler_field { } function render($values) { - return $this->render_link(check_plain($values->{$this->field_alias}), $values); + $value = $this->get_value($values); + return $this->render_link($this->sanitize_value($value), $values); } - } 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 8b0c778628febf000dea9fcb0d6d4dc4a7d69dca..64ed7dd1398b9801cef6cb38ff2a1951453f3647 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,4 @@ <?php -// $Id: views_handler_field_last_comment_timestamp.inc,v 1.1.6.2 2010/10/16 08:36:43 dereine Exp $ class views_handler_field_last_comment_timestamp extends views_handler_field_date { function construct() { @@ -8,7 +7,8 @@ class views_handler_field_last_comment_timestamp extends views_handler_field_dat } function render($values) { - if (empty($this->options['empty_zero']) || $values->{$this->aliases['comment_count']}) { + $comment_count = $this->get_value($values, 'comment_count'); + if (empty($this->options['empty_zero']) || $comment_count) { return parent::render($values); } else { 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 511a5283e5a5261e084ec9657f021ffc513b592f..648be92bad55c96253971944af5b011af1d86c2f 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,5 +1,4 @@ <?php -// $Id: views_handler_field_ncs_last_comment_name.inc,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * Field handler to present the name of the last comment poster @@ -35,14 +34,14 @@ class views_handler_field_ncs_last_comment_name extends views_handler_field { function render($values) { if (!empty($this->options['link_to_user'])) { $account = new stdClass(); - $account->name = $values->{$this->field_alias}; + $account->name = $this->get_value($values); $account->uid = $values->{$this->uid}; return theme('username', array( 'account' => $account )); } else { - return check_plain($values->{$this->field_alias}); + return $this->sanitize_value($this->get_value($values)); } } } 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 c7a5d7f306c64c4eccd013c12c644f91fc45a7ed..6c3e139dcc9d9ea8a0d2a331ee981e35256c79af 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,5 +1,4 @@ <?php -// $Id: views_handler_field_ncs_last_updated.inc,v 1.1 2008/09/03 19:21:29 merlinofchaos Exp $ /** * Field handler to display the newer of last comment / node updated */ 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 0ab7ba43eef101b5ece062db7ed5cee138b0f68c..4f89d64c6dcfcaf31b1a20beafff307d01d80bf7 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,12 +1,12 @@ <?php -// $Id: views_handler_field_node_comment.inc,v 1.1.6.1 2010/12/19 10:31:18 dereine Exp $ /** * Display node comment status */ class views_handler_field_node_comment extends views_handler_field { function render($values) { - switch ($values->{$this->field_alias}) { + $value = $this->get_value($values); + switch ($value) { case COMMENT_NODE_HIDDEN: default: return t('Hidden'); 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 a1778b8bbb4d302634bee873e6c1974bba717cb6..6c5835f007b39c27917371d6d814997be0984eaa 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,5 +1,4 @@ <?php -// $Id: views_handler_field_node_new_comments.inc,v 1.7.4.4 2010/11/18 07:50:23 dereine Exp $ /** * Field handler to display the number of new comments @@ -31,13 +30,14 @@ class views_handler_field_node_new_comments extends views_handler_field_numeric } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['link_to_comment'] = array( '#title' => t('Link this field to new comments'), - '#description' => t('This will override any other link you have set.'), + '#description' => t("Enable to override this field's links."), '#type' => 'checkbox', '#default_value' => $this->options['link_to_comment'], ); + + parent::options_form($form, $form_state); } function query() { @@ -85,11 +85,11 @@ class views_handler_field_node_new_comments extends views_handler_field_numeric function render_link($data, $values) { if (!empty($this->options['link_to_comment']) && $data !== NULL && $data !== '') { $node = new stdClass(); - $node->nid = $values->{$this->aliases['nid']}; - $node->type = $values->{$this->aliases['type']}; + $node->nid = $this->get_value($values, 'nid'); + $node->type = $this->get_value($values, 'type'); $this->options['alter']['make_link'] = TRUE; $this->options['alter']['path'] = 'node/' . $node->nid; - $this->options['alter']['query'] = comment_new_page_count($values->{$this->aliases['comment_count']}, $values->{$this->field_alias}, $node); + $this->options['alter']['query'] = comment_new_page_count($this->get_value($values, 'comment_count'), $this->get_value($values), $node); $this->options['alter']['fragment'] = 'new'; } @@ -97,7 +97,8 @@ class views_handler_field_node_new_comments extends views_handler_field_numeric } function render($values) { - if (!empty($values->{$this->field_alias})) { + $value = $this->get_value($values); + if (!empty($value)) { return $this->render_link(parent::render($values), $values); } else { 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 8467d07896fdb03a18dc0f9c4d9813aeeaede22d..900201919b30fbe86f2efdf69a37e7005f1dbdd5 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_comment_user_uid.inc,v 1.2.4.2 2009/11/13 12:36:06 dereine Exp $ /** * Filter handler to accept a user id to check for nodes that user posted or @@ -11,12 +10,13 @@ class views_handler_filter_comment_user_uid extends views_handler_filter_user_na $subselect = db_select('comments', 'c'); $subselect->addField('c', 'cid'); - $subselect->condition('uid', $this->value, $this->operator); - $subselect->condition('nid', "$this->table_alias.nid"); + $subselect->where("uid $this->operator $this->value"); + $subselect->where("nid = $this->table_alias.nid"); $subselect = $subselect->countQuery(); $condition = db_or() ->condition("$this->table_alias.uid", $this->value, $this->operator) + ->where("0 < (" . (string) $subselect . ")") ->condition(0, $subselect, '<'); $this->query->add_where(0, $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 c8f4cbe231f074fc01fdb6c002d2d13abab805a3..f931fe97c573ddb26ef7c48027f807a811b1f3d8 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,5 +1,4 @@ <?php -// $Id: views_handler_filter_ncs_last_updated.inc,v 1.1 2008/09/03 19:21:29 merlinofchaos Exp $ /** * Filter handler for the newer of last comment / node updated */ 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 87831fd98354a020660337bd868a89b9d2079dcd..9351c185e75f8dce28963ca1a03b1631967cddba 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_node_comment.inc,v 1.1.6.1 2010/12/19 10:31:18 dereine Exp $ /** * Filter based on comment node status diff --git a/sites/all/modules/views/modules/comment/views_handler_sort_comment_thread.inc b/sites/all/modules/views/modules/comment/views_handler_sort_comment_thread.inc index 1427bb4c03a6e0b65b8a21662cb7668a561a0576..e529b2a84414fbe01cf945cfdbd5af75f98ddf4f 100644 --- a/sites/all/modules/views/modules/comment/views_handler_sort_comment_thread.inc +++ b/sites/all/modules/views/modules/comment/views_handler_sort_comment_thread.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_sort_comment_thread.inc,v 1.1 2008/09/03 19:21:29 merlinofchaos Exp $ /** * Sort handler for ordering by thread */ 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 61b73313048f30643009840f1a9300dfbec35b27..397bb6c68cb48efdc594cca81053777302add76d 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,5 +1,4 @@ <?php -// $Id: views_handler_sort_ncs_last_comment_name.inc,v 1.1 2008/09/03 19:21:29 merlinofchaos Exp $ /** * Sort handler to sort by last comment name which might be in 2 different * fields 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 5e55d7e55f7f2f90754592adc6e08357e4432efb..fd788ec01a490c9d5a7a87fa865721d282c75513 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,5 +1,4 @@ <?php -// $Id: views_handler_sort_ncs_last_updated.inc,v 1.1 2008/09/03 19:21:29 merlinofchaos Exp $ /** * Sort handler for the newer of last comment / node updated */ 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 9212b86210ff565e1569425aaf595e6ef4c24124..0ff3c3a3671ad5985d74ce81ee42fa204e21f6c2 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_row_comment_rss.inc,v 1.3.6.3 2010/05/21 20:32:06 dereine Exp $ /** * @file * Contains the comment RSS row style plugin. diff --git a/sites/all/modules/views/modules/comment/views_plugin_row_comment_view.inc b/sites/all/modules/views/modules/comment/views_plugin_row_comment_view.inc index cc1dba9eeb2c304aedaaae76eee7e45c2aac419e..5228d9448c117e9249c776bf1d86cb444dbbfb2a 100644 --- a/sites/all/modules/views/modules/comment/views_plugin_row_comment_view.inc +++ b/sites/all/modules/views/modules/comment/views_plugin_row_comment_view.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_row_comment_view.inc,v 1.1.6.2 2010/01/28 00:00:56 dereine Exp $ /** * @file * Contains the node RSS row style plugin. @@ -12,6 +11,13 @@ class views_plugin_row_comment_view extends views_plugin_row { var $base_table = 'comment'; var $base_field = 'cid'; + function summary_title() { + if (empty($this->options['links'])) { + return t('Hide links'); + } + return t('Display links'); + } + function option_definition() { $options = parent::option_definition(); $options['links'] = array('default' => TRUE); @@ -36,8 +42,6 @@ class views_plugin_row_comment_view extends views_plugin_row { $cresult = comment_load_multiple($cids); foreach ($cresult as $comment) { - $comment = drupal_unpack($comment); - $comment->name = $comment->uid ? $comment->registered_name : $comment->name; $comment->depth = count(explode('.', $comment->thread)) - 1; $this->comments[$comment->cid] = $comment; } diff --git a/sites/all/modules/views/modules/contact.views.inc b/sites/all/modules/views/modules/contact.views.inc index 15268841bd66baf377653da541699fcfb62f4ee7..071f2cb4ea01953cb89d950f8872a9d0e95efda3 100644 --- a/sites/all/modules/views/modules/contact.views.inc +++ b/sites/all/modules/views/modules/contact.views.inc @@ -1,5 +1,4 @@ <?php -//$Id: contact.views.inc,v 1.1.6.2 2010/07/19 09:18:42 dereine Exp $ /** * @file * Provide views data and handlers for contact.module 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 f2456f4f37f4a7227f843ffd68db3aeda81e662d..26e5b1d4f91513b3b4cd750c6e37291c1a0cf9e7 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,5 +1,4 @@ <?php -// $Id: views_handler_field_contact_link.inc,v 1.2.4.5 2010/12/23 05:44:54 dereine Exp $ /** * A field that links to the user contact page, if access is permitted. */ @@ -12,7 +11,6 @@ class views_handler_field_contact_link extends views_handler_field_user_link { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['link_display'] = array( '#title' => t('Type of link'), '#default_value' => $this->options['link_display'], @@ -25,6 +23,7 @@ class views_handler_field_contact_link extends views_handler_field_user_link { $form['text']['#title'] = t('Link label'); $form['text']['#required'] = TRUE; $form['text']['#default_value'] = empty($this->options['text']) ? t('contact') : $this->options['text']; + parent::options_form($form, $form_state); } // An example of field level access control. @@ -43,7 +42,7 @@ class views_handler_field_contact_link extends views_handler_field_user_link { function render_link($data, $values) { global $user; - $uid = $values->{$this->aliases['uid']}; + $uid = $this->get_value($values, 'uid'); if (empty($uid)) { return; @@ -56,7 +55,8 @@ 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. - if (!_contact_personal_tab_access($account) || empty($account->contact)) { + $menu_item = menu_get_item("user/$uid/contact"); + if (!$menu_item['access'] || empty($account->contact)) { return; } diff --git a/sites/all/modules/views/modules/field.views.inc b/sites/all/modules/views/modules/field.views.inc index 7c2ac663b2aabaceff283e37d667a3d08e4694e9..0cf726b58476dcf93b978af724f420a920c358b6 100644 --- a/sites/all/modules/views/modules/field.views.inc +++ b/sites/all/modules/views/modules/field.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: field.views.inc,v 1.1.2.17 2011/01/04 23:54:35 dereine Exp $ /** * @file @@ -38,6 +37,31 @@ function field_views_data() { return $data; } +/** + * Returns the label of a certain field. + * + * Therefore it looks up in all bundles to find the most used instance. + */ +function field_views_field_label($field_name) { + $label_counter = array(); + // Count the amount of instances per label per field. + $instances = field_info_instances(); + foreach ($instances as $entity_type) { + foreach ($entity_type as $bundle) { + if (isset($bundle[$field_name])) { + $label_counter[$bundle[$field_name]['label']] = isset($label_counter[$bundle[$field_name]['label']]) ? ++$label_counter[$bundle[$field_name]['label']] : 1; + } + } + } + if (empty($label_counter)) { + return $field_name; + } + // Sort the field lables by it most used label and return the most used one. + arsort($label_counter); + $label_counter = array_keys($label_counter); + return $label_counter[0]; +} + /** * Default views data implementation for a field. */ @@ -58,11 +82,24 @@ function field_views_field_default_views_data($field) { $bundles_names = array(); $supports_revisions = FALSE; $entity_tables = array(); + $group_name = count($field['bundles']) > 1 ? t('Fields') : NULL; // Build the relationships between the field table and the entity tables. foreach ($field['bundles'] as $entity => $bundles) { $entity_info = entity_get_info($entity); + if (empty($group_name)) { + $group_name = $entity_info['label']; + + // Override Node to Content. + if ($group_name == t('Node')) { + $group_name = t('Content'); + } + } + $entity_tables[$entity_info['base table']] = $entity; + if (isset($entity_info['revision table'])) { + $entity_tables[$entity_info['revision table']] = $entity; + } $data[$current_table]['table']['join'][$entity_info['base table']] = array( 'left_field' => $entity_info['entity keys']['id'], @@ -102,22 +139,28 @@ function field_views_field_default_views_data($field) { $add_fields[] = _field_sql_storage_columnname($field['field_name'], $column_name); } - // Add the field handler for this field. - $title_short = $field['field_name']; + // Note: we don't have a label available here, because we are at the field + // level, not at the instance level. So we just go through all instances + // and take the one which is used the most frequently. + $field_name = $field['field_name']; + $label = field_views_field_label($field_name); foreach ($tables as $type => $table) { if ($type == FIELD_LOAD_CURRENT) { - $group = t('Fields'); - $column = 'entity_id'; + $group = $group_name; + $old_column = 'entity_id'; + $column = $field['field_name']; } else { - $group = t('Fields (historical data)'); - $column = 'revision_id'; + $group = t('@group (historical data)', array('@group' => $group_name)); + $old_column = 'revision_id'; + $column = $field['field_name'] . '-' . $old_column; } + $data[$table][$old_column]['field']['moved to'] = array($table, $column); $data[$table][$column] = array( 'group' => $group, - 'title' => $title_short, - 'title short' => $title_short, + 'title' => $label, + 'title short' => $label, 'help' => t('Appears in: @bundles', array('@bundles' => implode(', ', $bundles_names))), ); $data[$table][$column]['field'] = array( @@ -128,8 +171,16 @@ function field_views_field_default_views_data($field) { 'field_name' => $field['field_name'], 'additional fields' => $add_fields, 'entity_tables' => $entity_tables, - 'field_info' => $field, + // Default the element type to div, let the UI change it if necessary. + 'element type' => 'div', + 'is revision' => $type == FIELD_LOAD_REVISION, + 'entity id' => $entity_info['entity keys']['id'], + 'base table' => $entity_info['base table'], ); + if ($type == FIELD_LOAD_REVISION) { + $data[$table][$column]['field']['revision id'] = $entity_info['entity keys']['revision']; + $data[$table][$column]['field']['base table'] = $entity_info['revision table']; + } } foreach ($field['columns'] as $column => $attributes) { @@ -159,15 +210,15 @@ function field_views_field_default_views_data($field) { break; } - // Note: we don't have a label available here, because we are at the field - // level, not at the instance level. + if (count($field['columns']) == 1 && $column == 'value') { - $title = t('@label (!name)', array('@label' => $field['field_name'], '!name' => $field['field_name'])); + $title = t('@label (!name)', array('@label' => $label, '!name' => $field['field_name'])); + // CCK used the first 10 characters of $label. Probably doesn't matter. $title_short = $field['field_name']; } else { - $title = t('@label (!name) - !column', array('@label' => $field['field_name'], '!name' => $field['field_name'], '!column' => $column)); - $title_short = t('@label-truncated - !column', array('@label-truncated' => $field['field_name'], '!column' => $column)); + $title = t('@label (!name) - !column', array('@label' => $label, '!name' => $field['field_name'], '!column' => $column)); + $title_short = t('@label - !column', array('@label' => $field['field_name'], '!column' => $column)); } foreach ($tables as $type => $table) { @@ -212,13 +263,13 @@ function field_views_field_default_views_data($field) { // Expose additional delta column for multiple value fields. if ($field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) { - $title = t('@label (!name) - delta', array('@label' => $field['field_name'], '!name' => $field['field_name'])); - $title_short = t('!name - delta', array('!name' => $field['field_name'])); + $title_delta = t('@label (!name) - delta', array('@label' => $label, '!name' => $field['field_name'])); + $title_short_delta = t('!name - delta', array('!name' => $field['field_name'])); $data[$table]['delta'] = array( 'group' => $group, - 'title' => $title, - 'title short' => $title_short, + 'title' => $title_delta, + 'title short' => $title_short_delta, 'help' => t('Delta - Appears in: @bundles', array('@bundles' => implode(', ', $bundles_names))), ); $data[$table]['delta']['argument'] = array( @@ -257,9 +308,9 @@ function field_views_field_default_views_data($field) { function list_field_views_data($field) { $data = field_views_field_default_views_data($field); foreach ($data as $table_name => $table_data) { - foreach ($table_data as $field_name => $field_data) { - if (!in_array($field_name, array('table', 'entity_id', 'revision_id'))) { - $data[$table_name][$field_name]['filter']['handler'] = 'views_handler_filter_field_list'; + foreach ($table_data as $field => $field_data) { + if (isset($field_data['filter'])) { + $data[$table_name][$field]['filter']['handler'] = 'views_handler_filter_field_list'; } } } 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 e3cd7f8229d29bf12c034a2079f6d3fea4522eb6..b8c29d4847716712c7e2044b8ab7c2702d422e54 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_field.inc,v 1.1.2.20 2011/01/06 00:37:05 dereine Exp $ /** * Helper function: Return an array of formatter options for a field type. @@ -32,6 +31,40 @@ function _field_view_formatter_options($field_type = NULL) { * A field that displays fields. */ class views_handler_field_field extends views_handler_field { + /** + * An array to store field renderable arrays for use by render_items. + */ + public $items = array(); + + /** + * Store the field informations. + */ + public $field_info = array(); + + function init(&$view, &$options) { + parent::init($view, $options); + + $this->field_info = $field = field_info_field($this->definition['field_name']); + $this->multiple = FALSE; + $this->limit_values = FALSE; + + if ($field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) { + $this->multiple = TRUE; + + // If "Display all values in the same row" is FALSE, then we always limit + // in order to show a single unique value per row. + if (!$this->options['group_rows']) { + $this->limit_values = TRUE; + } + + // Otherwise, we only limit values if the user hasn't selected "all", 0, or + // the value matching field cardinality. + if (intval($this->options['delta_limit']) && ($this->options['delta_limit'] != $field['cardinality'])) { + $this->limit_values = TRUE; + } + } + } + /** * Called to add the field to a query. * @@ -44,8 +77,7 @@ class views_handler_field_field extends views_handler_field { * present in the query itself (such as "sphinx"). */ function query($use_groupby = FALSE) { - $base_table = $this->view->base_table; - $base_field = $this->view->base_field; + $base_table_alias = $base_table = $this->definition['base table']; // If the current field is under a relationship you can't be sure that the // base table of the view is the base table of the current field. @@ -54,7 +86,10 @@ class views_handler_field_field extends views_handler_field { foreach ($this->view->relationship as $relationship) { if ($relationship->alias == $this->relationship) { $base_table = $relationship->definition['base']; - $base_field = $relationship->definition['base field']; + $base_table_alias = $relationship->alias; + + $table_data = views_fetch_data($base_table); + $base_field = $table_data['table']['base']['field']; } } } @@ -69,19 +104,27 @@ class views_handler_field_field extends views_handler_field { ); } - // We always need the base field (entity_id / revision_id). - $this->field_alias = $this->query->add_field($base_table, $base_field, '', $params); - // Get the entity type according to the base table of the field. // Then add it to the query as a formula. That way we can avoid joining // the field table if all we need is entity_id and entity_type. - $this->entity_type = $entity_type = $this->definition['entity_tables'][$base_table]; + $entity_type = $this->definition['entity_tables'][$base_table]; + $entity_info = entity_get_info($entity_type); + + // We always need the base field (entity_id / revision_id). + if (empty($this->definition['is revision'])) { + $this->field_alias = $this->query->add_field($base_table_alias, $entity_info['entity keys']['id'], '', $params); + } + else { + $this->field_alias = $this->query->add_field($base_table_alias, $entity_info['entity keys']['revision'], '', $params); + $this->aliases['entity id'] = $this->query->add_field($base_table_alias, $entity_info['entity keys']['id'], '', $params); + } + + // The alias needs to be unique, so we use both the field table and the entity type. $entity_type_alias = $this->definition['table'] . '_' . $entity_type . '_entity_type'; $this->aliases['entity_type'] = $this->query->add_field(NULL, "'$entity_type'", $entity_type_alias); $fields = $this->additional_fields; - // We've already added entity_type, so we can remove it from the list. $entity_type_key = array_search('entity_type', $fields); if ($entity_type_key !== FALSE) { @@ -99,14 +142,14 @@ class views_handler_field_field extends views_handler_field { } // Add additional fields (and the table join itself) if needed. - if ($use_groupby || !empty($this->definition['add fields to query'])) { + if ($this->add_field_table($use_groupby)) { $this->ensure_my_table(); $this->add_additional_fields($fields); // Filter by language, if field translation is enabled. - $field = $this->definition['field_info']; - if (field_is_translatable($entity_type, $field)) { - $column = $this->table_alias . ".language"; + $field = $this->field_info; + if (field_is_translatable($entity_type, $field) && !empty($this->query->options['field_language_add_to_query'])) { + $column = $this->table_alias . '.language'; $this->query->add_where(0, $column, $this->query->options['field_language']); } } @@ -121,19 +164,56 @@ class views_handler_field_field extends views_handler_field { $this->add_additional_fields(array('revision_id')); } + /** + * Determine if the field table should be added to the query. + */ + function add_field_table($use_groupby) { + // Grouping is enabled, or we are explicitly required to do this. + if ($use_groupby || !empty($this->definition['add fields to query'])) { + return TRUE; + } + // This a multiple value field, but "group multiple values" is not checked. + if ($this->multiple && !$this->options['group_rows']) { + return TRUE; + } + return FALSE; + } + + /** + * Determine if this field is click sortable. + */ + function click_sortable() { + // Not click sortable in any case. + if (empty($this->definition['click sortable'])) { + return FALSE; + } + // A field is not click sortable if it's a multiple field with + // "group multiple values" checked, since a click sort in that case would + // add a join to the field table, which would produce unwanted duplicates. + if ($this->multiple && $this->options['group_rows']) { + return FALSE; + } + return TRUE; + } + /** * Called to determine what to tell the clicksorter. */ function click_sort($order) { + $this->ensure_my_table(); $column = _field_sql_storage_columnname($this->definition['field_name'], $this->options['click_sort_column']); - // The field has already been added to the query, just add a sort on it. + if (!isset($this->aliases[$column])) { + // Column is not in query; add a sort on it (without adding the column). + $this->aliases[$column] = $this->table_alias . '.' . $column; + } $this->query->add_orderby(NULL, NULL, $order, $this->aliases[$column]); } function option_definition() { $options = parent::option_definition(); - $field = $this->definition['field_info']; + // option_definition runs before init/construct, so no $this->field_info + $field = field_info_field($this->definition['field_name']); $field_type = field_info_field_types($field['type']); $column_names = array_keys($field['columns']); @@ -154,16 +234,46 @@ class views_handler_field_field extends views_handler_field { 'default' => array(), ); + // Options used for multiple value fields. + $options['group_rows'] = array( + 'default' => TRUE, + ); + // If we know the exact number of allowed values, then that can be + // the default. Otherwise, default to 'all'. + $options['delta_limit'] = array( + 'default' => ($field['cardinality'] > 1) ? $field['cardinality'] : 'all', + ); + $options['delta_offset'] = array( + 'default' => 0, + ); + $options['delta_reversed'] = array( + 'default' => FALSE, + ); + + $options['multi_type'] = array( + 'default' => 'separator' + ); + $options['separator'] = array( + 'default' => ', ' + ); + + $options['field_api_classes'] = array( + 'default' => FALSE, + ); + return $options; } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); - - $field = $this->definition['field_info']; + $field = $this->field_info; $formatters = _field_view_formatter_options($field['type']); $column_names = array_keys($field['columns']); + // If this is a multiple value field, add its options. + if ($this->multiple) { + $this->multiple_options_form($form, $form_state); + } + // No need to ask the user anything if the field has only one column. if (count($field['columns']) == 1) { $form['click_sort_column'] = array( @@ -178,6 +288,7 @@ class views_handler_field_field extends views_handler_field { '#options' => drupal_map_assoc($column_names), '#default_value' => $this->options['click_sort_column'], '#description' => t('Used by Style: Table to determine the actual column to click sort the field on. The default is usually fine.'), + '#fieldset' => 'more', ); } @@ -189,15 +300,25 @@ class views_handler_field_field extends views_handler_field { '#ajax' => array( 'path' => views_ui_build_form_url($form_state), ), + '#submit' => array('views_ui_config_item_form_submit_temporary'), + '#executes_submit_callback' => TRUE, ); - // Get the currently selected formatter. - if (isset($form_state['values']['options']['type'])) { - $format = $form_state['values']['options']['type']; - } - else { - $format = $this->options['type']; + $form['field_api_classes'] = array( + '#title' => t('Use field template'), + '#type' => 'checkbox', + '#default_value' => $this->options['field_api_classes'], + '#description' => t('If checked, field api classes will be added using field.tpl.php (or equivalent). This is not recommended unless your CSS depends upon these classes. If not checked, template will not be used.'), + '#fieldset' => 'more', + ); + + if ($this->multiple) { + $form['field_api_classes']['#description'] .= ' ' . t('Checking this option will cause the group Display Type and Separator values to be ignored.'); } + + // Get the currently selected formatter. + $format = $this->options['type']; + $formatter = field_info_formatter_types($format); $settings = $this->options['settings'] + field_info_formatter_settings($format); @@ -218,6 +339,110 @@ class views_handler_field_field extends views_handler_field { $settings_form = $function($field, $instance, '_dummy', $form, $form_state); } $form['settings'] = $settings_form; + + parent::options_form($form, $form_state); + } + + /** + * Provide options for multiple value fields. + */ + function multiple_options_form(&$form, &$form_state) { + $field = $this->field_info; + + $form['multiple_field_settings'] = array( + '#type' => 'fieldset', + '#title' => t('Multiple field settings'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#weight' => 5, + ); + + $form['group_rows'] = array( + '#title' => t('Display all values in the same row'), + '#type' => 'checkbox', + '#default_value' => $this->options['group_rows'], + '#description' => t('If checked, multiple values for this field will be shown in the same row. If not checked, each value in this field will create a new row.'), + '#fieldset' => 'multiple_field_settings', + ); + + // Make the string translatable by keeping it as a whole rather than + // translating prefix and suffix separately. + list($prefix, $suffix) = explode('@count', t('Display @count value(s)')); + + if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) { + $type = 'textfield'; + $options = NULL; + $size = 5; + $process = array(); + } + else { + $type = 'select'; + $options = drupal_map_assoc(range(1, $field['cardinality'])); + $size = 1; + $process = array('form_process_select'); + } + $form['multi_type'] = array( + '#type' => 'radios', + '#title' => t('Display type'), + '#options' => array( + 'ul' => t('Unordered list'), + 'ol' => t('Ordered list'), + 'separator' => t('Simple separator'), + ), + '#process' => array('form_process_radios', 'ctools_dependent_process'), + '#dependency' => array('edit-options-group-rows' => array(TRUE)), + '#default_value' => $this->options['multi_type'], + '#fieldset' => 'multiple_field_settings', + ); + + $form['separator'] = array( + '#type' => 'textfield', + '#title' => t('Separator'), + '#default_value' => $this->options['separator'], + '#process' => array('ctools_dependent_process'), + '#dependency' => array( + 'radio:options[multi_type]' => array('separator'), + 'edit-options-group-rows' => array(TRUE), + ), + '#dependency_count' => 2, + '#fieldset' => 'multiple_field_settings', + ); + + $form['delta_limit'] = array( + '#type' => $type, + '#size' => $size, + '#field_prefix' => $prefix, + '#field_suffix' => $suffix, + '#options' => $options, + '#default_value' => $this->options['delta_limit'], + '#prefix' => '<div class="container-inline">', + '#process' => $process + array('ctools_dependent_process'), + '#dependency' => array('edit-options-group-rows' => array(TRUE)), + '#fieldset' => 'multiple_field_settings', + ); + + list($prefix, $suffix) = explode('@count', t('starting from @count')); + $form['delta_offset'] = array( + '#type' => 'textfield', + '#size' => 5, + '#field_prefix' => $prefix, + '#field_suffix' => $suffix, + '#default_value' => $this->options['delta_offset'], + '#process' => array('ctools_dependent_process'), + '#dependency' => array('edit-options-group-rows' => array(TRUE)), + '#description' => t('(first item is 0)'), + '#fieldset' => 'multiple_field_settings', + ); + $form['delta_reversed'] = array( + '#title' => t('Reversed'), + '#type' => 'checkbox', + '#default_value' => $this->options['delta_reversed'], + '#suffix' => '</div>', + '#process' => array('form_process_checkbox', 'ctools_dependent_process'), + '#dependency' => array('edit-options-group-rows' => array(TRUE)), + '#description' => t('(start from last values)'), + '#fieldset' => 'multiple_field_settings', + ); } /** @@ -227,7 +452,7 @@ class views_handler_field_field extends views_handler_field { parent::groupby_form($form, $form_state); // With "field API" fields, the column target of the grouping function // and any additional grouping columns must be specified. - $group_columns = drupal_map_assoc(array_keys($this->definition['field_info']['columns']), 'ucfirst'); + $group_columns = drupal_map_assoc(array_keys($this->field_info['columns']), 'ucfirst'); $form['group_column'] = array( '#type' => 'select', '#title' => t('Group column'), @@ -256,8 +481,8 @@ class views_handler_field_field extends views_handler_field { } else { // Add settings for "field API" fields. - $item['group_column'] = $form_state['values']['group_column']; - $item['group_columns'] = array_filter($form_state['values']['group_columns']); + $item['group_column'] = $form_state['values']['options']['group_column']; + $item['group_columns'] = array_filter($form_state['values']['options']['group_columns']); } } @@ -268,52 +493,182 @@ class views_handler_field_field extends views_handler_field { if (!empty($values)) { // Divide the entity ids by entity type, so they can be loaded in bulk. $entities_by_type = array(); + $revisions_by_type = array(); foreach ($values as $key => $object) { if (isset($object->{$this->field_alias}) && !isset($values[$key]->_field_data[$this->field_alias])) { $entity_type = $object->{$this->aliases['entity_type']}; - $entity_id = $object->{$this->field_alias}; - $entities_by_type[$entity_type][$key] = $entity_id; + if (empty($this->definition['revision id'])) { + $entity_id = $object->{$this->field_alias}; + $entities_by_type[$entity_type][$key] = $entity_id; + } + else { + $revision_id = $object->{$this->field_alias}; + $entity_id = $object->{$this->aliases['entity id']}; + $entities_by_type[$entity_type][$key] = array($entity_id, $revision_id); + } } } // Load the entities. foreach ($entities_by_type as $entity_type => $entity_ids) { - $entities = entity_load($entity_type, $entity_ids); + $entity_info = entity_get_info($entity_type); + if (empty($this->definition['is revision'])) { + $entities = entity_load($entity_type, $entity_ids); + $keys = $entity_ids; + } + else { + // Revisions can't be loaded multiple, so we have to load them + // one by one. + $entities = array(); + $keys = array(); + foreach ($entity_ids as $key => $combined) { + list($entity_id, $revision_id) = $combined; + $entity = entity_load($entity_type, array($entity_id), array($entity_info['entity keys']['revision'] => $revision_id)); + if ($entity) { + $entities[$revision_id] = array_shift($entity); + $keys[$key] = $revision_id; + } + } + } - foreach ($entity_ids as $key => $entity_id) { - $values[$key]->_field_data[$this->field_alias] = array( - 'entity_type' => $entity_type, - 'entity' => $entities[$entity_id], - ); + foreach ($keys as $key => $entity_id) { + // If this is a revision, load the revision instead. + if (isset($entities[$entity_id])) { + $values[$key]->_field_data[$this->field_alias] = array( + 'entity_type' => $entity_type, + 'entity' => $entities[$entity_id], + ); + // Push the field values directly into the results array to make themers the life a bit easier. + $values[$key]->{$this->definition['table'] . '_' . $entity_type . '_values'} = field_get_items($entity_type, $entities[$entity_id], $this->definition['field_name']); + } } } } } - function render($values) { - if (isset($values->_field_data[$this->field_alias])) { - // Prepare arguments for rendering based on the objects cached in the - // pre-render phase and the display options for this field. - $entity_type = $values->_field_data[$this->field_alias]['entity_type']; - $entity = $values->_field_data[$this->field_alias]['entity']; + /** + * Render all items in this field together. + * + * When using advanced render, each possible item in the list is rendered + * individually. Then the items are all pasted together. + */ + function render_items($items) { + if (!empty($items)) { + if (!$this->options['group_rows']) { + return implode('', $items); + } - // The field we are trying to display doesn't exist on this entity. - if (!isset($entity->{$this->definition['field_name']})) { - return ''; + if ($this->options['multi_type'] == 'separator') { + return implode(check_plain($this->options['separator']), $items); } + else { + return theme('item_list', + array( + 'items' => $items, + 'title' => NULL, + 'type' => $this->options['multi_type'] + )); + } + } + } - $display = array( - 'type' => $this->options['type'], - 'settings' => $this->options['settings'], - 'label' => 'hidden', - ); + /** + * Return an array of items for the field. + * + * Items should be stored in the result array, if possible, as an array + * with 'value' as the actual displayable value of the item, plus + * any items that might be found in the 'alter' options array for + * creating links, such as 'path', 'fragment', 'query' etc, such a thing + * is to be made. Additionally, items that might be turned into tokens + * should also be in this array. + */ + function get_items($values) { + if (empty($values->_field_data[$this->field_alias]) || empty($values->_field_data[$this->field_alias]['entity'])) { + return array(); + } - $langcode = $this->field_language(); - $render_array = field_view_field($entity_type, $entity, $this->definition['field_name'], $display, $langcode); - return drupal_render($render_array); + // Go ahead and render and store in $this->items. + $entity = clone $values->_field_data[$this->field_alias]['entity']; + $entity_type = $values->_field_data[$this->field_alias]['entity_type']; + $langcode = $this->field_language($entity_type); + + // The field we are trying to display doesn't exist on this entity. + if (!isset($entity->{$this->definition['field_name']})) { + return array(); } - else { - return ''; + + // We are supposed to show only certain deltas. + if ($this->limit_values && !empty($entity->{$this->definition['field_name']})) { + $all_values = $entity->{$this->definition['field_name']}[$langcode]; + if ($this->options['delta_reversed']) { + $all_values = array_reverse($all_values); + } + + // 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']})) { + $delta_limit = 1; + $offset = $values->{$this->aliases['delta']}; + } + else { + $delta_limit = $this->options['delta_limit']; + $offset = intval($this->options['delta_offset']); + } + + $new_values = array(); + for ($i = 0; $i < $delta_limit; $i++) { + $new_delta = $offset + $i; + + if (isset($all_values[$new_delta])) { + $new_values[] = $all_values[$new_delta]; + } + } + $entity->{$this->definition['field_name']}[$langcode] = $new_values; + } + + $display = array( + 'type' => $this->options['type'], + 'settings' => $this->options['settings'], + 'label' => 'hidden', + ); + + + $render_array = field_view_field($entity_type, $entity, $this->definition['field_name'], $display, $langcode); + + $items = array(); + if ($this->options['field_api_classes']) { + // Make a copy. + $array = $render_array; + return array(array('rendered' => drupal_render($render_array))); + } + + foreach (element_children($render_array) as $count) { + $items[$count]['rendered'] = $render_array[$count]; + $items[$count]['raw'] = $render_array['#items'][$count]; + } + return $items; + } + + function render_item($count, $item) { + return render($item['rendered']); + } + + function document_self_tokens(&$tokens) { + $field = $this->field_info; + foreach ($field['columns'] as $id => $column) { + $tokens['[' . $this->options['id'] . '-' . $id . ']'] = t('Raw @column', array('@column' => $id)); + } + } + + function add_self_tokens(&$tokens, $item) { + $field = $this->field_info; + foreach ($field['columns'] as $id => $column) { + // Use filter_xss_admin because it's user data and we can't be sure it is safe. + // We know nothing about the data, though, so we can't really do much else. + if (isset($item['raw']) && is_scalar($item['raw'])) { + $tokens['[' . $this->options['id'] . '-' . $id . ']'] = filter_xss_admin($item['raw'][$id]); + } } } @@ -321,10 +676,10 @@ class views_handler_field_field extends views_handler_field { * Return the language code of the language the field should be displayed in, * according to the settings. */ - function field_language() { + function field_language($entity_type) { global $language_content; - if (field_is_translatable($this->entity_type, $this->definition['field_info'])) { + if (field_is_translatable($entity_type, $this->field_info)) { $default_language = language_default('language'); $language = str_replace(array('***CURRENT_LANGUAGE***', '***DEFAULT_LANGUAGE***'), array($language_content->language, $default_language), 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 a43e465f61e2e81bd0760da242d0876dc3ee3b19..dcae181647052ce6df12aad1473948ad25d8ffed 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,4 @@ <?php -// $Id: views_handler_filter_field_list.inc,v 1.1.2.2 2010/09/30 20:07:59 dereine Exp $ class views_handler_filter_field_list extends views_handler_filter_in_operator { function get_value_options() { diff --git a/sites/all/modules/views/modules/filter.views.inc b/sites/all/modules/views/modules/filter.views.inc index 1251c9d62d81a1fb8b50fc7a0822171506165fdc..ff6156f1ac843f1d326495f5421dd4578b004d36 100644 --- a/sites/all/modules/views/modules/filter.views.inc +++ b/sites/all/modules/views/modules/filter.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: filter.views.inc,v 1.1.6.2 2010/07/19 09:18:42 dereine Exp $ /** * @file * Provide basic views data for filter.module. @@ -17,11 +16,12 @@ */ function filter_views_data() { // ---------------------------------------------------------------------- - // filter_formats table + // filter_format table // Have not defined $data['filter_formats']['table']['group'] since // no fields are defined here yet. - $data['filter_formats']['table']['join'] = array( + $data['filter_formats']['moved to'] = 'filter_format'; + $data['filter_format']['table']['join'] = array( 'node_revisions' => array( 'left_field' => 'format', 'field' => 'format', 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 301b17a0da54fdae30b0337826f0127215c6f2b4..dec6dacc71847f1d9d27fc6b1bba765a2194cfc7 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,5 +1,4 @@ <?php -// $Id: views_handler_field_filter_format_name.inc,v 1.2.4.2 2010/05/22 11:57:38 dereine Exp $ /** * Field handler to output the name of an input format. */ @@ -16,14 +15,14 @@ class views_handler_field_filter_format_name extends views_handler_field { } function render($values) { - $format_name = $values->{$this->aliases['name']}; + $format_name = $this->get_value($values, 'name'); if (!$format_name) { // Default or invalid input format. // filter_formats() will reliably return the default format even if the // current user is unprivileged. $format = filter_formats(filter_default_format()); - return check_plain($format->name); + return $this->sanitize_value($format->name); } - return check_plain($format_name); + return $this->sanitize_value($format_name); } } diff --git a/sites/all/modules/views/modules/locale.views.inc b/sites/all/modules/views/modules/locale.views.inc index 50ead26925f983e74a42cd62c3f6791380555150..057b2a636c8eaa35defc817aa4fab7baa734a460 100644 --- a/sites/all/modules/views/modules/locale.views.inc +++ b/sites/all/modules/views/modules/locale.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: locale.views.inc,v 1.1.6.2 2010/07/19 09:18:42 dereine Exp $ /** * @file 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 e199e67fe5f0f7ce11b449742321ea5daf8f9c6a..199c7d1f0bfefd36e4b5e9779a4062a2a2002695 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_locale_group.inc,v 1.1 2009/02/20 23:02:09 merlinofchaos Exp $ /** * Argument handler to accept a language. 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 32b8288d6eda3f140dffc84750ee0eb394755376..00fafdc7884abf6e6c77f5cf0b2b503ccddd21ea 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_locale_language.inc,v 1.1 2009/02/20 23:02:09 merlinofchaos Exp $ /** * Argument handler to accept a language. 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 ffd0d43c50d86dc4e3c4cccfbcba69f136eab405..a8e7a32e9f71dca414de5863190ada43ef382560 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_locale_group.inc,v 1.1 2009/02/20 23:02:09 merlinofchaos Exp $ /** * Field handler to translate a group into its readable form. @@ -9,6 +8,7 @@ class views_handler_field_locale_group extends views_handler_field { $groups = module_invoke_all('locale', 'groups'); // Sort the list. asort($groups); - return isset($groups[$values->{$this->field_alias}]) ? $groups[$values->{$this->field_alias}] : ''; + $value = $this->get_value($values); + return isset($groups[$value]) ? $groups[$value] : ''; } } 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 d35242721d96b5fa6f5bc8c8ddd890c472dd0590..140c23adf540de3721f2823bfea4982d593448a3 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 @@ -1,12 +1,29 @@ <?php -// $Id: views_handler_field_locale_language.inc,v 1.1 2009/02/20 23:02:09 merlinofchaos Exp $ /** * Field handler to translate a language into its readable form. */ class views_handler_field_locale_language extends views_handler_field { + function option_definition() { + $options = parent::option_definition(); + $options['native_language'] = array('default' => FALSE); + + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $form['native_language'] = array( + '#title' => t('Native language'), + '#type' => 'checkbox', + '#default_value' => $this->options['native_language'], + '#description' => t('If enabled, the native name of the language will be displayed'), + ); + } + function render($values) { - $languages = language_list(); - return isset($languages[$values->{$this->field_alias}]) ? $languages[$values->{$this->field_alias}]->name : ''; + $languages = locale_language_list(empty($this->$options['native_language']) ? 'name' : 'native'); + $value = $this->get_value($values); + return isset($languages[$value]) ? $languages[$value]->name : ''; } } 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 62d3c3b97421fa14f076e4cb36c6a887f07f3d83..271f858e63505d66d00148f71323e77a87d94166 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_locale_link_edit.inc,v 1.1.6.2 2010/11/30 20:36:01 merlinofchaos Exp $ /** * Field handler to present a link to edit a translation. @@ -19,12 +18,12 @@ class views_handler_field_locale_link_edit extends views_handler_field { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['text'] = array( '#type' => 'textfield', '#title' => t('Text to display'), '#default_value' => $this->options['text'], ); + parent::options_form($form, $form_state); } function query() { @@ -38,14 +37,15 @@ class views_handler_field_locale_link_edit extends views_handler_field { } function render($values) { - return $this->render_link(check_plain($values->{$this->aliases['lid']}), $values); + $value = $this->get_value($values, 'lid'); + return $this->render_link($this->sanitize_value($value), $values); } function render_link($data, $values) { $text = !empty($this->options['text']) ? $this->options['text'] : t('edit'); $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = 'admin/build/translate/edit/' . $values->{$this->aliases['lid']}; + $this->options['alter']['path'] = 'admin/build/translate/edit/' . $data; $this->options['alter']['query'] = drupal_get_destination(); return $text; 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 ae0526f8709fc0ec38d4baa8d1f83f9746341d64..d46426f01d6be1c3b3b67b185d325ea253de478b 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_locale_group.inc,v 1.1 2009/02/20 23:02:09 merlinofchaos Exp $ /** * Filter by locale group. 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 1c215055aabcaede3717599bddb379387b0fcd16..9eb97874aacab5efe2fca41bc7d4d2a12ac2aaec 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_locale_language.inc,v 1.1.6.1 2011/01/06 00:37:05 dereine Exp $ /** * Filter by language. 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 45cbcad2c4650b738e5bb0f05310b8ba767328d1..7a472cf7b0a7885f7aabb96d3a5d35e576ac3aa1 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_locale_version.inc,v 1.1.6.2 2009/11/13 12:36:05 dereine Exp $ /** * Filter by version. diff --git a/sites/all/modules/views/modules/node.views.inc b/sites/all/modules/views/modules/node.views.inc index 8609260db0a8eb0ceed54e834f438f820b97d920..785d83eced9e3e700f3903da77be96b1e5858633 100644 --- a/sites/all/modules/views/modules/node.views.inc +++ b/sites/all/modules/views/modules/node.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: node.views.inc,v 1.97.4.25 2010/12/27 08:02:28 dereine Exp $ /** * @file * Provide views data and handlers for node.module @@ -21,15 +20,17 @@ function node_views_data() { // Define the base group of this table. Fields that don't // have a group defined will go into this field by default. - $data['node']['table']['group'] = t('Node'); + $data['node']['table']['group'] = t('Content'); // Advertise this table as a possible base table $data['node']['table']['base'] = array( 'field' => 'nid', - 'title' => t('Node'), - 'help' => t("Nodes are a Drupal site's primary content."), + 'title' => t('Content'), 'weight' => -10, 'access query tag' => 'node_access', + 'defaults' => array( + 'field' => 'title', + ), ); // For other base tables, explain how we join @@ -56,7 +57,7 @@ function node_views_data() { // nid $data['node']['nid'] = array( 'title' => t('Nid'), - 'help' => t('The node ID of the node.'), // The help that appears on the UI, + 'help' => t('The node ID.'), // The help that appears on the UI, // Information for displaying the nid 'field' => array( 'handler' => 'views_handler_field_node', @@ -83,13 +84,14 @@ function node_views_data() { // This definition has more items in it than it needs to as an example. $data['node']['title'] = array( 'title' => t('Title'), // The item it appears as on the UI, - 'help' => t('The title of the node.'), // The help that appears on the UI, + 'help' => t('The content title.'), // The help that appears on the UI, // Information for displaying a title as a field 'field' => array( 'field' => 'title', // the real field. This could be left out since it is the same. - 'group' => t('Node'), // The group it appears in on the UI. Could be left out. + 'group' => t('Content'), // The group it appears in on the UI. Could be left out. 'handler' => 'views_handler_field_node', 'click sortable' => TRUE, + 'link_to_node default' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort', @@ -106,7 +108,7 @@ function node_views_data() { // created field $data['node']['created'] = array( 'title' => t('Post date'), // The item it appears as on the UI, - 'help' => t('The date the node was posted.'), // The help that appears on the UI, + 'help' => t('The date the content was posted.'), // The help that appears on the UI, 'field' => array( 'handler' => 'views_handler_field_date', 'click sortable' => TRUE, @@ -122,7 +124,7 @@ function node_views_data() { // changed field $data['node']['changed'] = array( 'title' => t('Updated date'), // The item it appears as on the UI, - 'help' => t('The date the node was last updated.'), // The help that appears on the UI, + 'help' => t('The date the content was last updated.'), // The help that appears on the UI, 'field' => array( 'handler' => 'views_handler_field_date', 'click sortable' => TRUE, @@ -135,10 +137,10 @@ function node_views_data() { ), ); - // Node type + // Content type $data['node']['type'] = array( 'title' => t('Type'), // The item it appears as on the UI, - 'help' => t('The type of a node (for example, "blog entry", "forum post", "story", etc).'), // The help that appears on the UI, + 'help' => t('The content type (for example, "blog entry", "forum post", "story", etc).'), // The help that appears on the UI, 'field' => array( 'handler' => 'views_handler_field_node_type', 'click sortable' => TRUE, @@ -157,7 +159,7 @@ function node_views_data() { // published status $data['node']['status'] = array( 'title' => t('Published'), - 'help' => t('Whether or not the node is published.'), + 'help' => t('Whether or not the content is published.'), 'field' => array( 'handler' => 'views_handler_field_boolean', 'click sortable' => TRUE, @@ -179,7 +181,7 @@ function node_views_data() { // published status + extra $data['node']['status_extra'] = array( 'title' => t('Published or admin'), - 'help' => t('Filters out unpublished nodes if the current user cannot view them.'), + 'help' => t('Filters out unpublished content if the current user cannot view it.'), 'filter' => array( 'field' => 'status', 'handler' => 'views_handler_filter_node_status', @@ -190,7 +192,7 @@ function node_views_data() { // promote status $data['node']['promote'] = array( 'title' => t('Promoted to front page'), - 'help' => t('Whether or not the node is promoted to the front page.'), + 'help' => t('Whether or not the content is promoted to the front page.'), 'field' => array( 'handler' => 'views_handler_field_boolean', 'click sortable' => TRUE, @@ -208,7 +210,7 @@ function node_views_data() { // sticky $data['node']['sticky'] = array( 'title' => t('Sticky'), // The item it appears as on the UI, - 'help' => t('Whether or not the node is sticky.'), // The help that appears on the UI, + 'help' => t('Whether or not the content is sticky.'), // The help that appears on the UI, // Information for displaying a title as a field 'field' => array( 'handler' => 'views_handler_field_boolean', @@ -224,7 +226,7 @@ function node_views_data() { ), 'sort' => array( 'handler' => 'views_handler_sort', - 'help' => t('Whether or not the node is sticky. To list sticky nodes first, set this to descending.'), + 'help' => t('Whether or not the content is sticky. To list sticky content first, set this to descending.'), ), ); @@ -233,7 +235,7 @@ function node_views_data() { $data['node']['view_node'] = array( 'field' => array( 'title' => t('Link'), - 'help' => t('Provide a simple link to the node.'), + 'help' => t('Provide a simple link to the content.'), 'handler' => 'views_handler_field_node_link', ), ); @@ -241,7 +243,7 @@ function node_views_data() { $data['node']['edit_node'] = array( 'field' => array( 'title' => t('Edit link'), - 'help' => t('Provide a simple link to edit the node.'), + 'help' => t('Provide a simple link to edit the content.'), 'handler' => 'views_handler_field_node_link_edit', ), ); @@ -249,7 +251,7 @@ function node_views_data() { $data['node']['delete_node'] = array( 'field' => array( 'title' => t('Delete link'), - 'help' => t('Provide a simple link to delete the node.'), + 'help' => t('Provide a simple link to delete the content.'), 'handler' => 'views_handler_field_node_link_delete', ), ); @@ -257,7 +259,7 @@ function node_views_data() { $data['node']['path'] = array( 'field' => array( 'title' => t('Path'), - 'help' => t('The aliased path to this node.'), + 'help' => t('The aliased path to this content.'), 'handler' => 'views_handler_field_node_path', ), ); @@ -376,7 +378,7 @@ function node_views_data() { // uid field $data['node']['uid'] = array( 'title' => t('Author'), - 'help' => t('Relate a node to the user who created it.'), + 'help' => t('Relate content to the user who created it.'), 'relationship' => array( 'handler' => 'views_handler_relationship', 'base' => 'users', @@ -385,18 +387,36 @@ function node_views_data() { ), ); + $data['node']['uid_revision'] = array( + 'title' => t('User has a revision'), + 'help' => t('All nodes where a certain user has a revision'), + 'real field' => 'nid', + 'filter' => array( + 'handler' => 'views_handler_filter_node_uid_revision', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_node_uid_revision', + ), + ); + // ---------------------------------------------------------------------- - // Node revision table + // Content revision table // Define the base group of this table. Fields that don't // have a group defined will go into this field by default. - $data['node_revision']['table']['group'] = t('Node revision'); + $data['node_revisions']['moved to'] = 'node_revision'; + $data['node_revision']['table']['group'] = t('Content revision'); + // Support the conversion of the field body + $data['node_revisions']['body']['moved to'] = array('field_revision_data', 'body-revision_id'); // Advertise this table as a possible base table $data['node_revision']['table']['base'] = array( 'field' => 'vid', - 'title' => t('Node revision'), - 'help' => t('Node revision are a history of changes to nodes.'), + 'title' => t('Content revision'), + 'help' => t('Content revision is a history of changes to content.'), + 'defaults' => array( + 'field' => 'title', + ), ); // For other base tables, explain how we join @@ -411,7 +431,7 @@ function node_views_data() { // uid field for node revision $data['node_revision']['uid'] = array( 'title' => t('User'), - 'help' => t('Relate a node revision to the user who created the revision.'), + 'help' => t('Relate a content revision to the user who created the revision.'), 'relationship' => array( 'handler' => 'views_handler_relationship', 'base' => 'users', @@ -423,7 +443,7 @@ function node_views_data() { // nid $data['node_revision']['vid'] = array( 'title' => t('Vid'), - 'help' => t('The revision ID of the node revision.'), // The help that appears on the UI, + 'help' => t('The revision ID of the content revision.'), // The help that appears on the UI, // Information for displaying the nid 'field' => array( 'click sortable' => TRUE, @@ -446,15 +466,15 @@ function node_views_data() { 'handler' => 'views_handler_relationship', 'base' => 'node', 'base field' => 'nid', - 'title' => t('Node'), - 'label' => t('Get the actual node from a node revision.'), + 'title' => t('Content'), + 'label' => t('Get the actual content from a content revision.'), ), ); // title $data['node_revision']['title'] = array( 'title' => t('Title'), // The item it appears as on the UI, - 'help' => t('The title of the node.'), // The help that appears on the UI, + 'help' => t('The content title.'), // The help that appears on the UI, // Information for displaying a title as a field 'field' => array( 'field' => 'title', // the real field @@ -489,7 +509,7 @@ function node_views_data() { // changed field $data['node_revision']['timestamp'] = array( 'title' => t('Created date'), // The item it appears as on the UI, - 'help' => t('The date the node revision was created.'), // The help that appears on the UI, + 'help' => t('The date the content revision was created.'), // The help that appears on the UI, 'field' => array( 'handler' => 'views_handler_field_date', 'click sortable' => TRUE, @@ -513,7 +533,7 @@ function node_views_data() { $data['node_revision']['delete_revision'] = array( 'field' => array( 'title' => t('Delete link'), - 'help' => t('Provide a simple link to delete the node revision.'), + 'help' => t('Provide a simple link to delete the content revision.'), 'handler' => 'views_handler_field_node_revision_link_delete', ), ); @@ -523,7 +543,7 @@ function node_views_data() { // Define the base group of this table. Fields that don't // have a group defined will go into this field by default. - $data['node_access']['table']['group'] = t('Node access'); + $data['node_access']['table']['group'] = t('Content access'); // For other base tables, explain how we join $data['node_access']['table']['join'] = array( @@ -539,7 +559,7 @@ function node_views_data() { 'help' => t('Filter by access.'), 'filter' => array( 'handler' => 'views_handler_filter_node_access', - 'help' => t('Filter for nodes by view access. <strong>Not necessary if you are using node as your base table.</strong>'), + 'help' => t('Filter for content by view access. <strong>Not necessary if you are using node as your base table.</strong>'), ), ); @@ -549,7 +569,8 @@ function node_views_data() { // We're actually defining a specific instance of the table, so let's // alias it so that we can later add the real table for other purposes if we // need it. - $data['history']['table']['group'] = t('Node'); + $data['history_user']['moved to'] = 'history'; + $data['history']['table']['group'] = t('Content'); // Explain how this table joins to others. $data['history']['table']['join'] = array( @@ -568,10 +589,10 @@ function node_views_data() { 'title' => t('Has new content'), 'field' => array( 'handler' => 'views_handler_field_history_user_timestamp', - 'help' => t('Show a marker if the node has new or updated content.'), + 'help' => t('Show a marker if the content is new or updated.'), ), 'filter' => array( - 'help' => t('Show only nodes that have new content.'), + 'help' => t('Show only content that is new or updated.'), 'handler' => 'views_handler_filter_history_user_timestamp', ), ); @@ -579,15 +600,15 @@ function node_views_data() { } /** - * Implements hook_views_plugins + * Implements hook_views_plugins(). */ function node_views_plugins() { return array( 'module' => 'views', // This just tells our themes are elsewhere. 'row' => array( 'node' => array( - 'title' => t('Node'), - 'help' => t('Display the node with standard node view.'), + 'title' => t('Content'), + 'help' => t('Display the content with standard node view.'), 'handler' => 'views_plugin_row_node_view', 'path' => drupal_get_path('module', 'views') . '/modules/node', // not necessary for most modules 'theme' => 'views_view_row_node', @@ -597,8 +618,8 @@ function node_views_plugins() { 'help topic' => 'style-node', ), 'node_rss' => array( - 'title' => t('Node'), - 'help' => t('Display the node with standard node view.'), + 'title' => t('Content'), + 'help' => t('Display the content with standard node view.'), 'handler' => 'views_plugin_row_node_rss', 'path' => drupal_get_path('module', 'views') . '/modules/node', // not necessary for most modules 'theme' => 'views_view_row_rss', @@ -610,13 +631,13 @@ function node_views_plugins() { ), 'argument validator' => array( 'node' => array( - 'title' => t('Node'), + 'title' => t('Content'), 'handler' => 'views_plugin_argument_validate_node', ), ), 'argument default' => array( 'node' => array( - 'title' => t('Node ID from URL'), + 'title' => t('Content ID from URL'), 'handler' => 'views_plugin_argument_default_node' ), ), @@ -649,15 +670,16 @@ function template_preprocess_views_view_row_node(&$vars) { $node->view = $vars['view']; // Detect which build module should be used. - $node->build_mode = (!empty($options['build_mode'])) ? $options['build_mode'] : 'full'; - $content = node_view_multiple(array($node->nid => $node), $node->build_mode); + $node->view_mode = (!empty($options['view_mode'])) ? $options['view_mode'] : 'full'; + $content = node_view_multiple(array($node->nid => $node), $node->view_mode); $content = $content['nodes'][$node->nid]; if (!$options['links']) { unset($content['links']); } if (!empty($options['comments']) && user_access('access comments') && $node->comment) { - $vars['comments'] = drupal_render(comment_node_page_additions($node)); + $build = comment_node_page_additions($node); + $vars['comments'] = drupal_render($build); } $vars['node'] = drupal_render($content); @@ -693,7 +715,7 @@ function node_views_analyze($view) { ->condition('r.name', array('anonymous user', 'authenticated user'), 'IN') ->condition('p.permission', 'access content') ->execute(); - + foreach ($result as $role) { $role->safe = TRUE; $roles[$role->name] = $role; diff --git a/sites/all/modules/views/modules/node.views_convert.inc b/sites/all/modules/views/modules/node.views_convert.inc index a31198fda3eac8137c04e8ce758656b6fa1cf8af..2d3ea948d3d1af9f8dfa8a06265e83385dd2602d 100644 --- a/sites/all/modules/views/modules/node.views_convert.inc +++ b/sites/all/modules/views/modules/node.views_convert.inc @@ -1,5 +1,4 @@ <?php -//$Id: node.views_convert.inc,v 1.7.4.2 2010/02/06 16:29:52 dereine Exp $ /** * @file diff --git a/sites/all/modules/views/modules/node.views_default.inc b/sites/all/modules/views/modules/node.views_default.inc index 4c8ae67017401fda8e8323fd094effba5e0312be..ab71d62f7eeda9e8a1aee22ebfc8701a6dd2532c 100644 --- a/sites/all/modules/views/modules/node.views_default.inc +++ b/sites/all/modules/views/modules/node.views_default.inc @@ -1,5 +1,4 @@ <?php -// $Id: node.views_default.inc,v 1.11.6.5 2011/01/05 23:14:39 dereine Exp $ /** * @file * Contains default views on behalf of the node module. @@ -14,10 +13,11 @@ function node_views_default_views() { $view->description = 'Emulates the default Drupal front page; you may set the default home page path to this view to make it your front page.'; $view->tag = 'default'; $view->base_table = 'node'; + $view->human_name = 'Front page'; $view->api_version = 2; $view->version = 7; $view->disabled = TRUE; /* Edit this to true to make a default view disabled initially */ - $handler = $view->new_display('default', 'Defaults', 'default'); + $handler = $view->new_display('default', 'Master', 'default'); $handler->override_option('sorts', array( 'sticky' => array( 'id' => 'sticky', @@ -120,10 +120,11 @@ function node_views_default_views() { $view->description = 'A list of all content, by letter.'; $view->tag = 'default'; $view->base_table = 'node'; + $view->human_name = 'Glossary'; $view->api_version = 2; $view->version = 7; $view->disabled = TRUE; /* Edit this to true to make a default view disabled initially */ - $handler = $view->new_display('default', 'Defaults', 'default'); + $handler = $view->new_display('default', 'Master', 'default'); $handler->override_option('fields', array( 'title' => array( 'label' => 'Title', @@ -276,10 +277,11 @@ function node_views_default_views() { $view->description = 'Display a list of months that link to content for that month.'; $view->tag = 'default'; $view->base_table = 'node'; + $view->human_name = 'Archive'; $view->api_version = 2; $view->version = 7; $view->disabled = TRUE; /* Edit this to true to make a default view disabled initially */ - $handler = $view->new_display('default', 'Defaults', 'default'); + $handler = $view->new_display('default', 'Master', 'default'); $handler->override_option('title', 'Monthly archive'); $handler->override_option('sorts', array( 'created' => array( diff --git a/sites/all/modules/views/modules/node/views_handler_argument_dates_various.inc b/sites/all/modules/views/modules/node/views_handler_argument_dates_various.inc index 33a7e738791c0306a47fd495fa8ea2203b486f49..7171581fe1c507f6b3d1cb29f4abbb011d0eb1ec 100644 --- a/sites/all/modules/views/modules/node/views_handler_argument_dates_various.inc +++ b/sites/all/modules/views/modules/node/views_handler_argument_dates_various.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_dates_various.inc,v 1.4.6.3 2010/09/19 08:18:11 dereine Exp $ /** * Argument handler for a full date (CCYYMMDD) */ diff --git a/sites/all/modules/views/modules/node/views_handler_argument_node_language.inc b/sites/all/modules/views/modules/node/views_handler_argument_node_language.inc index fad8680c32bd41cdb3d0ac2ceaaef75ebb6466a6..85ff6c8e7d5669a4004ec42986c0b8f507aede6a 100644 --- a/sites/all/modules/views/modules/node/views_handler_argument_node_language.inc +++ b/sites/all/modules/views/modules/node/views_handler_argument_node_language.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_node_language.inc,v 1.1 2008/09/03 19:21:29 merlinofchaos Exp $ /** * Argument handler to accept a language. */ diff --git a/sites/all/modules/views/modules/node/views_handler_argument_node_nid.inc b/sites/all/modules/views/modules/node/views_handler_argument_node_nid.inc index 4b51049083de23d605d69b8356f4bb7e8b302cc8..72a739f5a56a9ce5b9bbbb9fa92189612e8eb53a 100644 --- a/sites/all/modules/views/modules/node/views_handler_argument_node_nid.inc +++ b/sites/all/modules/views/modules/node/views_handler_argument_node_nid.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_node_nid.inc,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * @file * Provide node nid argument handler. diff --git a/sites/all/modules/views/modules/node/views_handler_argument_node_type.inc b/sites/all/modules/views/modules/node/views_handler_argument_node_type.inc index 04aa7e0dcb1c2ff48f6126bfbf72c487fb05b67e..638973de3e468de9b90c0042fc3f982b05b87510 100644 --- a/sites/all/modules/views/modules/node/views_handler_argument_node_type.inc +++ b/sites/all/modules/views/modules/node/views_handler_argument_node_type.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_node_type.inc,v 1.2.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * Argument handler to accept a node type. */ @@ -27,7 +26,7 @@ class views_handler_argument_node_type extends views_handler_argument { function node_type($type) { $output = node_type_get_name($type); if (empty($output)) { - $output = t('Unknown node type'); + $output = t('Unknown content type'); } return check_plain($output); } diff --git a/sites/all/modules/views/modules/node/views_handler_argument_node_uid_revision.inc b/sites/all/modules/views/modules/node/views_handler_argument_node_uid_revision.inc new file mode 100644 index 0000000000000000000000000000000000000000..7ade1f98f3f3046075a842c19ca1ceccf7b1cf52 --- /dev/null +++ b/sites/all/modules/views/modules/node/views_handler_argument_node_uid_revision.inc @@ -0,0 +1,14 @@ +<?php +// $Id$ + +/** + * Filter handler to accept a user id to check for nodes that + * user posted or created a revision on. + */ +class views_handler_filter_node_uid_revision extends views_handler_argument_comment_user_uid { + function query() { + $this->ensure_my_table(); + $placeholder = $this->placeholder(); + $this->query->add_where_expression(0, "$this->table_alias.uid = $placeholder OR ((SELECT COUNT(*) FROM {node_revision} nr WHERE nr.uid = $placeholder AND nr.nid = $this->table_alias.nid) > 0)", array($placeholder => $this->argument)); + } +} diff --git a/sites/all/modules/views/modules/node/views_handler_argument_node_vid.inc b/sites/all/modules/views/modules/node/views_handler_argument_node_vid.inc index 4a20d5809cc691073d8829f222a3593447a7b1dc..88f110dbdc88f44c9894312be08df7a93e28a15b 100644 --- a/sites/all/modules/views/modules/node/views_handler_argument_node_vid.inc +++ b/sites/all/modules/views/modules/node/views_handler_argument_node_vid.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_node_vid.inc,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * @file * Provide node vid argument handler. 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 5d11c7e055b451778a433fe1f427fe30174d5dc4..196d443cac30f78e71b67ad7e80f3a9690888d5f 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_history_user_timestamp.inc,v 1.1.6.3 2010/08/26 09:41:55 dereine Exp $ /** * Field handler to display the marker for new content. * @@ -33,6 +32,7 @@ class views_handler_field_history_user_timestamp extends views_handler_field_nod '#type' => 'checkbox', '#title' => t('Check for new comments as well'), '#default_value' => !empty($this->options['comments']), + '#fieldset' => 'more', ); } } @@ -53,11 +53,11 @@ class views_handler_field_history_user_timestamp extends views_handler_field_nod $mark = MARK_READ; global $user; if ($user->uid) { - $last_read = $values->{$this->field_alias}; - $created = $values->{$this->aliases['created']}; - $changed = $values->{$this->aliases['changed']}; + $last_read = $this->get_value($values); + $created = $this->get_value($values, 'created'); + $changed = $this->get_value($values, 'changed'); - $last_comment = module_exists('comment') && !empty($this->options['comments']) ? $values->{$this->aliases['last_comment']} : 0; + $last_comment = module_exists('comment') && !empty($this->options['comments']) ? $this->get_value($values, 'last_comment') : 0; if (!$last_read && $created > NODE_NEW_LIMIT) { $mark = MARK_NEW; 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 b405b0d8c42a21ad21efa1ae5083ee0311105a7e..dd07b6c7120455c7b3d9d57fad220ea547fd1a0c 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_node.inc,v 1.7.4.8 2010/11/18 23:32:04 merlinofchaos Exp $ /** * @file * Contains the basic 'node' field handler. @@ -7,6 +6,8 @@ /** * 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. */ class views_handler_field_node extends views_handler_field { @@ -22,7 +23,7 @@ class views_handler_field_node extends views_handler_field { function option_definition() { $options = parent::option_definition(); - $options['link_to_node'] = array('default' => TRUE); + $options['link_to_node'] = array('default' => isset($this->definition['link_to_node default']) ? $this->definition['link_to_node default'] : FALSE); return $options; } @@ -30,13 +31,14 @@ class views_handler_field_node extends views_handler_field { * Provide link to node option */ function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['link_to_node'] = array( - '#title' => t('Link this field to its node'), - '#description' => t('This will override any other link you have set.'), + '#title' => t('Link this field to the original piece of content'), + '#description' => t("Enable to override this field's links."), '#type' => 'checkbox', '#default_value' => !empty($this->options['link_to_node']), ); + + parent::options_form($form, $form_state); } /** @@ -48,11 +50,12 @@ class views_handler_field_node extends views_handler_field { if (!empty($this->options['link_to_node'])) { if ($data !== NULL && $data !== '') { $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = "node/" . $values->{$this->aliases['nid']}; + $this->options['alter']['path'] = "node/" . $this->get_value($values, 'nid'); if (isset($this->aliases['language'])) { $languages = language_list(); - if (isset($languages[$values->{$this->aliases['language']}])) { - $this->options['alter']['language'] = $languages[$values->{$this->aliases['language']}]; + $language = $this->get_value($values, 'language'); + if (isset($languages[$language])) { + $this->options['alter']['language'] = $languages[$language]; } else { unset($this->options['alter']['language']); @@ -61,12 +64,13 @@ class views_handler_field_node extends views_handler_field { } else { $this->options['alter']['make_link'] = FALSE; - } + } } return $data; } function render($values) { - return $this->render_link(check_plain($values->{$this->field_alias}), $values); + $value = $this->get_value($values); + return $this->render_link($this->sanitize_value($value), $values); } } 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 c75569ddfcd6b259f2cd2a8ef55e3984f991ee07..c9339ace9352f6a57c87ac2bee527d140d5351f9 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,5 +1,4 @@ <?php -// $Id: views_handler_field_node_link.inc,v 1.1.6.2 2010/11/30 20:36:01 merlinofchaos Exp $ /** * Field handler to present a link to the node. */ @@ -18,12 +17,12 @@ class views_handler_field_node_link extends views_handler_field { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['text'] = array( '#type' => 'textfield', '#title' => t('Text to display'), '#default_value' => $this->options['text'], ); + parent::options_form($form, $form_state); } function query() { @@ -32,13 +31,13 @@ class views_handler_field_node_link extends views_handler_field { } function render($values) { - return $this->render_link(check_plain($values->{$this->aliases['nid']}), $values); + $value = $this->get_value($values, 'nid'); + return $this->render_link($this->sanitize_value($value), $values); } function render_link($data, $values) { - $nid = $values->{$this->aliases['nid']}; $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = "node/$nid"; + $this->options['alter']['path'] = "node/$data"; $text = !empty($this->options['text']) ? $this->options['text'] : t('view'); return $text; } 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 fb2771acd41bb3d8b0ed59fd8da17b91968cecfb..caf7439b634d7baf0ac0899fb08d507de4fe5f57 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,5 +1,4 @@ <?php -// $Id: views_handler_field_node_link_delete.inc,v 1.1.6.2 2010/11/18 07:29:03 dereine Exp $ /** * Field handler to present a link to delete a node. */ @@ -13,9 +12,9 @@ class views_handler_field_node_link_delete extends views_handler_field_node_link function render_link($data, $values) { // ensure user has access to edit this node. $node = new stdClass(); - $node->nid = $values->{$this->aliases['nid']}; - $node->uid = $values->{$this->aliases['uid']}; - $node->type = $values->{$this->aliases['type']}; + $node->nid = $this->get_value($values, 'nid'); + $node->uid = $this->get_value($values, 'uid'); + $node->type = $this->get_value($values, 'type'); $node->status = 1; // unpublished nodes ignore access control if (!node_access('delete', $node)) { return; @@ -29,4 +28,3 @@ class views_handler_field_node_link_delete extends views_handler_field_node_link return $text; } } - 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 e137b67be3bfbaef5685eb64b25d0a576e0ebe01..687412fac7e9ebd660515dafb2658660d36e5c9d 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,5 +1,4 @@ <?php -// $Id: views_handler_field_node_link_edit.inc,v 1.1.6.2 2010/11/18 07:29:03 dereine Exp $ /** * Field handler to present a link node edit. */ @@ -13,9 +12,9 @@ class views_handler_field_node_link_edit extends views_handler_field_node_link { function render_link($data, $values) { // ensure user has access to edit this node. $node = new stdClass(); - $node->nid = $values->{$this->aliases['nid']}; - $node->uid = $values->{$this->aliases['uid']}; - $node->type = $values->{$this->aliases['type']}; + $node->nid = $this->get_value($values, 'nid'); + $node->uid = $this->get_value($values, 'uid'); + $node->type = $this->get_value($values, 'type'); $node->status = 1; // unpublished nodes ignore access control if (!node_access('update', $node)) { return; @@ -29,4 +28,3 @@ class views_handler_field_node_link_edit extends views_handler_field_node_link { return $text; } } - 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 3924d2779c67cfdb9b4cce502e13742496b4cd59..b0cc5fb8cc4c77702249c245f7560ce280679749 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 @@ -1,5 +1,10 @@ <?php -// $Id: + +/** + * @file + * Handler for node path field. + */ + /** * Field handler to present the path to the node. */ @@ -23,7 +28,8 @@ class views_handler_field_node_path extends views_handler_field { '#type' => 'checkbox', '#title' => t('Use absolute link (begins with "http://")'), '#default_value' => $this->options['absolute'], - '#description' => t('If you want to use this as in "output this field as link" in "link path", you have to enabled this option.'), + '#description' => t('Enable this option to output an absolute link. Required if you want to use the path as a link destination (as in "output this field as a link" above).'), + '#fieldset' => 'alter', ); } @@ -33,7 +39,7 @@ class views_handler_field_node_path extends views_handler_field { } function render($values) { - $nid = $values->{$this->aliases['nid']}; + $nid = $this->get_value($values, 'nid'); return url("node/$nid", array('absolute' => $this->options['absolute'])); } } 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 e8ca371fd68e7291766a23e638ced475081db0d9..f4ca17d45e0f257bf064bed6ecb9e82da5b97dbc 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,5 +1,4 @@ <?php -// $Id: views_handler_field_node_revision.inc,v 1.1.6.3 2010/08/26 09:41:55 dereine Exp $ /** * @file * Contains the basic 'node_revision' field handler. @@ -26,13 +25,13 @@ class views_handler_field_node_revision extends views_handler_field_node { * Provide link to revision option. */ function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['link_to_node_revision'] = array( - '#title' => t('Link this field to its node revision'), + '#title' => t('Link this field to its content revision'), '#description' => t('This will override any other link you have set.'), '#type' => 'checkbox', '#default_value' => !empty($this->options['link_to_node_revision']), ); + parent::options_form($form, $form_state); } /** @@ -43,11 +42,14 @@ class views_handler_field_node_revision extends views_handler_field_node { function render_link($data, $values) { if (!empty($this->options['link_to_node_revision']) && $data !== NULL && $data !== '') { $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = "node/" . $values->{$this->aliases['nid']} . '/revisions/' . $values->{$this->aliases['vid']} .'/view'; - if (isset($this->aliases['language'])) { + $nid = $this->get_value($values, 'nid'); + $vid = $this->get_value($values, 'vid'); + $this->options['alter']['path'] = "node/" . $nid . '/revisions/' . $vid . '/view'; + if (module_exists('translation')) { + $language = $this->get_value($values, 'language'); $languages = language_list(); - if (isset($languages[$values->{$this->aliases['language']}])) { - $this->options['alter']['language'] = $languages[$values->{$this->aliases['language']}]; + if (isset($languages[$language])) { + $this->options['alter']['language'] = $languages[$language]; } } } @@ -57,4 +59,3 @@ class views_handler_field_node_revision extends views_handler_field_node { return $data; } } - 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 de9c36105ebdcee3d001927aa757b5555cb57991..031fe3e47a83076d39409383203ff121bcc108dd 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,5 +1,4 @@ <?php -// $Id: views_handler_field_node_revision_link_delete.inc,v 1.1.6.2 2010/11/18 07:29:03 dereine Exp $ /** * Field handler to present delete a node revision. */ @@ -18,16 +17,16 @@ 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 = $values->{$this->aliases['nid']}; - $node->vid = $values->{$this->aliases['vid']}; - $node->uid = $values->{$this->aliases['uid']}; + $node->nid = $this->get_value($values, 'nid'); + $node->uid = $this->get_value($values, 'uid'); + $node->type = $this->get_value($values, 'type'); $node->status = 1; // unpublished nodes ignore access control if (!node_access('delete', $node)) { return; } // Current revision cannot be deleted. - if ($node->vid == $values->{$this->aliases['node_vid']}) { + if ($node->vid == $this->get_value($values, 'node_vid')) { 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 4e2fc757bceaf9418e8c5b5390ac2fecfb96b613..a7fcb737119cb34a935408c5a9db9d0946db3acc 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,5 +1,4 @@ <?php -// $Id: views_handler_field_node_revision_link_revert.inc,v 1.1.6.2 2010/11/18 07:29:03 dereine Exp $ /** * Field handler to present a link to revert a node to a revision */ @@ -18,16 +17,16 @@ 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 = $values->{$this->aliases['nid']}; - $node->vid = $values->{$this->aliases['vid']}; - $node->uid = $values->{$this->aliases['uid']}; + $node->nid = $this->get_value($values, 'nid'); + $node->vid = $this->get_value($values, 'vid'); + $node->uid = $this->get_value($values, 'uid'); $node->status = 1; // unpublished nodes ignore access control if (!node_access('update', $node)) { return; } // Current revision cannot be reverted. - if ($node->vid == $values->{$this->aliases['node_vid']}) { + if ($node->vid == $this->get_value($values, 'node_vid')) { 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 038fa004a84b58cfbcf67899db8ad8351e9fec91..3c8f66f188bed765c8af0a2b93d89182effb01c6 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_node_type.inc,v 1.2.4.4 2010/04/29 18:33:29 merlinofchaos Exp $ /** * Field handler to translate a node type into its readable form. @@ -17,11 +16,13 @@ class views_handler_field_node_type extends views_handler_field_node { */ 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 the node type machine name.'), + '#description' => t('Display field as the content type machine name.'), '#type' => 'checkbox', '#default_value' => !empty($this->options['machine_name']), + '#fieldset' => 'more', ); } @@ -30,13 +31,13 @@ class views_handler_field_node_type extends views_handler_field_node { */ function render_name($data, $values) { if ($this->options['machine_name'] != 1 && $data !== NULL && $data !== '') { - return t(check_plain(node_type_get_name($data))); + return t($this->sanitize_value(node_type_get_name($data))); } - return check_plain($data); + return $this->sanitize_value($data); } function render($values) { - return $this->render_link($this->render_name($values->{$this->field_alias}, $values), $values); + $value = $this->get_value($values); + return $this->render_link($this->render_name($value, $values), $values); } } - 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 04219e6d94b66ca76920e96b0411a6b5ec5772de..f725b4c8f5efefef1e3f2675906b38cd5d1bc834 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_history_user_timestamp.inc,v 1.3.4.4 2010/12/25 22:03:47 dereine Exp $ /** * Filter for new content * @@ -9,8 +8,12 @@ class views_handler_filter_history_user_timestamp extends views_handler_filter { // Don't display empty space where the operator would be. var $no_operator = TRUE; - function expose_form_right() { - // We don't want any of the usual options for exposed filters. + function expose_form(&$form, &$form_state) { + parent::expose_form($form, $form_state); + // @todo There are better ways of excluding required and multiple (object flags) + unset($form['expose']['required']); + unset($form['expose']['multiple']); + unset($form['expose']['remember']); } function value_form(&$form, &$form_state) { @@ -53,6 +56,8 @@ class views_handler_filter_history_user_timestamp extends views_handler_filter { $field = "$this->table_alias.$this->real_field"; $node = $this->query->ensure_table('node', $this->relationship); + $clause = ''; + $clause2 = ''; if (module_exists('comment')) { $ncs = $this->query->ensure_table('node_comment_statistics', $this->relationship); $clause = ("OR $ncs.last_comment_timestamp > (***CURRENT_TIME*** - $limit)"); @@ -62,7 +67,7 @@ class views_handler_filter_history_user_timestamp extends views_handler_filter { // NULL means a history record doesn't exist. That's clearly new content. // Unless it's very very old content. Everything in the query is already // type safe cause none of it is coming from outside here. - $this->query->add_where($this->options['group'], "($field IS NULL AND ($node.changed > (***CURRENT_TIME*** - $limit) $clause)) OR $field < $node.changed $clause2", array(), 'formula'); + $this->query->add_where_expression($this->options['group'], "($field IS NULL AND ($node.changed > (***CURRENT_TIME*** - $limit) $clause)) OR $field < $node.changed $clause2"); } function admin_summary() { 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 0ae2a62b2155566ae2b54b967f0ed27a6c744ee4..333b9b2b96e731fa60916491cd15e2c2a6225f47 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,5 +1,4 @@ <?php -// $Id: views_handler_filter_node_access.inc,v 1.2.4.2 2010/08/26 09:41:55 dereine Exp $ /** * Filter by node_access records. */ 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 634ac690e271e2201e0b442015ebafa4dda9e76c..2b79b9e9548472655531c66a3a8c7b06b410c6c7 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,14 +1,14 @@ <?php -// $Id: views_handler_filter_node_status.inc,v 1.2.4.6 2010/11/18 00:43:18 merlinofchaos Exp $ /** * Filter by published status */ class views_handler_filter_node_status extends views_handler_filter { function admin_summary() { } function operator_form(&$form, &$form_state) { } + function can_expose() { return FALSE; } function query() { $table = $this->ensure_my_table(); - $this->query->add_where($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", array(), 'formula'); + $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"); } } 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 5c543429a276d87ce136cb95481d891bba8b13d0..8232c99078efae3ca787de3b7fa890f5da5138ea 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,12 +1,11 @@ <?php -// $Id: views_handler_filter_node_type.inc,v 1.2.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * Filter by node type */ class views_handler_filter_node_type extends views_handler_filter_in_operator { function get_value_options() { if (!isset($this->value_options)) { - $this->value_title = t('Node type'); + $this->value_title = t('Content types'); $types = node_type_get_types(); foreach ($types as $type => $info) { $options[$type] = t($info->name); 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 new file mode 100644 index 0000000000000000000000000000000000000000..c7d4512663d513fa6442573645177f67d0c8eea1 --- /dev/null +++ b/sites/all/modules/views/modules/node/views_handler_filter_node_uid_revision.inc @@ -0,0 +1,19 @@ +<?php +// $Id$ +/** + * @file + * Filter handler to check for revisions a certain user has created. + */ +class views_handler_filter_node_uid_revision extends views_handler_filter_user_name { + function query() { + $this->ensure_my_table(); + + $placeholder = $this->placeholder(); + + $args = array_values($this->value); + + $this->query->add_where_expression($this->options['group'], "$this->table_alias.uid IN($placeholder) " . $condition . " OR + ((SELECT COUNT(*) FROM {node_revision} nr WHERE nr.uid IN($placeholder) AND nr.nid = $this->table_alias.nid) > 0)", array($placeholder => $args), + $args); + } +} diff --git a/sites/all/modules/views/modules/node/views_plugin_argument_default_node.inc b/sites/all/modules/views/modules/node/views_plugin_argument_default_node.inc index 6fc68d0071d93fa7165f2ee34f73f0ce72ea34d5..276c7fef6ef84930135326d4de68527a7348d5ef 100644 --- a/sites/all/modules/views/modules/node/views_plugin_argument_default_node.inc +++ b/sites/all/modules/views/modules/node/views_plugin_argument_default_node.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_default_node.inc,v 1.1.6.1 2010/01/28 22:44:36 dereine Exp $ /** * @file * Contains the node from URL argument default plugin. diff --git a/sites/all/modules/views/modules/node/views_plugin_argument_validate_node.inc b/sites/all/modules/views/modules/node/views_plugin_argument_validate_node.inc index 8d3779f4cee2c7a4f9c780313ae409e3bdc4f51f..ead008b5093c1a57840d74bc4172ca3e8fdab00f 100644 --- a/sites/all/modules/views/modules/node/views_plugin_argument_validate_node.inc +++ b/sites/all/modules/views/modules/node/views_plugin_argument_validate_node.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_validate_node.inc,v 1.2.4.3 2010/05/15 08:11:14 dereine Exp $ /** * @file * Contains the 'node' argument validator plugin. @@ -13,6 +12,7 @@ class views_plugin_argument_validate_node extends views_plugin_argument_validate $options = parent::option_definition(); $options['types'] = array('default' => array()); $options['access'] = array('default' => FALSE); + $options['access_op'] = array('default' => 'view'); $options['nid_type'] = array('default' => 'nid'); return $options; @@ -26,21 +26,27 @@ class views_plugin_argument_validate_node extends views_plugin_argument_validate $form['types'] = array( '#type' => 'checkboxes', - '#title' => t('Types'), + '#title' => t('Content types'), '#options' => $options, '#default_value' => $this->options['types'], - '#description' => t('If you wish to validate for specific node types, check them; if none are checked, all nodes will pass.'), + '#description' => t('Choose one or more content types to validate with.'), ); $form['access'] = array( '#type' => 'checkbox', - '#title' => t('Validate user has access to the node'), + '#title' => t('Validate user has access to the content'), '#default_value' => $this->options['access'], ); + $form['access_op'] = array( + '#type' => 'radios', + '#title' => t('Access operation to check'), + '#options' => array('view' => t('View'), 'update' => t('Edit'), 'delete' => t('Delete')), + '#default_value' => $this->options['access_op'], + ); $form['nid_type'] = array( '#type' => 'select', - '#title' => t('Argument type'), + '#title' => t('Filter value format'), '#options' => array( 'nid' => t('Node ID'), 'nids' => t('Node IDs separated by , or +'), @@ -58,6 +64,7 @@ class views_plugin_argument_validate_node extends views_plugin_argument_validate if (!isset($options['types']) && !empty($this->argument->options['validate_argument_node_type'])) { $options['types'] = $this->argument->options['validate_argument_node_type']; $options['access'] = !empty($this->argument->options['validate_argument_node_access']); + $options['access_op'] = $this->argument->options['validate_argument_node_access_op']; $options['nid_type'] = isset($this->argument->options['validate_argument_nid_type']) ? $this->argument->options['validate_argument_nid_type'] : array(); } } @@ -76,7 +83,7 @@ class views_plugin_argument_validate_node extends views_plugin_argument_validate } if (!empty($this->options['access'])) { - if (!node_access('view', $node)) { + if (!node_access($this->options['access_op'], $node)) { return FALSE; } } @@ -93,7 +100,7 @@ class views_plugin_argument_validate_node extends views_plugin_argument_validate case 'nids': $nids = new stdClass(); $nids->value = array($argument); - $nids = views_nid_type($argument, $nids); + $nids = views_break_phrase($argument, $nids); if ($nids->value == -1) { return FALSE; } @@ -108,7 +115,7 @@ class views_plugin_argument_validate_node extends views_plugin_argument_validate } if (!empty($this->options['access'])) { - if (!node_access('view', $node)) { + if (!node_access($this->options['access_op'], $node)) { return FALSE; } } @@ -123,4 +130,3 @@ class views_plugin_argument_validate_node extends views_plugin_argument_validate } } } - 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 6c3f966c5965b74ffc56697ce20ac8378f710051..ac589b0e5ee80bfc707a3b13abfa93252ec2f5e8 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_row_node_rss.inc,v 1.7.4.7 2010/11/11 19:41:11 dereine Exp $ /** * @file * Contains the node RSS row style plugin. @@ -31,16 +30,29 @@ class views_plugin_row_node_rss extends views_plugin_row { $form['item_length'] = array( '#type' => 'select', '#title' => t('Display type'), - '#options' => array( - 'fulltext' => t('Full text'), - 'teaser' => t('Title plus teaser'), - 'title' => t('Title only'), - 'default' => t('Use default RSS settings'), - ), + '#options' => $this->options_form_summary_options(), '#default_value' => $this->options['item_length'], ); } + /** + * 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'), + ); + } + + function summary_title() { + $options = $this->options_form_summary_options(); + return check_plain($options[$this->options['item_length']]); + } + + function pre_render($values) { foreach ($values as $row) { $nids[] = $row->{$this->field_alias}; @@ -70,10 +82,10 @@ class views_plugin_row_node_rss extends views_plugin_row { $item_text = ''; - $node->rss_namespaces = array(); + $node->rss_namespaces = array('xmlns:dc' => 'http://purl.org/dc/elements/1.1/'); $node->rss_elements = array( array('key' => 'pubDate', 'value' => gmdate('r', $node->created)), - array('key' => 'dc:creator', 'value' => $node->name, 'namespace' => array('xmlns:dc' => 'http://purl.org/dc/elements/1.1/')), + array('key' => 'dc:creator', 'value' => $node->name), array('key' => 'guid', 'value' => $node->nid . ' at ' . $base_url, 'attributes' => array('isPermaLink' => 'false')) ); @@ -81,11 +93,7 @@ class views_plugin_row_node_rss extends views_plugin_row { // and $node->rss_namespaces. node_build_content($node, 'rss'); - foreach ($node->rss_elements as $element) { - if (isset($element['namespace'])) { - $this->view->style_plugin->namespaces = array_merge($this->view->style_plugin->namespaces, $element['namespace']); - } - } + $this->view->style_plugin->namespaces = array_merge($this->view->style_plugin->namespaces, $node->rss_namespaces); if ($item_length != 'title' && !empty($node->content)) { // We render node contents and force links to be last. @@ -93,6 +101,7 @@ class views_plugin_row_node_rss extends views_plugin_row { $item_text .= drupal_render($node->content) . $links; } + $item = new stdClass; $item->description = $item_text; $item->title = $node->title; $item->link = url("node/$node->nid", array('absolute' => TRUE)); 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 af70597714160cc96af5cb83beaa2b44a15ecd06..bff594987a76236b875733256f237bd162b6059a 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_row_node_view.inc,v 1.3.6.3 2010/12/03 11:26:09 dereine Exp $ /** * @file * Contains the node view row style plugin. @@ -24,12 +23,16 @@ class views_plugin_row_node_view extends views_plugin_row { if (isset($this->options['teaser'])) { $this->options['build_mode'] = $this->options['teaser'] ? 'teaser' : 'full'; } + // Handle existing views which has used build_mode instead of view_mode. + if (isset($this->options['build_mode'])) { + $this->options['view_mode'] = $this->options['build_mode']; + } } function option_definition() { $options = parent::option_definition(); - $options['build_mode'] = array('default' => 'teaser'); + $options['view_mode'] = array('default' => 'teaser'); $options['links'] = array('default' => TRUE); $options['comments'] = array('default' => FALSE); @@ -39,6 +42,29 @@ class views_plugin_row_node_view extends views_plugin_row { 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['links'] = array( + '#type' => 'checkbox', + '#title' => t('Display links'), + '#default_value' => $this->options['links'], + ); + $form['comments'] = array( + '#type' => 'checkbox', + '#title' => t('Display comments'), + '#default_value' => $this->options['comments'], + ); + } + + /** + * Return the main options, which are shown in the summary title. + */ + function options_form_summary_options() { $entity_info = entity_get_info('node'); $options = array(); if (!empty($entity_info['view modes'])) { @@ -49,26 +75,16 @@ class views_plugin_row_node_view extends views_plugin_row { if (empty($options)) { $options = array( 'teaser' => t('Teaser'), - 'full' => t('Full node') + 'full' => t('Full content') ); } - $form['build_mode'] = array( - '#type' => 'select', - '#options' => $options, - '#title' => t('Build mode'), - '#default_value' => $this->options['build_mode'], - ); - $form['links'] = array( - '#type' => 'checkbox', - '#title' => t('Display links'), - '#default_value' => $this->options['links'], - ); - $form['comments'] = array( - '#type' => 'checkbox', - '#title' => t('Display node comments'), - '#default_value' => $this->options['comments'], - ); + return $options; + } + + function summary_title() { + $options = $this->options_form_summary_options(); + return check_plain($options[$this->options['view_mode']]); } function pre_render($values) { diff --git a/sites/all/modules/views/modules/poll.views.inc b/sites/all/modules/views/modules/poll.views.inc index d759e8b96ab4e153b880bca142f56c61b41c4f8d..5819b7e81fffaa968d398e30314144fe5ebad4af 100644 --- a/sites/all/modules/views/modules/poll.views.inc +++ b/sites/all/modules/views/modules/poll.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: poll.views.inc,v 1.4.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * @file * Provide views data and handlers for poll.module diff --git a/sites/all/modules/views/modules/profile.views.inc b/sites/all/modules/views/modules/profile.views.inc index 9fe790746ea890c4552b0aebca3af1f9eae64683..65ad71dc9001d5501d9b8310db298d8f1c809759 100644 --- a/sites/all/modules/views/modules/profile.views.inc +++ b/sites/all/modules/views/modules/profile.views.inc @@ -1,5 +1,4 @@ <?php -//$Id: profile.views.inc,v 1.10.4.8 2010/12/16 06:50:28 merlinofchaos Exp $ /** * @file * Provide views data and handlers for user.module @@ -15,6 +14,7 @@ * Implements hook_views_data() */ function profile_views_data() { + $data['profile_values']['moved to'] = 'profile_value'; // Define the base group of this table. Fields that don't // have a group defined will go into this field by default. $data['profile_value']['table']['group'] = t('Profile'); diff --git a/sites/all/modules/views/modules/profile.views_convert.inc b/sites/all/modules/views/modules/profile.views_convert.inc index 4819dda688d06e76bd2bc2e7784e4e775db4a33a..b4f08daaa5fb7820f1377eb4a852de11a77b983d 100644 --- a/sites/all/modules/views/modules/profile.views_convert.inc +++ b/sites/all/modules/views/modules/profile.views_convert.inc @@ -1,5 +1,4 @@ <?php -// $Id: profile.views_convert.inc,v 1.2.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * @file 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 8f61976565cc316e5e4e9b5f9161cb8d74c44ce8..a294b65574fed33a2c6f6e440c9c03837968b040 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_profile_date.inc,v 1.1 2008/09/03 19:21:29 merlinofchaos Exp $ /** * Field handler display a profile date * @@ -16,11 +15,12 @@ class views_handler_field_profile_date extends views_handler_field_date { /** * Display a profile field of type 'date' */ - function render($value) { - if (!$value->{$this->field_alias}) { + function render($values) { + $value = $this->get_value($values); + if (!$value) { return; } - $value = unserialize($value->{$this->field_alias}); + $value = unserialize($value); $format = $this->options['date_format']; switch ($format) { case 'custom': @@ -79,4 +79,3 @@ class views_handler_field_profile_date extends views_handler_field_date { return strtr($format, $replace); } } - 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 84861e57440b13105d3c7855d5a7a17c200b5a2d..bb09015dd2e60c4226ec6624b3d70da0a6c48640 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,5 +1,4 @@ <?php -// $Id: views_handler_field_profile_list.inc,v 1.4.4.4 2010/12/20 20:14:28 dereine Exp $ /** * Field handler display a profile list item. */ @@ -10,7 +9,7 @@ class views_handler_field_profile_list extends views_handler_field_prerender_lis function pre_render(&$values) { $this->items = array(); foreach ($values as $value) { - $field = $value->{$this->field_alias}; + $field = $this->get_value($value); $this->items[$field] = array(); foreach (preg_split("/[,\n\r]/", $field) as $item) { if ($item != '' && $item !== NULL) { 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 2e54351ba2759b6cc8ebe4529c8db3a291cbf822..77c34f433bb1f19b5ed91c42ceff19d0a294b00f 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_profile_selection.inc,v 1.1.6.1 2010/12/20 20:14:28 dereine Exp $ /** * Filter by a selection widget in the profile. diff --git a/sites/all/modules/views/modules/search.views.inc b/sites/all/modules/views/modules/search.views.inc index a75e397153339520de7839dfa5f597f736b9bc8b..f661c7cf499aaf9164585c55696ef8a5174bf455 100644 --- a/sites/all/modules/views/modules/search.views.inc +++ b/sites/all/modules/views/modules/search.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: search.views.inc,v 1.18.4.3 2010/07/19 09:18:42 dereine Exp $ /** * @file * Provide views data and handlers for search.module diff --git a/sites/all/modules/views/modules/search.views_convert.inc b/sites/all/modules/views/modules/search.views_convert.inc index ab1a1ccedbde0921a5f588c91332a05b4d54cf27..08fd29769b9b117c8d7dcca2cdaffc72e4a7575c 100644 --- a/sites/all/modules/views/modules/search.views_convert.inc +++ b/sites/all/modules/views/modules/search.views_convert.inc @@ -1,6 +1,4 @@ <?php -// $Id: search.views_convert.inc,v 1.2.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ - /** * @file * Field conversion for fields handled by this module. diff --git a/sites/all/modules/views/modules/search.views_default.inc b/sites/all/modules/views/modules/search.views_default.inc index 2bbfd522407007f6d385b9730137ee93eeb4b000..f10f3766e161882ea6b35338dafd6c71157a8519 100644 --- a/sites/all/modules/views/modules/search.views_default.inc +++ b/sites/all/modules/views/modules/search.views_default.inc @@ -1,5 +1,4 @@ <?php -// $Id: search.views_default.inc,v 1.6.6.4 2011/01/05 23:14:39 dereine Exp $ /** * @file * Contains default views on behalf of the search module. @@ -14,10 +13,11 @@ function search_views_default_views() { $view->description = 'Displays a list of nodes that link to the node, using the search backlinks table.'; $view->tag = 'default'; $view->base_table = 'node'; + $view->human_name = 'Backlinks'; $view->api_version = 2; $view->version = 7; $view->disabled = TRUE; /* Edit this to true to make a default view disabled initially */ - $handler = $view->new_display('default', 'Defaults', 'default'); + $handler = $view->new_display('default', 'Master', 'default'); $handler->override_option('fields', array( 'title' => array( 'id' => 'title', 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 cf3f20a5f37609b3b0765b370efdaabc79e2d629..fd1372f3b340dbb0ddf34eb225204edb40a79280 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_search.inc,v 1.1.2.2 2010/01/24 22:37:52 dereine Exp $ /** * Argument that accepts query keys for search. @@ -7,19 +6,46 @@ class views_handler_argument_search extends views_handler_argument { /** - * Add this argument to the query. + * Take sure that parseSearchExpression is runned and everything is set up for it. + * + * @param $input + * The search phrase which was input by the user. */ - function query() { - $this->search_query = search_parse_query($this->argument); + function query_parse_search_expression($input) { + if (!isset($this->search_query)) { + $this->search_query = db_select('search_index', 'i', array('target' => 'slave'))->extend('viewsSearchQuery'); + $this->search_query->searchExpression($input, $this->view->base_table); + $this->search_query->publicParseSearchExpression(); + } + } - if (!isset($this->search_query) || empty($this->search_query[3])) { + /** + * Add this argument to the query. + */ + function query($group_by = FALSE) { + $required = FALSE; + $this->query_parse_search_expression($this->argument); + if (!isset($this->search_query)) { + $required = TRUE; + } + else { + $words = $this->search_query->words(); + if (empty($words)) { + $required = TRUE; + } + } + if ($required) { if ($this->operator == 'required') { - $this->query->add_where($this->options['group'], '0'); + $this->query->add_where($this->options['group'], 'FALSE'); } } else { $search_index = $this->ensure_my_table(); - $this->search_query[2] = str_replace('i.', "$search_index.", $this->search_query[2]); + + $or = db_or(); + foreach ($words as $word) { + $or->condition("$search_index.word", $word); + } // Create a new join to relate the 'search_total' table to our current 'search_index' table. $join = new views_join; @@ -28,7 +54,7 @@ class views_handler_argument_search extends views_handler_argument { $this->search_score = $this->query->add_field('', "SUM($search_index.score * $search_total.count)", 'score', array('aggregate' => TRUE)); - $this->query->add_where($this->options['group'], $this->search_query[2], $this->search_query[3]); + $this->query->add_where($this->options['group'], $or); if (empty($this->query->relationships[$this->relationship])) { $base_table = $this->query->base_table; @@ -36,15 +62,25 @@ class views_handler_argument_search extends views_handler_argument { else { $base_table = $this->query->relationships[$this->relationship]['base']; } - $this->query->add_where($this->options['group'], "$search_index.type = '%s'", $base_table); - if (!$this->search_query[5]) { + $this->query->add_where($this->options['group'], "$search_index.type", $base_table); + if (!$this->search_query->simple()) { $search_dataset = $this->query->add_table('search_dataset'); - $this->search_query[0] = str_replace('d.', "$search_dataset.", $this->search_query[0]); - $this->query->add_where($this->options['group'], $this->search_query[0], $this->search_query[1]); + $conditions = $this->search_query->conditions(); + $condition_conditions =& $conditions->conditions(); + foreach ($condition_conditions as $key => &$condition) { + // Take sure we just look at real conditions. + if (is_numeric($key)) { + // Replace the conditions with the table alias of views. + $this->search_query->condition_replace_string('d.', "$search_dataset.", $condition); + } + } + $this->query->add_where($this->options['group'], $conditions); } $this->query->add_groupby("$search_index.sid"); - $this->query->add_having($this->options['group'], 'COUNT(*)', $this->search_query[4], '>='); + $matches = $this->search_query->matches(); + $placeholder = $this->placeholder(); + $this->query->add_having_expression($this->options['group'], "COUNT(*) >= $placeholder", array($placeholder => $matches)); } } } 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 3f0b248533d0c34ef4faeacfd3085a3ea85e772d..b3d6fe3ab671abd6afa62fc4bf66bcc6c2af53bb 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,4 @@ <?php -// $Id: views_handler_field_search_score.inc,v 1.2.6.1 2010/12/09 21:31:10 merlinofchaos Exp $ - /** * Field handler to provide simple renderer that allows linking to a node. */ @@ -26,7 +24,7 @@ class views_handler_field_search_score extends views_handler_field_numeric { $form['alternate_sort'] = array( '#type' => 'select', '#title' => t('Alternative sort'), - '#description' => t('If no search is performed and this field does not appear, pick an alternative default table sort field.'), + '#description' => t('Pick an alternative default table sort field to use when the search score field is unavailable.'), '#options' => $options, '#default_value' => $this->options['alternate_sort'], ); 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 48ccb6ed93a0cbe241ffe8ff8e700c1a3ee314f1..bf7089fb44fdfbc5eda8aae22430bf6e2ecb80bc 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 @@ -1,11 +1,23 @@ <?php -// $Id: views_handler_filter_search.inc,v 1.5.6.2 2009/12/24 00:37:00 merlinofchaos Exp $ /** * Field handler to provide simple renderer that allows linking to a node. */ class views_handler_filter_search extends views_handler_filter { - var $no_single = TRUE; + var $always_multiple = TRUE; + + /** + * Stores a viewsSearchQuery object to be able to use the search.module "api". + * + * @var viewsSearchQuery + */ + var $search_query = NULL; + + /** + * Checks if the search query has been parsed. + */ + var $parsed = FALSE; + function option_definition() { $options = parent::option_definition(); @@ -47,26 +59,35 @@ class views_handler_filter_search extends views_handler_filter { /** * Validate the options form. */ - function exposed_validate($form, &$form_state) { + function exposed_validate(&$form, &$form_state) { if (!isset($this->options['expose']['identifier'])) { return; } $key = $this->options['expose']['identifier']; if (!empty($form_state['values'][$key])) { - $this->search_query = search_parse_query($form_state['values'][$key]); - - if ($this->search_query[2] == '') { - form_set_error($key, t('You must include at least one positive keyword with @count characters or more.', array('@count' => variable_get('minimum_word_size', 3)))); - } - if ($this->search_query[6]) { - if ($this->search_query[6] == 'or') { - drupal_set_message(t('Search for either of the two terms with uppercase <strong>OR</strong>. For example, <strong>cats OR dogs</strong>.')); - } + $this->query_parse_search_expression($form_state['values'][$key]); + if (count($this->search_query->words()) == 0) { + form_set_error($key, format_plural(variable_get('minimum_word_size', 3), 'You must include at least one positive keyword with 1 character or more.', 'You must include at least one positive keyword with @count characters or more.')); } } } + /** + * Take sure that parseSearchExpression is runned and everything is set up for it. + * + * @param $input + * The search phrase which was input by the user. + */ + function query_parse_search_expression($input) { + if (!isset($this->search_query)) { + $this->parsed = TRUE; + $this->search_query = db_select('search_index', 'i', array('target' => 'slave'))->extend('viewsSearchQuery'); + $this->search_query->searchExpression($input, $this->view->base_table); + $this->search_query->publicParseSearchExpression(); + } + } + /** * Add this filter to the query. * @@ -75,14 +96,33 @@ class views_handler_filter_search extends views_handler_filter { * and $this->value respectively. */ function query() { - if (!isset($this->search_query) || empty($this->search_query[3])) { + // Since attachment views don't validate the exposed input, parse the search + // expression if required. + if (!$this->parsed) { + $this->query_parse_search_expression($this->value); + } + $required = FALSE; + if (!isset($this->search_query)) { + $required = TRUE; + } + else { + $words = $this->search_query->words(); + if (empty($words)) { + $required = TRUE; + } + } + if ($required) { if ($this->operator == 'required') { $this->query->add_where($this->options['group'], 'FALSE'); } } else { $search_index = $this->ensure_my_table(); - $this->search_query[2] = str_replace('i.', "$search_index.", $this->search_query[2]); + + $or = db_or(); + foreach ($words as $word) { + $or->condition("$search_index.word", $word); + } // Create a new join to relate the 'serach_total' table to our current 'search_index' table. $join = new views_join; @@ -91,7 +131,7 @@ class views_handler_filter_search extends views_handler_filter { $this->search_score = $this->query->add_field('', "SUM($search_index.score * $search_total.count)", 'score', array('aggregate' => TRUE)); - $this->query->add_where($this->options['group'], $this->search_query[2], $this->search_query[3]); + $this->query->add_where($this->options['group'], $or); if (empty($this->query->relationships[$this->relationship])) { $base_table = $this->query->base_table; @@ -99,15 +139,60 @@ class views_handler_filter_search extends views_handler_filter { else { $base_table = $this->query->relationships[$this->relationship]['base']; } - $this->query->add_where($this->options['group'], "$search_index.type = '%s'", $base_table); - if (!$this->search_query[5]) { + $this->query->add_where($this->options['group'], "$search_index.type", $base_table); + if (!$this->search_query->simple()) { $search_dataset = $this->query->add_table('search_dataset'); - $this->search_query[0] = str_replace('d.', "$search_dataset.", $this->search_query[0]); - $this->query->add_where($this->options['group'], $this->search_query[0], $this->search_query[1]); + $conditions = $this->search_query->conditions(); + $condition_conditions =& $conditions->conditions(); + foreach ($condition_conditions as $key => &$condition) { + // Take sure we just look at real conditions. + if (is_numeric($key)) { + // Replace the conditions with the table alias of views. + $this->search_query->condition_replace_string('d.', "$search_dataset.", $condition); + } + } + $this->query->add_where($this->options['group'], $conditions); } $this->query->add_groupby("$search_index.sid"); - $this->query->add_having($this->options['group'], 'COUNT(*)', $this->search_query[4], '>='); + $matches = $this->search_query->matches(); + $placeholder = $this->placeholder(); + $this->query->add_having_expression($this->options['group'], "COUNT(*) >= $placeholder", array($placeholder => $matches)); + } + } +} + +class viewsSearchQuery extends searchQuery { + public function &conditions() { + return $this->conditions; + } + public function words() { + return $this->words; + } + + public function simple() { + return $this->simple; + } + + public function matches() { + return $this->matches; + } + + public function publicParseSearchExpression() { + return $this->parseSearchExpression(); + } + + function condition_replace_string($search, $replace, &$condition) { + if ($condition['field'] instanceof DatabaseCondition) { + $conditions =& $condition['field']->conditions(); + foreach ($conditions as $key => &$subcondition) { + if (is_numeric($key)) { + $this->condition_replace_string($search, $replace, $subcondition); + } + } + } + else { + $condition['field'] = str_replace($search, $replace, $condition['field']); } } } 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 48a938cae4040ccf55f60b8b17bd8a05958b6817..90c99eae9de2b8919a9fc8a58e3ea0fa1a1368bc 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_sort_search_score.inc,v 1.1 2009/02/23 22:19:47 merlinofchaos Exp $ /** * Field handler to provide simple renderer that allows linking to a node. diff --git a/sites/all/modules/views/modules/search/views_plugin_row_search_view.inc b/sites/all/modules/views/modules/search/views_plugin_row_search_view.inc index 6311676f66e8d66baf0861ff389511fad93a3007..738334404868e27ca9cc5384ca0963723cfbb7a9 100644 --- a/sites/all/modules/views/modules/search/views_plugin_row_search_view.inc +++ b/sites/all/modules/views/modules/search/views_plugin_row_search_view.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_row_search_view.inc,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * @file * Contains the search row style plugin. diff --git a/sites/all/modules/views/modules/statistics.views.inc b/sites/all/modules/views/modules/statistics.views.inc index 5ee89ecb1b3fb1e39a00dfea65ec57aa26cb3835..78ef793f0efbac6406d9377cef40734c3d7dea93 100644 --- a/sites/all/modules/views/modules/statistics.views.inc +++ b/sites/all/modules/views/modules/statistics.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: statistics.views.inc,v 1.9.6.3 2010/07/19 09:18:42 dereine Exp $ /** * @file * Provide views data and handlers for statistics.module @@ -21,7 +20,7 @@ function statistics_views_data() { // ---------------------------------------------------------------- // node_counter table - $data['node_counter']['table']['group'] = t('Node statistics'); + $data['node_counter']['table']['group'] = t('Content statistics'); $data['node_counter']['table']['join'] = array( // ...to the node table diff --git a/sites/all/modules/views/modules/statistics.views_convert.inc b/sites/all/modules/views/modules/statistics.views_convert.inc index 90785d99dd308e49ec5d2dce030f36ffd0a3e4be..19257a9fdaae9b8c4020f569623572b7d0f017d2 100644 --- a/sites/all/modules/views/modules/statistics.views_convert.inc +++ b/sites/all/modules/views/modules/statistics.views_convert.inc @@ -1,5 +1,4 @@ <?php -// $Id: statistics.views_convert.inc,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * @file diff --git a/sites/all/modules/views/modules/statistics.views_default.inc b/sites/all/modules/views/modules/statistics.views_default.inc index eb92fdea8883bdc0bf07234fdd55278f5ef7fcd5..c6bbd62c3185b4c4ef30e3160d5e59a30e793239 100644 --- a/sites/all/modules/views/modules/statistics.views_default.inc +++ b/sites/all/modules/views/modules/statistics.views_default.inc @@ -1,5 +1,4 @@ <?php -// $Id: statistics.views_default.inc,v 1.5.6.5 2011/01/05 23:14:39 dereine Exp $ /** * @file * Contains default views on behalf of the statistics module. @@ -14,10 +13,11 @@ function statistics_views_default_views() { $view->description = 'Shows the most-viewed nodes on the site. This requires the statistics to be enabled at administer >> reports >> access log settings.'; $view->tag = 'default'; $view->base_table = 'node'; + $view->human_name = 'Popular content'; $view->api_version = 2; $view->version = 7; $view->disabled = TRUE; /* Edit this to true to make a default view disabled initially */ - $handler = $view->new_display('default', 'Defaults', 'default'); + $handler = $view->new_display('default', 'Master', 'default'); $handler->override_option('fields', array( 'type' => array( 'id' => 'type', 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 8cf1b9d0aa46c28fea51593011137d21bbe13e38..03fa7d204b9e94d98ab4bdfe5edf91e2351c0905 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,5 +1,4 @@ <?php -// $Id: views_handler_field_accesslog_path.inc,v 1.1.6.1 2010/11/18 07:29:03 dereine Exp $ /** * Field handler to provide simple renderer that turns a URL into a clickable link. */ @@ -7,10 +6,10 @@ class views_handler_field_accesslog_path extends views_handler_field { /** * Override init function to provide generic option to link to node. */ - function init(&$view, &$data) { - parent::init($view, $data); - if (isset($data['display_as_link'])) { - $this->additional_fields[] = 'path'; + function init(&$view, $options) { + parent::init($view, $options); + if (!empty($this->options['display_as_link'])) { + $this->additional_fields['path'] = 'path'; } } @@ -26,22 +25,23 @@ class views_handler_field_accesslog_path extends views_handler_field { * Provide link to the page being visited. */ function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['display_as_link'] = array( '#title' => t('Display as link'), '#type' => 'checkbox', '#default_value' => !empty($this->options['display_as_link']), ); + parent::options_form($form, $form_state); } function render($values) { - return $this->render_link(check_plain($values->{$this->field_alias}), $values); + $value = $this->get_value($values); + return $this->render_link($this->sanitize_value($value), $values); } function render_link($data, $values) { if (!empty($this->options['display_as_link'])) { $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = $values->{$this->aliases['path']}; + $this->options['alter']['path'] = $this->get_value($values, 'path'); $this->options['alter']['html'] = TRUE; } diff --git a/sites/all/modules/views/modules/system.views.inc b/sites/all/modules/views/modules/system.views.inc index 7c5ba6d5c3372f6857c1678212a2bb46fbf22756..6e2c72a0fc1b9bad9b9598d6d692c7f9607c3951 100644 --- a/sites/all/modules/views/modules/system.views.inc +++ b/sites/all/modules/views/modules/system.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: system.views.inc,v 1.7.6.7 2010/10/16 09:06:51 dereine Exp $ /** * @file * @@ -22,6 +21,7 @@ function system_views_data() { // ---------------------------------------------------------------------- // file_managed table + $data['files']['moved to'] = 'file_managed'; $data['file_managed']['table']['group'] = t('File'); // Advertise this table as a possible base table @@ -29,6 +29,9 @@ function system_views_data() { 'field' => 'fid', 'title' => t('File'), 'help' => t("Files maintained by Drupal and various modules."), + 'defaults' => array( + 'field' => 'filename' + ), ); // The file table does not inherently join to the node table, @@ -198,31 +201,31 @@ function system_views_data() { 'node' => array( 'field' => 'id', 'left_field' => 'nid', - 'extra' => array(array('table' => 'file_usage', 'field' => 'type', 'value' => 'node')), + 'extra' => array(array('field' => 'type', 'value' => 'node')), ), // Link ourself to the {users} table so we can provide user->file relationships. 'users' => array( 'field' => 'id', 'left_field' => 'uid', - 'extra' => array(array('table' => 'file_usage', 'field' => 'type', 'value' => 'user')), + 'extra' => array(array('field' => 'type', 'value' => 'user')), ), // Link ourself to the {comment} table so we can provide comment->file relationships. 'comment' => array( 'field' => 'id', 'left_field' => 'cid', - 'extra' => array(array('table' => 'file_usage', 'field' => 'type', 'value' => 'comment')), + 'extra' => array(array('field' => 'type', 'value' => 'comment')), ), // Link ourself to the {taxonomy_term_data} table so we can provide taxonomy_term->file relationships. 'taxonomy_term_data' => array( 'field' => 'id', 'left_field' => 'tid', - 'extra' => array(array('table' => 'file_usage', 'field' => 'type', 'value' => 'taxonomy_term')), + 'extra' => array(array('field' => 'type', 'value' => 'taxonomy_term')), ), // Link ourself to the {taxonomy_vocabulary} table so we can provide taxonomy_vocabulary->file relationships. 'taxonomy_vocabulary' => array( 'field' => 'id', 'left_field' => 'vid', - 'extra' => array(array('table' => 'file_usage', 'field' => 'type', 'value' => 'taxonomy_vocabulary')), + 'extra' => array(array('field' => 'type', 'value' => 'taxonomy_vocabulary')), ), ); @@ -233,14 +236,14 @@ function system_views_data() { // Relationships between files and nodes. $data['file_usage']['file_to_node'] = array( - 'title' => t('Node'), - 'help' => t('A node that is associated with this file, usually because this file is in a field on the node.'), + 'title' => t('Content'), + 'help' => t('Content that is associated with this file, usually because this file is in a field on the content.'), // Only provide this field/relationship/etc. when the 'file_managed' base table is present. 'skip base' => array('node', 'node_revision', 'users', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'), 'real field' => 'id', 'relationship' => array( - 'title' => t('Node'), - 'label' => t('Node'), + 'title' => t('Content'), + 'label' => t('Content'), 'base' => 'node', 'base field' => 'nid', 'relationship field' => 'id', @@ -437,6 +440,114 @@ function system_views_data() { ), ); + // ---------------------------------------------------------------------- + // system table + $data['system']['table']['group'] = t('System'); + + // Advertise this table as a possible base table + $data['system']['table']['base'] = array( + 'field' => 'filename', + 'title' => t('Module/Theme/Theme engine'), + 'help' => t('Modules/Themes/Theme engines in your codebase.'), + ); + + // fields + // - filename + $data['system']['filename'] = array( + 'title' => t('Module/Theme/Theme engine filename'), + 'help' => t('The path of the primary file for this item, relative to the Drupal root; e.g. modules/node/node.module.'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + 'name field' => 'filename', // the field to display in the summary. + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ); + // - name + $data['system']['name'] = array( + 'title' => t('Module/Theme/Theme engine name'), + 'help' => t('The name of the item; e.g. node.'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + 'name field' => 'name', // the field to display in the summary. + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ); + // - type + $data['system']['type'] = array( + 'title' => t('Type'), + 'help' => t('The type of the item, either module, theme, or theme_engine.'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + 'name field' => 'type', // the field to display in the summary. + ), + 'filter' => array( + 'handler' => 'views_handler_filter_system_type', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ); + // - status + $data['system']['status'] = array( + 'title' => t('Status'), + 'help' => t('Boolean indicating whether or not this item is enabled.'), + 'field' => array( + 'handler' => 'views_handler_field_boolean', + 'click sortable' => TRUE, + ), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + 'name field' => 'status', // the field to display in the summary. + ), + 'filter' => array( + 'handler' => 'views_handler_filter_boolean_operator', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ); + // - schema version + $data['system']['schema_version'] = array( + 'title' => t('Schema version'), + 'help' => t("The module's database schema version number. -1 if the module is not installed (its tables do not exist); 0 or the largest N of the module's hook_update_N() function that has either been run or existed when the module was first installed."), + 'field' => array( + 'handler' => 'views_handler_field_numeric', + 'click sortable' => TRUE, + ), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + 'name field' => 'schema_version', // the field to display in the summary. + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ); + return $data; } 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 91181e04ee3055a060e0eb8fec2f55ba6e35879b..d51e5fb8cc91a63b8e31f575fd8a51c9deb5ea70 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,5 +1,4 @@ <?php -// $Id: views_handler_argument_file_fid.inc,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * Argument handler to accept a file id. */ 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 8dddb4380c2b73d95ce0f8550d58aec40f35fbb5..6d1660e2695e077da794eb5b9371f2aa7353ae30 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,5 +1,4 @@ <?php -// $Id: views_handler_field_file.inc,v 1.3.6.3 2010/10/06 17:47:37 dereine Exp $ /** * Field handler to provide simple renderer that allows linking to a file. */ @@ -24,13 +23,13 @@ class views_handler_field_file extends views_handler_field { * Provide link to file option */ function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['link_to_file'] = array( '#title' => t('Link this field to download the file'), - '#description' => t('This will override any other link you have set.'), + '#description' => t("Enable to override this field's links."), '#type' => 'checkbox', '#default_value' => !empty($this->options['link_to_file']), ); + parent::options_form($form, $form_state); } /** @@ -41,13 +40,14 @@ class views_handler_field_file extends views_handler_field { function render_link($data, $values) { if (!empty($this->options['link_to_file']) && $data !== NULL && $data !== '') { $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = file_create_url($values->{$this->aliases['uri']}); + $this->options['alter']['path'] = file_create_url($this->get_value($values, 'uri')); } return $data; } function render($values) { - return $this->render_link(check_plain($values->{$this->field_alias}), $values); + $value = $this->get_value($values); + return $this->render_link($this->sanitize_value($value), $values); } } \ No newline at end of file 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 c5b7ae2e695fecea15e78ac08a6abb1c47c72baa..f26dee8686746b99cda0b47e1000ec0578a268ff 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,5 +1,4 @@ <?php -// $Id: views_handler_field_file_extension.inc,v 1.1.4.2 2010/10/16 09:06:51 dereine Exp $ /** * @file * Returns a pure file extension of the file, for example 'module'. @@ -7,9 +6,9 @@ class views_handler_field_file_extension extends views_handler_field { function render($values) { - $value = $values->{$this->field_alias}; + $value = $this->get_value($values); if (preg_match('/\.([^\.]+)$/', $value, $match)) { - return check_plain($match[1]); + return $this->sanitize_value($match[1]); } } } 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 1193d1b6231872f589a2eb9bf6b27829d62348d7..9a06639a70039137aa81619075d192e0d4d63576 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_file_filemime.inc,v 1.1.2.1 2010/10/06 17:47:37 dereine Exp $ /** * Field handler to add rendering MIME type images as an option on the filemime field. @@ -12,12 +11,12 @@ class views_handler_field_file_filemime extends views_handler_field_file { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['filemime_image'] = array( - '#title' => t('Display an image representing the MIME type instead of the MIME text.'), + '#title' => t('Display an icon representing the file type, instead of the MIME text (such as "image/jpeg").'), '#type' => 'checkbox', '#default_value' => !empty($this->options['filemime_image']), ); + parent::options_form($form, $form_state); } function render($values) { 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 9b89c0fae543cf2c9e06b889ce4e48ba9c185168..8b42aa8094376e340cf39213c0f73b5e851990ab 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,11 +1,10 @@ <?php -// $Id: views_handler_field_file_status.inc,v 1.1 2008/09/03 19:21:30 merlinofchaos Exp $ /** * Field handler to translate a node type into its readable form. */ class views_handler_field_file_status extends views_handler_field { function render($values) { - return _views_file_status($values->{$this->field_alias}); + $value = $this->get_value($values); + return _views_file_status($value); } } - diff --git a/sites/all/modules/views/modules/system/views_handler_field_file_uri.inc b/sites/all/modules/views/modules/system/views_handler_field_file_uri.inc index 2ec18a09fa3ecb3cb4a06e481242618d92dd7f0e..d36aba389e3da97c6115fc996463e5a5f9a2339b 100644 --- a/sites/all/modules/views/modules/system/views_handler_field_file_uri.inc +++ b/sites/all/modules/views/modules/system/views_handler_field_file_uri.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_file_uri.inc,v 1.1.2.1 2010/10/06 17:47:37 dereine Exp $ /** * Field handler to add rendering file paths as file URLs instead of as internal file URIs. @@ -12,13 +11,13 @@ class views_handler_field_file_uri extends views_handler_field_file { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['file_download_path'] = array( '#title' => t('Display download path instead of file storage URI'), '#description' => t('This will provide the full download URL rather than the internal filestream address.'), '#type' => 'checkbox', '#default_value' => !empty($this->options['file_download_path']), ); + parent::options_form($form, $form_state); } 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 9a80d90dcca20690dac59de2a4cd4f4d764136c7..16dce1be08fa941a77f0e44179ded0daff162c0e 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,5 +1,4 @@ <?php -// $Id: views_handler_filter_file_status.inc,v 1.1 2008/09/03 19:21:30 merlinofchaos Exp $ /** * Filter by file status */ diff --git a/sites/all/modules/views/modules/system/views_handler_filter_system_type.inc b/sites/all/modules/views/modules/system/views_handler_filter_system_type.inc new file mode 100644 index 0000000000000000000000000000000000000000..5a9a8111554b9726cd4092faa2614448f016620a --- /dev/null +++ b/sites/all/modules/views/modules/system/views_handler_filter_system_type.inc @@ -0,0 +1,16 @@ +<?php + +/** + * Filter by system type. + */ +class views_handler_filter_system_type extends views_handler_filter_in_operator { + function get_value_options() { + if (!isset($this->value_options)) { + $this->value_title = t('Type'); + // Enable filtering by type. + $types = array(); + $types = db_query('SELECT DISTINCT(type) FROM {system} ORDER BY type')->fetchAllKeyed(0, 0); + $this->value_options = $types; + } + } +} diff --git a/sites/all/modules/views/modules/taxonomy.views.inc b/sites/all/modules/views/modules/taxonomy.views.inc index 98ded4a4516aa82c84122df771da613087d4ce44..ec2c92932f7ff67655c1d7522eabd17d2e6bef12 100644 --- a/sites/all/modules/views/modules/taxonomy.views.inc +++ b/sites/all/modules/views/modules/taxonomy.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: taxonomy.views.inc,v 1.57.4.18 2010/12/04 07:46:13 dereine Exp $ /** * @file * @@ -21,6 +20,7 @@ function taxonomy_views_data() { // ---------------------------------------------------------------------- // taxonomy_vocabulary table + $data['vocabulary']['moved to'] = 'taxonomy_vocabulary'; $data['taxonomy_vocabulary']['table']['group'] = t('Taxonomy'); $data['taxonomy_vocabulary']['table']['join'] = array( @@ -77,6 +77,7 @@ function taxonomy_views_data() { // ---------------------------------------------------------------------- // taxonomy_term_data table + $data['term_data']['moved to'] = 'taxonomy_term_data'; $data['taxonomy_term_data']['table']['group'] = t('Taxonomy'); $data['taxonomy_term_data']['table']['base'] = array( 'field' => 'tid', @@ -163,6 +164,9 @@ function taxonomy_views_data() { 'sort' => array( 'handler' => 'views_handler_sort', ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), ); // Term description @@ -198,6 +202,7 @@ function taxonomy_views_data() { // ---------------------------------------------------------------------- // taxonomy_index table + $data['term_node']['moved to'] = 'taxonomy_index'; $data['taxonomy_index']['table']['group'] = t('Taxonomy'); $data['taxonomy_index']['table']['join'] = array( @@ -218,8 +223,8 @@ function taxonomy_views_data() { ); $data['taxonomy_index']['nid'] = array( - 'title' => t('Node'), - 'help' => t('Get all nodes tagged with a term.'), + 'title' => t('Content'), + 'help' => t('Get all content tagged with a term.'), 'relationship' => array( 'handler' => 'views_handler_relationship', 'base' => 'node', @@ -262,6 +267,7 @@ function taxonomy_views_data() { $data['taxonomy_term_hierarchy']['table']['group'] = t('Taxonomy'); + $data['term_hierarchy']['moved to'] = 'taxonomy_term_hierarchy'; $data['taxonomy_term_hierarchy']['table']['join'] = array( 'taxonomy_term_hierarchy' => array( // links to self through left.parent = right.tid (going down in depth) @@ -296,11 +302,12 @@ function taxonomy_views_data() { ); // ---------------------------------------------------------------------- - // term_synonym table + // taxonomy_term_synonym table - $data['term_synonym']['table']['group'] = t('Taxonomy'); + $data['term_synonym']['moved to'] = 'taxonomy_term_synonym'; + $data['taxonomy_term_synonym']['table']['group'] = t('Taxonomy'); - $data['term_synonym']['table']['join'] = array( + $data['taxonomy_term_synonym']['table']['join'] = array( 'taxonomy_term_data' => array( // links directly to taxonomy_term_data via tid 'left_field' => 'tid', @@ -313,7 +320,7 @@ function taxonomy_views_data() { ), ); - $data['term_synonym']['name'] = array( + $data['taxonomy_term_synonym']['name'] = array( 'title' => t('Term synonym'), 'help' => t('Term synonyms may be used to find terms by alternate names.'), 'argument' => array( @@ -331,7 +338,7 @@ function taxonomy_views_data() { function taxonomy_views_data_alter(&$data) { $data['node']['term_node_tid'] = array( 'group' => t('Taxonomy'), - 'title' => t('Related terms'), + 'title' => t('Terms on node'), 'help' => t('Relate nodes to taxonomy terms, specifiying which vocabulary or vocabularies to use. This relationship will cause duplicated records if there are multiple terms.'), 'relationship' => array( 'handler' => 'views_handler_relationship_node_term_data', @@ -357,7 +364,7 @@ function taxonomy_views_data_alter(&$data) { $data['node']['term_node_tid_depth_modifier'] = array( 'group' => t('Taxonomy'), 'title' => t('Term ID depth modifier'), - 'help' => t('Allows the "depth" for Taxonomy: Term ID (with depth) to be modified via an additional argument.'), + 'help' => t('Allows the "depth" for Taxonomy: Term ID (with depth) to be modified via an additional contextual filter value.'), 'argument' => array( 'handler' => 'views_handler_argument_term_node_tid_depth_modifier', ), @@ -429,7 +436,7 @@ function views_taxonomy_set_breadcrumb(&$breadcrumb, &$argument) { continue; } if ($argument->options['use_taxonomy_term_path']) { - $path = taxonomy_term_path($parent); + $path = taxonomy_term_uri($parent); } else { $args[$argument->position] = $parent->tid; diff --git a/sites/all/modules/views/modules/taxonomy.views_convert.inc b/sites/all/modules/views/modules/taxonomy.views_convert.inc index 0fe5efa3e9b240796a243d164121907b8af7f99b..50c9b952a2b0fb17af6c0388a43dacad7f7a73b3 100644 --- a/sites/all/modules/views/modules/taxonomy.views_convert.inc +++ b/sites/all/modules/views/modules/taxonomy.views_convert.inc @@ -1,5 +1,4 @@ <?php -//$Id: taxonomy.views_convert.inc,v 1.4.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * @file diff --git a/sites/all/modules/views/modules/taxonomy.views_default.inc b/sites/all/modules/views/modules/taxonomy.views_default.inc index cb8049d8d20b18908520ffe5d8b691f3ca729b95..d03a1d386ae68ea73644f9ae44dddb9f251e5373 100644 --- a/sites/all/modules/views/modules/taxonomy.views_default.inc +++ b/sites/all/modules/views/modules/taxonomy.views_default.inc @@ -1,5 +1,4 @@ <?php -// $Id: taxonomy.views_default.inc,v 1.3.6.4 2011/01/05 23:14:39 dereine Exp $ /** * @file * Contains default views on behalf of the statistics module. @@ -14,10 +13,11 @@ function taxonomy_views_default_views() { $view->description = 'A view to emulate Drupal core\'s handling of taxonomy/term; it also emulates Views 1\'s handling by having two possible feeds.'; $view->tag = 'default'; $view->base_table = 'node'; + $view->human_name = 'Taxonomy term'; $view->api_version = 2; $view->version = 7; $view->disabled = TRUE; /* Edit this to true to make a default view disabled initially */ - $handler = $view->new_display('default', 'Defaults', 'default'); + $handler = $view->new_display('default', 'Master', 'default'); $handler->override_option('sorts', array( 'sticky' => array( 'id' => 'sticky', 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 9fd0ae00895cfaede0e91937306ede53ff598d9e..44b2bdac188ca18c10f61133dd378c2a3850d852 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_taxonomy.inc,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * Argument handler for basic taxonomy tid. 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 c3c7c9aeff82273cd663d02a6b3f108d58fa57bf..cf83d46efcdc0cae25e95b0b065f3c041716c6c0 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,5 +1,4 @@ <?php -// $Id: views_handler_argument_term_node_tid.inc,v 1.1.6.5 2010/10/27 05:12:52 dereine Exp $ /** * Allow taxonomy term ID(s) as argument */ 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 5d1922fd1459cc9e5ecb14134061270f19c71ea5..3bc3c5fd1454e2ebca19160c0e226d327ed0f2c2 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_term_node_tid_depth.inc,v 1.3.4.7 2010/11/27 20:53:28 dereine Exp $ /** * Argument handler for taxonomy terms with depth. * @@ -19,7 +18,6 @@ class views_handler_argument_term_node_tid_depth extends views_handler_argument } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['depth'] = array( '#type' => 'weight', '#title' => t('Depth'), @@ -29,8 +27,8 @@ class views_handler_argument_term_node_tid_depth extends views_handler_argument $form['break_phrase'] = array( '#type' => 'checkbox', - '#title' => t('Allow multiple terms per argument'), - '#description' => t('If selected, users can enter multiple arguments in the form of 1+2+3. Due to the number of JOINs it would require, AND will be treated as OR with this argument.'), + '#title' => t('Allow multiple values'), + '#description' => t('If selected, users can enter multiple values in the form of 1+2+3. Due to the number of JOINs it would require, AND will be treated as OR with this filter.'), '#default_value' => !empty($this->options['break_phrase']), ); @@ -49,6 +47,7 @@ class views_handler_argument_term_node_tid_depth extends views_handler_argument '#process' => array('form_process_checkbox', 'ctools_dependent_process'), '#dependency' => array('edit-options-set-breadcrumb' => array(TRUE)), ); + parent::options_form($form, $form_state); } function set_breadcrumb(&$breadcrumb) { @@ -75,7 +74,7 @@ class views_handler_argument_term_node_tid_depth extends views_handler_argument return $actions; } - function query() { + function query($group_by = FALSE) { $this->ensure_my_table(); if (!empty($this->options['break_phrase'])) { @@ -97,7 +96,7 @@ class views_handler_argument_term_node_tid_depth extends views_handler_argument } else { $operator = "="; - $tids = array($this->argument); + $tids = $this->argument; } // Now build the subqueries. $subquery = db_select('taxonomy_index', 'tn'); 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 9bde14ccaa97dff045f11e08eac39881163063bf..e28b9ebea5f08cd26cd434d2b6f5243cab82ed88 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_term_node_tid_depth_modifier.inc,v 1.1 2008/09/03 19:21:30 merlinofchaos Exp $ /** * Argument handler for to modify depth for a previous term. @@ -9,7 +8,7 @@ */ class views_handler_argument_term_node_tid_depth_modifier extends views_handler_argument { function options_form(&$form, &$form_state) { } - function query() { } + function query($group_by = FALSE) { } function pre_query() { // We don't know our argument yet, but it's based upon our position: $argument = isset($this->view->args[$this->position]) ? $this->view->args[$this->position] : NULL; 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 0564416d9d4cfd2f3c2c4260899ef5cbb7d61916..5c828c1668c88c9b300da5403631521bf16901c2 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_vocabulary_vid.inc,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * Argument handler to accept a vocabulary id. 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 4713e09ce2d39234e3891dda2444e7e459a3b467..c721e841b7bd94a9e583efd8b28cf07f408b42fe 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_taxonomy.inc,v 1.3.6.3 2010/09/19 09:40:34 dereine Exp $ /** * Field handler to provide simple renderer that allows linking to a taxonomy @@ -32,13 +31,13 @@ class views_handler_field_taxonomy extends views_handler_field { * Provide link to taxonomy option */ function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['link_to_taxonomy'] = array( '#title' => t('Link this field to its taxonomy term page'), - '#description' => t('This will override any other link you have set.'), + '#description' => t("Enable to override this field's links."), '#type' => 'checkbox', '#default_value' => !empty($this->options['link_to_taxonomy']), ); + parent::options_form($form, $form_state); } /** @@ -47,10 +46,11 @@ class views_handler_field_taxonomy extends views_handler_field { * Data should be made XSS safe prior to calling this function. */ function render_link($data, $values) { - if (!empty($this->options['link_to_taxonomy']) && !empty($values->{$this->aliases['tid']}) && $data !== NULL && $data !== '') { + $tid = $this->get_value($values, 'tid'); + if (!empty($this->options['link_to_taxonomy']) && !empty($tid) && $data !== NULL && $data !== '') { $term = new stdClass(); - $term->tid = $values->{$this->aliases['tid']}; - $term->vid = $values->{$this->aliases['vid']}; + $term->tid = $tid; + $term->vid = $this->get_value($values, 'vid'); $term->vocabulary_machine_name = $values->{$this->aliases['vocabulary_machine_name']}; $this->options['alter']['make_link'] = TRUE; $uri = entity_uri('taxonomy_term', $term); @@ -60,6 +60,7 @@ class views_handler_field_taxonomy extends views_handler_field { } function render($values) { - return $this->render_link(check_plain($values->{$this->field_alias}), $values); + $value = $this->get_value($values); + return $this->render_link($this->sanitize_value($value), $values); } } 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 43a812d444cd6ff337bbd6685e2f7e234b2140c5..3903951bb83225f2f005d0a9039ff3549067450c 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,5 +1,4 @@ <?php -// $Id: views_handler_field_term_link_edit.inc,v 1.1.4.3 2010/12/19 10:33:13 dereine Exp $ /** * Field handler to present a term edit link . @@ -24,12 +23,12 @@ class views_handler_field_term_link_edit extends views_handler_field { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['text'] = array( '#type' => 'textfield', '#title' => t('Text to display'), '#default_value' => $this->options['text'], ); + parent::options_form($form, $form_state); } function query() { @@ -46,7 +45,8 @@ class views_handler_field_term_link_edit extends views_handler_field { $term->vocabulary_machine_name = $values->{$this->aliases['vocabulary_machine_name']}; if (taxonomy_term_edit_access($term)) { $text = !empty($this->options['text']) ? $this->options['text'] : t('edit'); - return l($text, 'taxonomy/term/'. $values->{$this->aliases['tid']} .'/edit', array('query' => drupal_get_destination())); + $tid = $this->get_value($values, 'tid'); + return l($text, 'taxonomy/term/'. $tid . '/edit', array('query' => drupal_get_destination())); } } } 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 be9ad2eb292a0743f565115b8a4c4bf5dcf2dbb3..7e63f2f9152399bf974e254819f8aa8b3e17defb 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,5 +1,4 @@ <?php -// $Id: views_handler_field_term_node_tid.inc,v 1.4.4.10 2011/01/04 00:11:54 dereine Exp $ /** * Field handler for terms. @@ -39,7 +38,6 @@ class views_handler_field_term_node_tid extends views_handler_field_prerender_li * Provide "link to term" option. */ function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['link_to_taxonomy'] = array( '#title' => t('Link this field to its term page'), '#type' => 'checkbox', @@ -50,6 +48,7 @@ class views_handler_field_term_node_tid extends views_handler_field_prerender_li '#type' => 'checkbox', '#title' => t('Limit terms by vocabulary'), '#default_value'=> $this->options['limit'], + '#fieldset' => 'more', ); $options = array(); @@ -67,7 +66,10 @@ class views_handler_field_term_node_tid extends views_handler_field_prerender_li '#default_value' => $this->options['vocabularies'], '#process' => array('form_process_checkboxes', 'ctools_dependent_process'), '#dependency' => array('edit-options-limit' => array(TRUE)), + '#fieldset' => 'more', ); + + parent::options_form($form, $form_state); } /** 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 c7b0a4ffeb2e3864505d31b17c3c2e3b51ef86a7..5ffe2f1a40ec2474ee8d66db4d6f228b634a26b3 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,5 +1,4 @@ <?php -// $Id: views_handler_filter_term_node_tid.inc,v 1.8.6.14 2010/12/24 13:42:01 dereine Exp $ /** * Filter by term id @@ -156,13 +155,13 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on if (!empty($this->options['expose']['reduce'])) { $options = $this->reduce_value_options($options); - if (empty($this->options['expose']['single']) && !empty($this->options['expose']['optional'])) { + if (!empty($this->options['expose']['multiple']) && empty($this->options['expose']['required'])) { $default_value = array(); } } - if (!empty($this->options['expose']['single'])) { - if (!empty($this->options['expose']['optional']) && (empty($default_value) || !empty($this->options['expose']['reduce']))) { + if (empty($this->options['expose']['multiple'])) { + if (empty($this->options['expose']['required']) && (empty($default_value) || !empty($this->options['expose']['reduce']))) { $default_value = 'All'; } elseif (empty($default_value)) { @@ -196,7 +195,7 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on } } - function value_validate(&$form, &$form_state) { + function value_validate($form, &$form_state) { // We only validate if they've chosen the text field style. if ($this->options['type'] != 'textfield') { return; @@ -215,8 +214,8 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on return TRUE; } - // If it's optional and there's no value don't bother filtering. - if ($this->options['expose']['optional'] && empty($this->validated_exposed_input)) { + // If it's non-required and there's no value don't bother filtering. + if (!$this->options['expose']['required'] && empty($this->validated_exposed_input)) { return FALSE; } @@ -307,8 +306,8 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on // prevent array_filter from messing up our arrays in parent submit. } - function expose_form_right(&$form, &$form_state) { - parent::expose_form_right($form, $form_state); + function expose_form(&$form, &$form_state) { + parent::expose_form($form, $form_state); if ($this->options['type'] != 'select') { unset($form['expose']['reduce']); } 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 b00d59bafb11fd9c3e2252428ba482f0f8d8a601..a718ec2eff8af9ec0b2a9b475179c3505ccd018b 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_term_node_tid_depth.inc,v 1.1.6.4 2010/09/09 21:31:49 dereine Exp $ /** * Filter handler for taxonomy terms with depth. * @@ -38,6 +37,10 @@ class views_handler_filter_term_node_tid_depth extends views_handler_filter_term return; } elseif (count($this->value) == 1) { + // Somethis $this->value is an array with a single element so convert it. + if (is_array($this->value)) { + $this->value = current($this->value); + } $operator = '='; } else { 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 2fc68e88f0ede189ebe6ce12e9c13d65dd1289e6..e75d6a730230ddb7bead5b80544178d55b056e0a 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,5 +1,4 @@ <?php -// $Id: views_handler_filter_vocabulary_machine_name.inc,v 1.1.2.1 2010/10/17 10:48:08 dereine Exp $ /** * Filter by vocabulary machine name 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 0afdfe532801dd78c7578d9e855f4ab2d3008931..cb624dca28ed4c4d4de63c3d8c6d01c0e71b260e 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,5 +1,4 @@ <?php -// $Id: views_handler_filter_vocabulary_vid.inc,v 1.3.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * Filter by vocabulary id 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 558ed550ed13937f4fded63a3e55a0892e9eacd7..2f013daf7c6ba89ff412c654c7d824b468000992 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_relationship_node_term_data.inc,v 1.3.4.3 2010/10/07 19:40:02 dereine Exp $ /** * @file * Views' relationship handlers. @@ -26,12 +25,7 @@ class views_handler_relationship_node_term_data extends views_handler_relationsh return $options; } - /** - * Default options form that provides the label widget that all fields - * should have. - */ function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $vocabularies = taxonomy_get_vocabularies(); $options = array(); foreach ($vocabularies as $voc) { @@ -45,6 +39,7 @@ class views_handler_relationship_node_term_data extends views_handler_relationsh '#default_value' => $this->options['vocabularies'], '#description' => t('Choose which vocabularies you wish to relate. Remember that every term found will create a new record, so this relationship is best used on just one vocabulary that has only one term per node.'), ); + parent::options_form($form, $form_state); } /** diff --git a/sites/all/modules/views/modules/taxonomy/views_plugin_argument_default_taxonomy_tid.inc b/sites/all/modules/views/modules/taxonomy/views_plugin_argument_default_taxonomy_tid.inc index eb743c612b0faf7ea3ba622eea5e968c039709ec..5026e54c7f25fd9f2b38446026277cf251226379 100644 --- a/sites/all/modules/views/modules/taxonomy/views_plugin_argument_default_taxonomy_tid.inc +++ b/sites/all/modules/views/modules/taxonomy/views_plugin_argument_default_taxonomy_tid.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_default_taxonomy_tid.inc,v 1.1.2.9 2010/12/03 20:17:14 dereine Exp $ /** * @file * Taxonomy tid default argument. @@ -34,12 +33,12 @@ class views_plugin_argument_default_taxonomy_tid extends views_plugin_argument_d function options_form(&$form, &$form_state) { $form['term_page'] = array( '#type' => 'checkbox', - '#title' => t('Load default argument from term page'), + '#title' => t('Load default filter from term page'), '#default_value' => $this->options['term_page'], ); $form['node'] = array( '#type' => 'checkbox', - '#title' => t('Load default argument from node page, thats good for related taxonomy blocks.'), + '#title' => t('Load default filter from node page, that\'s good for related taxonomy blocks.'), '#default_value' => $this->options['node'], ); @@ -125,6 +124,13 @@ class views_plugin_argument_default_taxonomy_tid extends views_plugin_argument_d } } } + + // If the current page is a view that takes tid as an argument, + // find the tid argument and return it. + $views_page = views_get_page_view(); + if ($views_page && isset($views_page->view->argument['tid'])) { + return $views_page->view->argument['tid']->argument; + } } } diff --git a/sites/all/modules/views/modules/taxonomy/views_plugin_argument_validate_taxonomy_term.inc b/sites/all/modules/views/modules/taxonomy/views_plugin_argument_validate_taxonomy_term.inc index 6c046ea3b8c99622a3e7e7f4fa01068cf7d7ae88..d4318c085e2edf3ed1058d7857ce80d2df97d9b3 100644 --- a/sites/all/modules/views/modules/taxonomy/views_plugin_argument_validate_taxonomy_term.inc +++ b/sites/all/modules/views/modules/taxonomy/views_plugin_argument_validate_taxonomy_term.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_validate_taxonomy_term.inc,v 1.6.4.8 2010/12/14 22:32:11 dereine Exp $ /** * @file * Contains the 'taxonomy term' argument validator plugin. @@ -51,7 +50,7 @@ class views_plugin_argument_validate_taxonomy_term extends views_plugin_argument $form['type'] = array( '#type' => 'select', - '#title' => t('Argument type'), + '#title' => t('Filter value type'), '#options' => array( 'tid' => t('Term ID'), 'tids' => t('Term IDs separated by , or +'), @@ -59,12 +58,12 @@ class views_plugin_argument_validate_taxonomy_term extends views_plugin_argument 'convert' => t('Term name converted to Term ID'), ), '#default_value' => $this->options['type'], - '#description' => t('Select the form of this argument; if using term name, it is generally more efficient to convert it to a term ID and use Taxonomy: Term ID rather than Taxonomy: Term Name" as an argument.'), + '#description' => t('Select the form of this filter value; if using term name, it is generally more efficient to convert it to a term ID and use Taxonomy: Term ID rather than Taxonomy: Term Name" as the filter.'), ); $form['transform'] = array( '#type' => 'checkbox', - '#title' => t('Transform dashes in URL to spaces in term name arguments'), + '#title' => t('Transform dashes in URL to spaces in term name filter values'), '#default_value' => $this->options['transform'], ); } @@ -178,8 +177,8 @@ class views_plugin_argument_validate_taxonomy_term extends views_plugin_argument if ($term && (empty($vocabularies) || !empty($vocabularies[$term->machine_name]))) { if ($type == 'convert') { $this->argument->argument = $term->tid; - $this->argument->validated_title = check_plain($term->name); } + $this->argument->validated_title = check_plain($term->name); return TRUE; } return FALSE; diff --git a/sites/all/modules/views/modules/translation.views.inc b/sites/all/modules/views/modules/translation.views.inc index f47ddd1c01d0e5f48c3fb3f79764238b2e7da8fd..8189faab6f29762dc025c94663f8fb054c37f6ad 100644 --- a/sites/all/modules/views/modules/translation.views.inc +++ b/sites/all/modules/views/modules/translation.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: translation.views.inc,v 1.8.6.5 2010/12/09 01:10:24 merlinofchaos Exp $ /** * @file @@ -28,7 +27,7 @@ function translation_views_data_alter(&$data) { // Language field $data['node']['language'] = array( - 'group' => t('Node translation'), + 'group' => t('Content translation'), 'title' => t('Language'), 'help' => t('The language the content is in.'), 'field' => array( @@ -48,7 +47,7 @@ function translation_views_data_alter(&$data) { // The translation ID (nid of the "source" translation) $data['node']['tnid'] = array( - 'group' => t('Node translation'), + 'group' => t('Content translation'), 'title' => t('Translation set node ID'), 'help' => t('The ID of the translation set the content belongs to.'), 'field' => array( @@ -79,7 +78,7 @@ function translation_views_data_alter(&$data) { // The source translation. $data['node']['translation'] = array( - 'group' => t('Node translation'), + 'group' => t('Content translation'), 'title' => t('Translations'), 'help' => t('Versions of content in different languages.'), 'relationship' => array( @@ -96,9 +95,9 @@ function translation_views_data_alter(&$data) { // The source translation. $data['node']['source_translation'] = array( - 'group' => t('Node translation'), + 'group' => t('Content translation'), 'title' => t('Source translation'), - 'help' => t('Nodes that are either untranslated or are the original versions of a translation set.'), + 'help' => t('Content that is either untranslated or is the original version of a translation set.'), 'filter' => array( 'handler' => 'views_handler_filter_node_tnid', ), @@ -108,7 +107,7 @@ function translation_views_data_alter(&$data) { $data['node']['child_translation'] = array( 'group' => t('Node translation'), 'title' => t('Child translation'), - 'help' => t('Nodes that are translations of a source translation.'), + 'help' => t('Content that is a translation of a source translation.'), 'filter' => array( 'handler' => 'views_handler_filter_node_tnid_child', ), @@ -116,9 +115,9 @@ function translation_views_data_alter(&$data) { // Translation status $data['node']['translate'] = array( - 'group' => t('Node translation'), + 'group' => t('Content translation'), 'title' => t('Translation status'), - 'help' => t('The translation status of the node--whether or not the translation needs to be updated.'), + 'help' => t('The translation status of the content - whether or not the translation needs to be updated.'), 'field' => array( 'handler' => 'views_handler_field_boolean', 'click sortable' => TRUE, @@ -135,7 +134,7 @@ function translation_views_data_alter(&$data) { // Translate node link. $data['node']['translate_node'] = array( - 'group' => t('Node translation'), + 'group' => t('Content translation'), 'title' => t('Translate link'), 'help' => t('Provide a simple link to translate the node.'), 'field' => array( 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 d9699a0bd0715f52591927383361de30f0f620a3..22c4eb0deddaf2a37b4259497a0bcf688a694d85 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_node_tnid.inc,v 1.1.6.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * @file * Provide node tnid argument handler. 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 5e7cbfdf13145700bd26b5d95d8c0bd9e07b2dde..3177ce4a774edece3a049158174d7459c4a86027 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 @@ -1,13 +1,30 @@ <?php -// $Id: views_handler_field_node_language.inc,v 1.2 2008/10/28 17:46:14 merlinofchaos Exp $ /** * Field handler to translate a language into its readable form. */ class views_handler_field_node_language extends views_handler_field_node { + function option_definition() { + $options = parent::option_definition(); + $options['native_language'] = array('default' => FALSE); + + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $form['native_language'] = array( + '#title' => t('Native language'), + '#type' => 'checkbox', + '#default_value' => $this->options['native_language'], + '#description' => t('If enabled, the native name of the language will be displayed'), + ); + } + function render($values) { - $languages = locale_language_list(); - $value = isset($languages[$values->{$this->field_alias}]) ? $languages[$values->{$this->field_alias}] : ''; + $languages = locale_language_list(empty($this->options['native_language']) ? 'name' : 'native'); + $value = $this->get_value($values); + $value = isset($languages[$value]) ? $languages[$value] : ''; return $this->render_link($value, $values); } } 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 6cdf3136172f03e5392d3fd0c9be9242128360f7..105041fef447611ee5f9d73278673a7d0e60de3f 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,5 +1,4 @@ <?php -// $Id: views_handler_field_node_link_translate.inc,v 1.1.6.2 2010/05/11 21:41:18 dereine Exp $ /** * Field handler to present a link node translate. */ @@ -15,11 +14,11 @@ class views_handler_field_node_link_translate extends views_handler_field_node_l function render($values) { // ensure user has access to edit this node. $node = new stdClass(); - $node->nid = $values->{$this->aliases['nid']}; - $node->uid = $values->{$this->aliases['uid']}; - $node->type = $values->{$this->aliases['type']}; - $node->format = $values->{$this->aliases['format']}; - $node->language = $values->{$this->aliases['language']}; + $node->nid = $this->get_value($values, 'nid'); + $node->uid = $this->get_value($values, 'uid'); + $node->type = $this->get_value($values, 'type'); + $node->format = $this->get_value($values, 'format'); + $node->language = $this->get_value($values, 'language'); $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 356ba13a4c38f04fc997e1c98d897350256b007d..cefeec0b922df3433fa1696ada5002f23965b062 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,5 +1,4 @@ <?php -// $Id: views_handler_field_node_translation_link.inc,v 1.1.6.3 2010/12/09 21:45:49 dereine Exp $ /** * Field handler to present a link to the node. */ @@ -18,14 +17,16 @@ class views_handler_field_node_translation_link extends views_handler_field { } function render($values) { - return $this->render_link(check_plain($values->{$this->aliases['tnid']}), $values); + $value = $this->get_value($values, 'tnid'); + return $this->render_link($this->sanitize_value($value), $values); } function render_link($data, $values) { global $language; - $tnid = $values->{$this->aliases['tnid']}; + + $tnid = $this->get_value($values, 'tnid'); // Only load translations if the node isn't in the current language. - if ($values->{$this->aliases['language']} != $language->language) { + if ($this->get_value($values, 'language') != $language->language) { $translations = translation_node_get_translations($tnid); if (isset($translations[$language->language])) { $values->{$this->aliases['nid']} = $translations[$language->language]->nid; @@ -34,7 +35,7 @@ class views_handler_field_node_translation_link extends views_handler_field { } $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = "node/" . $values->{$this->aliases['nid']}; - return $values->{$this->aliases['title']}; + $this->options['alter']['path'] = "node/" . $this->get_value($values, 'nid'); + return $this->get_value($values, 'title'); } } 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 1da3b98a59a213f2d1dd95e2ceb6d9affcc1fc0b..034d0fcbf9ffb584360928159ab28ca8ae2bf632 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,5 +1,4 @@ <?php -// $Id: views_handler_filter_node_language.inc,v 1.1.6.1 2011/01/06 00:37:05 dereine Exp $ /** * Filter by language */ 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 47fce79f65ebc0b33ea20399cec1558f38a3e795..b47847bb2e8e6f0a42d7259a621a775a74dc6d5e 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,5 +1,4 @@ <?php -// $Id: views_handler_filter_node_tnid.inc,v 1.1 2008/12/02 16:34:24 merlinofchaos Exp $ /** * Filter by whether the node is the original translation. */ @@ -19,7 +18,7 @@ class views_handler_filter_node_tnid extends views_handler_filter { function operator_form(&$form, &$form_state) { $form['operator'] = array( '#type' => 'radios', - '#title' => t('Include untranslated nodes'), + '#title' => t('Include untranslated content'), '#default_value' => $this->operator, '#options' => array( 1 => t('Yes'), @@ -35,5 +34,4 @@ class views_handler_filter_node_tnid extends views_handler_filter { // Select for source translations (tnid = nid). Conditionally, also accept either untranslated nodes (tnid = 0). $this->query->add_where($this->options['group'], "$table.tnid = $table.nid" . ($this->operator ? " OR $table.tnid = 0" : '')); } -} - +} \ No newline at end of file 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 6a35c2ebf38b08715d2099ac5a856c5dcb72a2db..d35aff7ffbbc514ce551dfca747fa387735239c5 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,5 +1,4 @@ <?php -// $Id: views_handler_filter_node_tnid_child.inc,v 1.1 2008/12/02 18:57:27 merlinofchaos Exp $ /** * Filter by whether the node is not the original translation. */ 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 448de5a6376de90cd76d931f576bee89047d9345..ab47132369d62b46efb1e9b1101b8c5adcbde022 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_relationship_translation.inc,v 1.1 2008/09/30 22:07:15 merlinofchaos Exp $ /** * Handles relationships for content translation sets and provides multiple diff --git a/sites/all/modules/views/modules/upload.views.inc b/sites/all/modules/views/modules/upload.views.inc index 57f3f31ceaf53677df1aa1afb1d7cda30ab77a4f..198b64e7c3b560b8f5110f4423bbe2f73cb879c5 100644 --- a/sites/all/modules/views/modules/upload.views.inc +++ b/sites/all/modules/views/modules/upload.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: upload.views.inc,v 1.16.4.5 2010/07/19 09:18:42 dereine Exp $ /** * @file * @@ -40,8 +39,8 @@ function upload_views_data() { ); $data['upload']['vid'] = array( - 'title' => t('Node'), - 'help' => t('The node the uploaded file is attached to'), + 'title' => t('Content'), + 'help' => t('The content the uploaded file is attached to'), 'relationship' => array( 'label' => t('upload'), 'base' => 'node', diff --git a/sites/all/modules/views/modules/upload.views_convert.inc b/sites/all/modules/views/modules/upload.views_convert.inc index 1ee2b2e23cdaf7ccc987c98fa0cef7ea559ad2d0..27e80650fddfe6e808d21cb4eec275b50234ec77 100644 --- a/sites/all/modules/views/modules/upload.views_convert.inc +++ b/sites/all/modules/views/modules/upload.views_convert.inc @@ -1,5 +1,4 @@ <?php -//$Id: upload.views_convert.inc,v 1.4.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * @file diff --git a/sites/all/modules/views/modules/upload/views_handler_field_upload_description.inc b/sites/all/modules/views/modules/upload/views_handler_field_upload_description.inc index 24ecc0c25bb4d6a6f7eff4db36838ed757b7ce44..d978433ea5a23c18c84df3b67dee7d3a5b2ae213 100644 --- a/sites/all/modules/views/modules/upload/views_handler_field_upload_description.inc +++ b/sites/all/modules/views/modules/upload/views_handler_field_upload_description.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_upload_description.inc,v 1.5.4.3 2010/12/03 20:46:32 dereine Exp $ /** * Field handler to provide a list of roles. @@ -51,7 +50,8 @@ class views_handler_field_upload_description extends views_handler_field { } function render($values) { - return $this->render_link(check_plain($values->{$this->field_alias}), $values); + $value = $this->get_value($values); + return $this->render_link($this->sanitize_value($value), $values); } /** @@ -59,9 +59,10 @@ class views_handler_field_upload_description extends views_handler_field { * * Data should be made XSS safe prior to calling this function. */ - function render_link($data, $value) { - if (!empty($this->options['link_to_file']) && $value->{$this->aliases['fid']} && $data !== NULL && $data !== '') { - $values = $this->items[$value->{$this->aliases['fid']}]; + function render_link($data, $values) { + $fid = $this->get_value($values, 'fid'); + if (!empty($this->options['link_to_file']) && $fid && $data !== NULL && $data !== '') { + $values = $this->items[$fid]; $this->options['alter']['make_link'] = TRUE; $this->options['alter']['path'] = file_create_url($values->uri); } diff --git a/sites/all/modules/views/modules/upload/views_handler_field_upload_fid.inc b/sites/all/modules/views/modules/upload/views_handler_field_upload_fid.inc index 566cfe21893f0e2ceec96c8b7989dcd98a9b5e8f..1e2a1f6f8468416f44756648fa6743e9e0890c34 100644 --- a/sites/all/modules/views/modules/upload/views_handler_field_upload_fid.inc +++ b/sites/all/modules/views/modules/upload/views_handler_field_upload_fid.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_upload_fid.inc,v 1.10.4.5 2010/12/03 20:46:32 dereine Exp $ /** * Field handler to provide a list of roles. */ diff --git a/sites/all/modules/views/modules/upload/views_handler_filter_upload_fid.inc b/sites/all/modules/views/modules/upload/views_handler_filter_upload_fid.inc index e05ce80f4ca9be73bc4eda1e56a4dc921b14ea87..31a95709475e818ca715587a74ff75e85025ed1e 100644 --- a/sites/all/modules/views/modules/upload/views_handler_filter_upload_fid.inc +++ b/sites/all/modules/views/modules/upload/views_handler_filter_upload_fid.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_upload_fid.inc,v 1.1 2008/09/03 19:21:30 merlinofchaos Exp $ /** * Filter by whether or not a node has attached files from the upload module diff --git a/sites/all/modules/views/modules/user.views.inc b/sites/all/modules/views/modules/user.views.inc index 68a60e4fac272721a0cbd333bf96745c1cda5947..0029fcf9824fadf18e45901c51d684ed1cd09f48 100644 --- a/sites/all/modules/views/modules/user.views.inc +++ b/sites/all/modules/views/modules/user.views.inc @@ -1,5 +1,4 @@ <?php -//$Id: user.views.inc,v 1.59.4.13 2010/09/22 21:31:29 dereine Exp $ /** * @file * Provide views data and handlers for user.module @@ -64,8 +63,8 @@ function user_views_data() { 'handler' => 'views_handler_sort', ), 'relationship' => array( - 'title' => t('Nodes authored'), - 'help' => t('Relate nodes to the user who created it. This relationship will create one record for every node created by the user.'), + 'title' => t('Content authored'), + 'help' => t('Relate content to the user who created it. This relationship will create one record for each content item created by the user.'), 'handler' => 'views_handler_relationship', 'base' => 'node', 'base field' => 'uid', @@ -146,6 +145,7 @@ function user_views_data() { ); // picture + $data['users']['picture_fid']['moved to'] = array('users', 'picture'); $data['users']['picture'] = array( 'title' => t('Picture'), 'help' => t("The user's picture, if allowed."), // The help that appears on the UI, @@ -158,13 +158,13 @@ function user_views_data() { 'handler' => 'views_handler_sort', ), 'filter' => array( - 'handler' => 'views_handler_filter_boolean_operator_string', + 'handler' => 'views_handler_filter_boolean_operator', 'label' => t('Has Avatar'), 'type' => 'yes-no', ), ); - // created field + // created field $data['users']['created'] = array( 'title' => t('Created date'), // The item it appears as on the UI, 'help' => t('The date the user was created.'), // The help that appears on the UI, @@ -180,6 +180,60 @@ function user_views_data() { ), ); + $data['users']['created_fulldate'] = array( + 'title' => t('Created date'), + 'help' => t('In the form of CCYYMMDD.'), + 'argument' => array( + 'field' => 'created', + 'handler' => 'views_handler_argument_node_created_fulldate', + ), + ); + + $data['users']['created_year_month'] = array( + 'title' => t('Created year + month'), + 'help' => t('In the form of YYYYMM.'), + 'argument' => array( + 'field' => 'created', + 'handler' => 'views_handler_argument_node_created_year_month', + ), + ); + + $data['users']['timestamp_year'] = array( + 'title' => t('Created year'), + 'help' => t('In the form of YYYY.'), + 'argument' => array( + 'field' => 'created', + 'handler' => 'views_handler_argument_node_created_year', + ), + ); + + $data['users']['created_month'] = array( + 'title' => t('Created month'), + 'help' => t('In the form of MM (01 - 12).'), + 'argument' => array( + 'field' => 'created', + 'handler' => 'views_handler_argument_node_created_month', + ), + ); + + $data['users']['created_day'] = array( + 'title' => t('Created day'), + 'help' => t('In the form of DD (01 - 31).'), + 'argument' => array( + 'field' => 'created', + 'handler' => 'views_handler_argument_node_created_day', + ), + ); + + $data['users']['created_week'] = array( + 'title' => t('Created week'), + 'help' => t('In the form of WW (01 - 53).'), + 'argument' => array( + 'field' => 'timestamp', + 'handler' => 'views_handler_argument_node_created_week', + ), + ); + // access field $data['users']['access'] = array( 'title' => t('Last access'), // The item it appears as on the UI, @@ -253,11 +307,19 @@ function user_views_data() { ), ); - $data['users']['delete_node'] = array( + $data['users']['cancel_node'] = array( + 'field' => array( + 'title' => t('Cancel link'), + 'help' => t('Provide a simple link to cancel the user.'), + 'handler' => 'views_handler_field_user_link_cancel', + ), + ); + + $data['users']['data'] = array( + 'title' => t('Data'), + 'help' => t('Provide serialized data of the user'), 'field' => array( - 'title' => t('Delete link'), - 'help' => t('Provide a simple link to delete the user.'), - 'handler' => 'views_handler_field_user_link_delete', + 'handler' => 'views_handler_field_serialized', ), ); diff --git a/sites/all/modules/views/modules/user.views_convert.inc b/sites/all/modules/views/modules/user.views_convert.inc index 4d5f95307edaf7be05a905d829f41275a5eaac31..dd67d47e93b45426abf2a8f930a11e327c183e0d 100644 --- a/sites/all/modules/views/modules/user.views_convert.inc +++ b/sites/all/modules/views/modules/user.views_convert.inc @@ -1,5 +1,4 @@ <?php -// $Id: user.views_convert.inc,v 1.3.4.1 2009/11/02 22:01:26 merlinofchaos Exp $ /** * @file 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 a53456a20dd258dee619d0b06bf7aacb7146f551..f4cb423c4c8836442310f4f89d7c876192642109 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_user_uid.inc,v 1.1.6.1 2009/11/02 22:01:27 merlinofchaos Exp $ /** * @file * Provide user uid argument handler. 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 1657d68e684e839225e845dd638ce129f1924080..b5ccf12feee1aaae03bee872a00a64b1142c5634 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,5 +1,4 @@ <?php -// $Id: views_handler_argument_users_roles_rid.inc,v 1.1.6.1 2009/11/02 22:01:27 merlinofchaos Exp $ /** * Allow role ID(s) as argument */ 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 ebf1de2a3c2f819ca3ef9cd543c5c74a89169fc0..e88033a9e8937d71a0621fcb7f58a736532d85fc 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_user.inc,v 1.3 2009/01/30 00:01:42 merlinofchaos Exp $ /** * Field handler to provide simple renderer that allows linking to a user. @@ -25,24 +24,25 @@ class views_handler_field_user extends views_handler_field { * Provide link to node option */ function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['link_to_user'] = array( '#title' => t('Link this field to its user'), - '#description' => t('This will override any other link you have set.'), + '#description' => t("Enable to override this field's links."), '#type' => 'checkbox', '#default_value' => $this->options['link_to_user'], ); + parent::options_form($form, $form_state); } function render_link($data, $values) { - if (!empty($this->options['link_to_user']) && user_access('access user profiles') && $values->{$this->aliases['uid']} && $data !== NULL && $data !== '') { + if (!empty($this->options['link_to_user']) && user_access('access user profiles') && ($uid = $this->get_value($values, 'uid')) && $data !== NULL && $data !== '') { $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = "user/" . $values->{$this->aliases['uid']}; + $this->options['alter']['path'] = "user/" . $uid; } return $data; } function render($values) { - return $this->render_link(check_plain($values->{$this->field_alias}), $values); + $value = $this->get_value($values); + return $this->render_link($this->sanitize_value($value), $values); } } 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 850911cc41ad99bbafe862d2846459ac74f0d0a9..3d3e7228778b307929c90bb82d1d1fbfff57281c 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,5 +1,4 @@ <?php -// $Id: views_handler_field_user_language.inc,v 1.1.6.1 2009/11/02 22:01:27 merlinofchaos Exp $ /** * @file * Views field handler for userlanguage. @@ -8,9 +7,10 @@ class views_handler_field_user_language extends views_handler_field_user { function render_link($data, $values) { - if (!empty($this->options['link_to_user']) && user_access('access user profiles') && $values->{$this->aliases['uid']}) { + $uid = $this->get_value($values, 'uid'); + if (!empty($this->options['link_to_user']) && user_access('access user profiles') && $uid) { $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = 'user/' . $values->{$this->aliases['uid']}; + $this->options['alter']['path'] = 'user/' . $uid; } if (empty($data)) { $lang = language_default(); @@ -20,10 +20,11 @@ class views_handler_field_user_language extends views_handler_field_user { $lang = $lang[$data]; } - return check_plain($lang->name); + return $this->sanitize_value($lang->name); } function render($values) { - return $this->render_link(check_plain($values->{$this->field_alias}), $values); + $value = $this->get_value($values); + return $this->render_link($this->sanitize_value($value), $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 98e7e71fdc05aec9cd9f515fdcf77dae11ed4534..7f26f060d2dbf13d594a55fd6ce302abd67004c3 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,5 +1,4 @@ <?php -// $Id: views_handler_field_user_link.inc,v 1.1.6.2 2010/11/30 20:36:01 merlinofchaos Exp $ /** * Field handler to present a link to the user. */ @@ -16,12 +15,12 @@ class views_handler_field_user_link extends views_handler_field { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['text'] = array( '#type' => 'textfield', '#title' => t('Text to display'), '#default_value' => $this->options['text'], ); + parent::options_form($form, $form_state); } // An example of field level access control. @@ -35,15 +34,15 @@ class views_handler_field_user_link extends views_handler_field { } function render($values) { - return $this->render_link(check_plain($values->{$this->aliases['uid']}), $values); + $value = $this->get_value($values, 'uid'); + return $this->render_link($this->sanitize_value($value), $values); } function render_link($data, $values) { - $uid = $values->{$this->aliases['uid']}; $text = !empty($this->options['text']) ? $this->options['text'] : t('view'); $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = "user/" . $uid; + $this->options['alter']['path'] = "user/" . $data; return $text; } 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 new file mode 100644 index 0000000000000000000000000000000000000000..d0c4ee7e82204d7eab1fbde48741cb7120dd7afe --- /dev/null +++ b/sites/all/modules/views/modules/user/views_handler_field_user_link_cancel.inc @@ -0,0 +1,26 @@ +<?php +/** + * Field handler to present a link to user cancel. + */ +class views_handler_field_user_link_cancel extends views_handler_field_user_link { + + function render_link($data, $values) { + $uid = $values->{$this->aliases['uid']}; + + // Build a pseudo account object to be able to check the access. + $account = new stdClass(); + $account->uid = $uid; + + if ($uid && user_cancel_access($account)) { + $this->options['alter']['make_link'] = TRUE; + + $text = !empty($this->options['text']) ? $this->options['text'] : t('cancel'); + + $this->options['alter']['path'] = "user/$uid/cancel"; + $this->options['alter']['query'] = drupal_get_destination(); + + return $text; + } + } +} + 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 928070a35537a68c4223331162b742b2c527ed22..bdeecf0dc2c394477ba3ac883801d115c55b7fd6 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,26 +1,22 @@ <?php -// $Id: views_handler_field_user_link_edit.inc,v 1.1.6.2 2010/11/18 07:29:03 dereine Exp $ /** * Field handler to present a link to user edit. */ class views_handler_field_user_link_edit extends views_handler_field_user_link { - function render_link($data, $values) { - $uid = $values->{$this->aliases['uid']}; // Build a pseudo account object to be able to check the access. $account = new stdClass(); - $account->uid = $uid; + $account->uid = $data; - if ($uid && user_edit_access($account)) { + if ($data && user_edit_access($account)) { $this->options['alter']['make_link'] = TRUE; $text = !empty($this->options['text']) ? $this->options['text'] : t('edit'); - $this->options['alter']['path'] = "user/$uid/edit"; + $this->options['alter']['path'] = "user/$data/edit"; $this->options['alter']['query'] = drupal_get_destination(); return $text; } } } - 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 013f0aaaa8df4679be19a235fb4402aacf19461b..cf55366b4dfe0a8959541ccf4599e3f0898b9288 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,5 +1,4 @@ <?php -// $Id: views_handler_field_user_mail.inc,v 1.1.6.1 2010/11/18 07:29:03 dereine Exp $ /** * Field handler to provide acess control for the email field */ @@ -11,7 +10,6 @@ class views_handler_field_user_mail extends views_handler_field_user { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); $form['link_to_user'] = array( '#title' => t('Link this field'), '#type' => 'radios', @@ -22,10 +20,11 @@ class views_handler_field_user_mail extends views_handler_field_user { ), '#default_value' => $this->options['link_to_user'], ); + parent::options_form($form, $form_state); } function render_link($data, $values) { - parent::render_link(check_plain($values->{$this->field_alias}), $values); + parent::render_link($data, $values); if ($this->options['link_to_user'] == 'mailto') { $this->options['alter']['make_link'] = TRUE; 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 6008eb6e2e1f1d207c76ee5093331c96ebff9b9b..3b04dd1e58824f7c3a5f07b0b05995fd4c2872fb 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,5 +1,4 @@ <?php -// $Id: views_handler_field_user_name.inc,v 1.2.6.3 2010/11/05 07:20:54 dereine Exp $ /** * Field handler to provide simple renderer that allows using a themed user link */ @@ -24,13 +23,12 @@ class views_handler_field_user_name extends views_handler_field_user { } function options_form(&$form, &$form_state) { - parent::options_form($form, $form_state); - $form['overwrite_anonymous'] = array( '#title' => t('Overwrite the value to display for anonymous users'), '#type' => 'checkbox', '#default_value' => !empty($this->options['overwrite_anonymous']), - '#description' => t('If selected, you will see a field to enter the text to use for anonymous users.'), + '#description' => t('Enable to display different text for anonymous users.'), + '#fieldset' => 'more', ); $form['anonymous_text'] = array( '#title' => t('Text to display for anonymous users'), @@ -40,19 +38,22 @@ class views_handler_field_user_name extends views_handler_field_user { '#dependency' => array( 'edit-options-overwrite-anonymous' => array(1), ), + '#fieldset' => 'more', ); + + parent::options_form($form, $form_state); } function render_link($data, $values) { if (!empty($this->options['link_to_user']) || !empty($this->options['overwrite_anonymous'])) { $account = new stdClass(); - $account->uid = $values->{$this->aliases['uid']}; + $account->uid = $this->get_value($values, 'uid'); if (!empty($this->options['overwrite_anonymous']) && !$account->uid) { // This is an anonymous user, and we're overriting the text. return check_plain($this->options['anonymous_text']); } elseif (!empty($this->options['link_to_user'])) { - $account->name = $values->{$this->field_alias}; + $account->name = $this->get_value($values); return theme('username', array('account' => $account)); } } 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 2a470ed980522c19eeb360e9ad48aaa080439a7f..60e09cdd3cf49107dd5fc9ba6fb4fdcff66bc12f 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,5 +1,4 @@ <?php -// $Id: views_handler_field_user_picture.inc,v 1.1.6.5 2010/12/16 18:23:42 dereine Exp $ /** * Field handler to provide simple renderer that allows using a themed user link @@ -19,10 +18,10 @@ class views_handler_field_user_picture extends views_handler_field { function render($values) { // Fake an account object. $account = new stdClass(); - $account->uid = $values->{$this->aliases['uid']}; - $account->name = $values->{$this->aliases['name']}; - $account->mail = $values->{$this->aliases['mail']}; - $account->picture = $values->{$this->field_alias}; + $account->uid = $this->get_value($values, 'uid'); + $account->name = $this->get_value($values, 'name'); + $account->mail = $this->get_value($values, 'mail'); + $account->picture = $this->get_value($values); return theme('user_picture', array('account' => $account)); } 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 f121f21c228ff0c7edb335b6bcdc31b9df45f198..592c10fff8dc87eca237a2d82c50f6a2b0af461a 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,5 +1,4 @@ <?php -// $Id: views_handler_field_user_roles.inc,v 1.2.4.2 2010/12/03 20:46:32 dereine Exp $ /** * Field handler to provide a list of roles. */ @@ -19,7 +18,7 @@ class views_handler_field_user_roles extends views_handler_field_prerender_list $this->items = array(); foreach ($values as $result) { - $uids[] = $result->{$this->aliases['uid']}; + $uids[] = $this->get_value($result); } if ($uids) { 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 e1dfb75bce40e8c6b741edd88d0cfe5fe3930d46..ee119619eae655c07075bfb810450544c4e2de11 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,5 +1,4 @@ <?php -// $Id: views_handler_filter_user_current.inc,v 1.2.4.2 2010/09/24 05:34:15 dereine Exp $ /** * Filter handler for the current user 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 a38a97f33607a6a1c0190c427d21268c2127a1f7..2fce71ab89f6385df8711fb24fc5dce63eee5592 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,11 +1,10 @@ <?php -// $Id: views_handler_filter_user_name.inc,v 1.2.6.2 2010/08/26 09:41:55 dereine Exp $ /** * Filter handler for usernames */ class views_handler_filter_user_name extends views_handler_filter_in_operator { - var $no_single = TRUE; + var $always_multiple = TRUE; function value_form(&$form, &$form_state) { $values = array(); 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 3978632970dd6efd449e6d3bfe473834e6faac89..3442aa9cfaca4da7defe760d43f77e4c0ed3008d 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,5 +1,4 @@ <?php -// $Id: views_handler_filter_user_roles.inc,v 1.1 2008/09/03 19:21:30 merlinofchaos Exp $ /** * Filter handler for user roles */ diff --git a/sites/all/modules/views/modules/user/views_plugin_argument_default_current_user.inc b/sites/all/modules/views/modules/user/views_plugin_argument_default_current_user.inc index f2ca6de414570fc508331b331f4a6f26c51acf79..631133e2daa1c20c5391295d717ebb5b6db7be9e 100644 --- a/sites/all/modules/views/modules/user/views_plugin_argument_default_current_user.inc +++ b/sites/all/modules/views/modules/user/views_plugin_argument_default_current_user.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_default_current_user.inc,v 1.1.6.1 2010/01/28 22:44:36 dereine Exp $ /** * @file * Contains the current user argument default plugin. diff --git a/sites/all/modules/views/modules/user/views_plugin_argument_default_user.inc b/sites/all/modules/views/modules/user/views_plugin_argument_default_user.inc index dee52c0b8bb30408dd804368fd64b5eab6f8aa8b..a2e1b4a76c2edffb06a3ab9bb9c7eceeb7bb0916 100644 --- a/sites/all/modules/views/modules/user/views_plugin_argument_default_user.inc +++ b/sites/all/modules/views/modules/user/views_plugin_argument_default_user.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_default_user.inc,v 1.1.6.2 2010/12/14 00:00:52 merlinofchaos Exp $ /** * @file * Contains the user from URL argument default plugin. @@ -66,6 +65,13 @@ class views_plugin_argument_default_user extends views_plugin_argument_default { } } } + + // If the current page is a view that takes uid as an argument, return the uid. + $views_page = views_get_page_view(); + + if ($views_page && isset($views_page->view->argument['uid'])) { + return $views_page->view->argument['uid']->argument; + } } } diff --git a/sites/all/modules/views/modules/user/views_plugin_argument_validate_user.inc b/sites/all/modules/views/modules/user/views_plugin_argument_validate_user.inc index 3cf78655bc994e7979e4c0bdaa6f0834a3e33507..28eaf40e7294d7ea83f24ba850e922c8dfd57916 100644 --- a/sites/all/modules/views/modules/user/views_plugin_argument_validate_user.inc +++ b/sites/all/modules/views/modules/user/views_plugin_argument_validate_user.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_validate_user.inc,v 1.2.6.10 2010/11/05 07:20:54 dereine Exp $ /** * Validate whether an argument is a valid user. @@ -21,7 +20,7 @@ class views_plugin_argument_validate_user extends views_plugin_argument_validate function options_form(&$form, &$form_state) { $form['type'] = array( '#type' => 'radios', - '#title' => t('Type of user argument to allow'), + '#title' => t('Type of user filter value to allow'), '#options' => array( 'uid' => t('Only allow numeric UIDs'), 'name' => t('Only allow string usernames'), @@ -38,20 +37,20 @@ class views_plugin_argument_validate_user extends views_plugin_argument_validate $form['roles'] = array( '#type' => 'checkboxes', - '#prefix' => '<div id="edit-options-argument-validate-user-roles-wrapper">', + '#prefix' => '<div id="edit-options-validate-options-user-roles-wrapper">', '#suffix' => '</div>', '#title' => t('Restrict to the selected roles'), - '#options' => user_roles(TRUE), + '#options' => array_map('check_plain', user_roles(TRUE)), '#default_value' => $this->options['roles'], '#description' => t('If no roles are selected, users from any role will be allowed.'), '#process' => array('form_process_checkboxes', 'ctools_dependent_process'), '#dependency' => array( - 'edit-options-argument-validate-user-restrict-roles' => array(1), + 'edit-options-validate-options-user-restrict-roles' => array(1), ), ); } - function options_submit(&$form, &$form_state, &$options) { + function options_submit(&$form, &$form_state, &$options = array()) { // filter trash out of the options so we don't store giant unnecessary arrays $options['roles'] = array_filter($options['roles']); } @@ -122,4 +121,3 @@ class views_plugin_argument_validate_user extends views_plugin_argument_validate return TRUE; } } - diff --git a/sites/all/modules/views/modules/views.views.inc b/sites/all/modules/views/modules/views.views.inc index e686c8c18d87de19f4658604e093009cfcb19880..bf90a4ef1072afee7d042b9ed19efd856c0edca1 100644 --- a/sites/all/modules/views/modules/views.views.inc +++ b/sites/all/modules/views/modules/views.views.inc @@ -1,5 +1,4 @@ <?php -// $Id: views.views.inc,v 1.7.4.4 2010/11/05 21:55:20 dereine Exp $ /** * @file * Provide views data and handlers that aren't tied to any other module. @@ -30,7 +29,7 @@ function views_views_data() { $data['views']['null'] = array( 'title' => t('Null'), - 'help' => t('Allow an argument to be ignored. The query will not be altered by this argument.'), + 'help' => t('Allow a contextual filter value to be ignored. The query will not be altered by this contextual filter value. Can be used when contextual filter values come from the URL, and a part of the URL needs to be ignored.'), 'argument' => array( 'handler' => 'views_handler_argument_null', ), @@ -60,6 +59,14 @@ function views_views_data() { ), ); + $data['views']['view'] = array( + 'title' => t('View area'), + 'help' => t('Insert a view inside an area.'), + 'area' => array( + 'handler' => 'views_handler_area_view', + ), + ); + 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 new file mode 100644 index 0000000000000000000000000000000000000000..9f5642e9fc747834c6dfa73ff06276e5014a990b --- /dev/null +++ b/sites/all/modules/views/plugins/export_ui/views_ui.class.php @@ -0,0 +1,390 @@ +<?php + +/** + * @file + * Contains the CTools Export UI integration code. + * + * Note that this is only a partial integration. + */ + +/** + * CTools Export UI class handler for Views UI. + */ +class views_ui extends ctools_export_ui { + + function init($plugin) { + // We modify the plugin info here so that we take the defaults and + // twiddle, rather than completely override them. + + // Reset the edit path to match what we're really using. + $plugin['menu']['items']['edit']['path'] = 'view/%ctools_export_ui/edit'; + $plugin['menu']['items']['clone']['path'] = 'view/%ctools_export_ui/clone'; + $plugin['menu']['items']['clone']['type'] = MENU_VISIBLE_IN_BREADCRUMB; + $plugin['menu']['items']['export']['path'] = 'view/%ctools_export_ui/export'; + $plugin['menu']['items']['export']['type'] = MENU_VISIBLE_IN_BREADCRUMB; + $plugin['menu']['items']['enable']['path'] = 'view/%ctools_export_ui/enable'; + $plugin['menu']['items']['disable']['path'] = 'view/%ctools_export_ui/disable'; + $plugin['menu']['items']['delete']['path'] = 'view/%ctools_export_ui/delete'; + $plugin['menu']['items']['delete']['type'] = MENU_VISIBLE_IN_BREADCRUMB; + $plugin['menu']['items']['revert']['path'] = 'view/%ctools_export_ui/revert'; + $plugin['menu']['items']['revert']['type'] = MENU_VISIBLE_IN_BREADCRUMB; + + $prefix_count = count(explode('/', $plugin['menu']['menu prefix'])); + $plugin['menu']['items']['add-template'] = array( + 'path' => 'template/%/add', + 'title' => 'Add from template', + 'page callback' => 'ctools_export_ui_switcher_page', + 'page arguments' => array($plugin['name'], 'add_template', $prefix_count + 2), + 'load arguments' => array($plugin['name']), + 'access callback' => 'ctools_export_ui_task_access', + 'access arguments' => array($plugin['name'], 'add_template', $prefix_count + 2), + 'type' => MENU_CALLBACK, + ); + + return parent::init($plugin); + } + + function hook_menu(&$items) { + // We are using our own 'edit' still, rather than having edit on this + // object (maybe in the future) so unset the edit callbacks: + + // We leave these to make sure the operations still exist in the plugin so + // that the path finder. + unset($this->plugin['menu']['items']['edit']); + unset($this->plugin['menu']['items']['add']); + unset($this->plugin['menu']['items']['import']); + unset($this->plugin['menu']['items']['edit callback']); + + parent::hook_menu($items); + } + + function list_form(&$form, &$form_state) { + $row_class = 'container-inline'; + if (!variable_get('views_ui_show_listing_filters', FALSE)) { + $row_class .= " element-invisible"; + } + + views_include('admin'); + + parent::list_form($form, $form_state); + + // ctools only has two rows. We want four. + // That's why we create our own structure. + $form['bottom row']['submit']['#attributes']['class'][] = 'js-hide'; + $form['first row'] = array( + '#prefix' => '<div class="' . $row_class . ' ctools-export-ui-row ctools-export-ui-first-row clearfix">', + '#suffix' => '</div>', + 'search' => $form['top row']['search'], + 'submit' => $form['bottom row']['submit'], + 'reset' => $form['bottom row']['reset'], + ); + $form['second row'] = array( + '#prefix' => '<div class="' . $row_class . ' ctools-export-ui-row ctools-export-ui-second-row clearfix">', + '#suffix' => '</div>', + 'storage' => $form['top row']['storage'], + 'disabled' => $form['top row']['disabled'], + ); + $form['third row'] = array( + '#prefix' => '<div class="' . $row_class . ' ctools-export-ui-row ctools-export-ui-third-row clearfix element-hidden">', + '#suffix' => '</div>', + 'order' => $form['bottom row']['order'], + 'sort' => $form['bottom row']['sort'], + ); + unset($form['top row']); + unset($form['bottom row']); + + // Modify the look and contents of existing form elements. + $form['second row']['storage']['#title'] = ''; + $form['second row']['storage']['#options'] = array( + 'all' => t('All storage'), + t('Normal') => t('In database'), + t('Default') => t('In code'), + t('Overridden') => t('Database overriding code'), + ); + $form['second row']['disabled']['#title'] = ''; + $form['second row']['disabled']['#options']['all'] = t('All status'); + $form['third row']['sort']['#title'] = ''; + + // And finally, add our own. + $this->bases = array(); + foreach (views_fetch_base_tables() as $table => $info) { + $this->bases[$table] = $info['title']; + } + + $form['second row']['base'] = array( + '#type' => 'select', + '#options' => array_merge(array('all' => t('All types')), $this->bases), + '#default_value' => 'all', + '#weight' => -1, + ); + + $tags = array(); + if (isset($form_state['views'])) { + foreach ($form_state['views'] as $name => $view) { + if (!empty($view->tag)) { + $tags[$view->tag] = $view->tag; + } + } + } + asort($tags); + + $form['second row']['tag'] = array( + '#type' => 'select', + '#title' => t('Filter'), + '#options' => array_merge(array('all' => t('All tags')), array('none' => t('No tags')), $tags), + '#default_value' => 'all', + '#weight' => -9, + ); + + $displays = array(); + foreach (views_fetch_plugin_data('display') as $id => $info) { + if (!empty($info['admin'])) { + $displays[$id] = $info['admin']; + } + } + asort($displays); + + $form['second row']['display'] = array( + '#type' => 'select', + '#options' => array_merge(array('all' => t('All displays')), $displays), + '#default_value' => 'all', + '#weight' => -1, + ); + } + + function list_filter($form_state, $view) { + if ($form_state['values']['base'] != 'all' && $form_state['values']['base'] != $view->base_table) { + return TRUE; + } + + return parent::list_filter($form_state, $view); + } + + function list_sort_options() { + return array( + 'disabled' => t('Enabled, name'), + 'name' => t('Name'), + 'path' => t('Path'), + 'tag' => t('Tag'), + 'storage' => t('Storage'), + ); + } + + + function list_build_row($view, &$form_state, $operations) { + if (!empty($view->human_name)) { + $title = $view->human_name; + } + else { + $title = $view->get_title(); + if (empty($title)) { + $title = $view->name; + } + } + + $paths = _views_ui_get_paths($view); + $paths = implode(", ", $paths); + + $base = !empty($this->bases[$view->base_table]) ? $this->bases[$view->base_table] : t('Broken'); + + $info = theme('views_ui_view_info', array('view' => $view, 'base' => $base)); + + // Reorder the operations so that enable is the default action for a templatic views + if (!empty($operations['enable'])) { + $operations = array('enable' => $operations['enable']) + $operations; + } + + // Set up sorting + switch ($form_state['values']['order']) { + case 'disabled': + $this->sorts[$view->name] = strtolower(empty($view->disabled) . $title); + break; + case 'name': + $this->sorts[$view->name] = strtolower($title); + break; + case 'path': + $this->sorts[$view->name] = strtolower($paths); + break; + case 'tag': + $this->sorts[$view->name] = strtolower($view->tag); + break; + case 'storage': + $this->sorts[$view->name] = strtolower($view->type . $title); + break; + } + + $ops = theme('links__ctools_dropbutton', array('links' => $operations, 'attributes' => array('class' => array('links', 'inline')))); + + $this->rows[$view->name] = array( + 'data' => array( + array('data' => $info, 'class' => array('views-ui-name')), + array('data' => check_plain($view->description), 'class' => array('views-ui-description')), + array('data' => check_plain($view->tag), 'class' => array('views-ui-tag')), + array('data' => $paths, 'class' => array('views-ui-path')), + array('data' => $ops, 'class' => array('views-ui-operations')), + ), + 'title' => t('Machine name: ') . check_plain($view->name), + 'class' => array(!empty($view->disabled) ? 'ctools-export-ui-disabled' : 'ctools-export-ui-enabled'), + ); + } + + function list_render(&$form_state) { + views_include('admin'); + views_ui_add_admin_css(); + if (empty($_REQUEST['js'])) { + views_ui_check_advanced_help(); + } + drupal_add_library('system', 'jquery.bbq'); + views_add_js('views-list'); + + $this->active = $form_state['values']['order']; + $this->order = $form_state['values']['sort']; + + $query = tablesort_get_query_parameters(); + + $header = array( + $this->tablesort_link(t('View name'), 'name', 'views-ui-name'), + array('data' => t('Description'), 'class' => array('views-ui-description')), + $this->tablesort_link(t('Tag'), 'tag', 'views-ui-tag'), + $this->tablesort_link(t('Path'), 'path', 'views-ui-path'), + array('data' => t('Operations'), 'class' => array('views-ui-operations')), + ); + + $table = array( + 'header' => $header, + 'rows' => $this->rows, + 'empty' => t('No views match the search criteria.'), + 'attributes' => array('id' => 'ctools-export-ui-list-items'), + ); + return theme('table', $table); + } + + function tablesort_link($label, $field, $class) { + $title = t('sort by @s', array('@s' => $label)); + $initial = 'asc'; + + if ($this->active == $field) { + $initial = ($this->order == 'asc') ? 'desc' : 'asc'; + $label .= theme('tablesort_indicator', array('style' => $initial)); + } + + $query['order'] = $field; + $query['sort'] = $initial; + $link_options = array( + 'html' => TRUE, + 'attributes' => array('title' => $title), + 'query' => $query, + ); + $link = l($label, $_GET['q'], $link_options); + if ($this->active == $field) { + $class .= ' active'; + } + + return array('data' => $link, 'class' => $class); + } + + function clone_page($js, $input, $item, $step = NULL) { + drupal_set_title($this->get_page_title('clone', $item)); + + $name = $item->{$this->plugin['export']['key']}; + + $form_state = array( + 'plugin' => $this->plugin, + 'object' => &$this, + 'ajax' => $js, + 'item' => $item, + 'op' => 'add', + 'form type' => 'clone', + 'original name' => $name, + 'rerender' => TRUE, + 'no_redirect' => TRUE, + 'step' => $step, + // Store these in case additional args are needed. + 'function args' => func_get_args(), + ); + + $output = drupal_build_form('views_ui_clone_form', $form_state); + if (!empty($form_state['executed'])) { + $item->name = $form_state['values']['name']; + $item->human_name = $form_state['values']['human_name']; + $item->vid = NULL; + views_ui_cache_set($item); + + drupal_goto(ctools_export_ui_plugin_menu_path($this->plugin, 'edit', $item->name)); + } + + return $output; + } + + function add_template_page($js, $input, $name, $step = NULL) { + $templates = views_get_all_templates(); + + if (empty($templates[$name])) { + return MENU_NOT_FOUND; + } + + $template = $templates[$name]; + + // The template description probably describes the template, not the + // view that will be created from it, but users aren't that likely to + // touch it. + if (!empty($template->description)) { + unset($template->description); + } + + $template->is_template = TRUE; + $template->type = t('Default'); + + $output = $this->clone_page($js, $input, $template, $step); + drupal_set_title(t('Create view from template @template', array('@template' => $template->get_human_name()))); + return $output; + } +} + +/** + * Form callback to edit an exportable item using the wizard + * + * This simply loads the object defined in the plugin and hands it off. + */ +function views_ui_clone_form($form, &$form_state) { + $counter = 1; + do { + if (empty($form_state['item']->is_template)) { + $name = format_plural($counter, 'Clone of', 'Clone @count of') . ' ' . $form_state['original name']; + } + else { + $name = $form_state['original name']; + if ($counter > 1) { + $name .= ' ' . $counter; + } + } + $counter++; + $machine_name = preg_replace('/[^a-z0-9_]+/', '_', drupal_strtolower($name)); + } while (ctools_export_crud_load($form_state['plugin']['schema'], $machine_name)); + + $form['human_name'] = array( + '#type' => 'textfield', + '#title' => t('View name'), + '#default_value' => $name, + ); + + $form['name'] = array( + '#title' => t('View name'), + '#type' => 'machine_name', + '#required' => TRUE, + '#maxlength' => 255, + '#machine_name' => array( + 'exists' => 'ctools_export_ui_edit_name_exists', + 'source' => array('human_name'), + ), + ); + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Continue'), + ); + + return $form; +} + + diff --git a/sites/all/modules/views/plugins/export_ui/views_ui.inc b/sites/all/modules/views/plugins/export_ui/views_ui.inc new file mode 100644 index 0000000000000000000000000000000000000000..fc79f3dd5ef03d66e5b385aaa6f95f9707e5f4ef --- /dev/null +++ b/sites/all/modules/views/plugins/export_ui/views_ui.inc @@ -0,0 +1,38 @@ +<?php + +/** + * @file + * Plugin definition for CTools Export UI integration. + */ + +$plugin = array( + 'schema' => 'views_view', + 'access' => 'administer views', + + 'menu' => array( + 'menu item' => 'views', + 'menu title' => 'Views', + 'menu description' => 'Manage customized lists of content.', + ), + + 'title singular' => t('view'), + 'title singular proper' => t('View'), + 'title plural' => t('views'), + 'title plural proper' => t('Views'), + + 'handler' => 'views_ui', + + 'strings' => array( + 'confirmation' => array( + 'revert' => array( + 'information' => t('This action will permanently remove any customizations made to this view.'), + 'success' => t('The view has been reverted.'), + ), + 'delete' => array( + 'information' => t('This action will permanently remove the view from your database.'), + 'success' => t('The view has been deleted.'), + ), + ), + ), +); + diff --git a/sites/all/modules/views/plugins/views_plugin_access.inc b/sites/all/modules/views/plugins/views_plugin_access.inc index af8c1a299efa259be7bf85c863cdafcc83728814..b3fbb29dc17256cf57877740e309ebdf795d823a 100644 --- a/sites/all/modules/views/plugins/views_plugin_access.inc +++ b/sites/all/modules/views/plugins/views_plugin_access.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_access.inc,v 1.1.6.1 2009/11/13 23:19:22 dereine Exp $ /** * The base plugin to handle access control. diff --git a/sites/all/modules/views/plugins/views_plugin_access_none.inc b/sites/all/modules/views/plugins/views_plugin_access_none.inc index f39d76c704cb0cad411e0ca25664beb661cc7052..be563a2c2428bb377cce13b042e892e6e3fc8961 100644 --- a/sites/all/modules/views/plugins/views_plugin_access_none.inc +++ b/sites/all/modules/views/plugins/views_plugin_access_none.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_access_none.inc,v 1.1 2008/09/08 22:50:17 merlinofchaos Exp $ /** * Access plugin that provides no access control at all. diff --git a/sites/all/modules/views/plugins/views_plugin_access_perm.inc b/sites/all/modules/views/plugins/views_plugin_access_perm.inc index 27a392a7f254f245980937b57a1095ae028d8fbf..3310bb2a0f30590d66170cb7ace7ec442728746b 100644 --- a/sites/all/modules/views/plugins/views_plugin_access_perm.inc +++ b/sites/all/modules/views/plugins/views_plugin_access_perm.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_access_perm.inc,v 1.3.6.3 2010/03/10 21:03:19 merlinofchaos Exp $ /** * Access plugin that provides permission-based access control. diff --git a/sites/all/modules/views/plugins/views_plugin_access_role.inc b/sites/all/modules/views/plugins/views_plugin_access_role.inc index 5a278d57351950959ed21e028d4e1d0e1e44dc22..b273971e7e009f57953755397d08faf91461de0c 100644 --- a/sites/all/modules/views/plugins/views_plugin_access_role.inc +++ b/sites/all/modules/views/plugins/views_plugin_access_role.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_access_role.inc,v 1.2.6.3 2010/03/10 21:03:19 merlinofchaos Exp $ /** * Access plugin that provides role-based access control. @@ -23,8 +22,8 @@ class views_plugin_access_role extends views_plugin_access { } else { $rids = views_ui_get_roles(); - $rid = array_shift($this->options['role']); - return $rids[$rid]; + $rid = reset($this->options['role']); + return check_plain($rids[$rid]); } } @@ -41,7 +40,7 @@ class views_plugin_access_role extends views_plugin_access { '#type' => 'checkboxes', '#title' => t('Role'), '#default_value' => $this->options['role'], - '#options' => views_ui_get_roles(), + '#options' => array_map('check_plain', views_ui_get_roles()), '#description' => t('Only the checked roles will be able to access this display. Note that users with "access all views" can see any view, regardless of role.'), ); } @@ -57,6 +56,3 @@ class views_plugin_access_role extends views_plugin_access { $form_state['values']['access_options']['role'] = array_filter($form_state['values']['access_options']['role']); } } - - - diff --git a/sites/all/modules/views/plugins/views_plugin_argument_default.inc b/sites/all/modules/views/plugins/views_plugin_argument_default.inc index d47fc9982617abfc355765f0d624239f4211acce..bc284df6655fad4cf81cf067ed4d118c5fd1b1d3 100644 --- a/sites/all/modules/views/plugins/views_plugin_argument_default.inc +++ b/sites/all/modules/views/plugins/views_plugin_argument_default.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_default.inc,v 1.2.4.2 2010/01/28 22:44:37 dereine Exp $ /** * @file * Contains the fixed argument default plugin. @@ -76,7 +75,7 @@ class views_plugin_argument_default extends views_plugin { if (!$this->access()) { $form[$option_name]['#disabled'] = TRUE; $form[$option_name]['#value'] = $form[$this->option_name]['#default_value']; - $form[$option_name]['#description'] .= ' <strong>' . t('Note: you do not have permission to modify this. If you change the default argument type, this setting will be lost and you will NOT be able to get it back.') . '</strong>'; + $form[$option_name]['#description'] .= ' <strong>' . t('Note: you do not have permission to modify this. If you change the default filter type, this setting will be lost and you will NOT be able to get it back.') . '</strong>'; } } diff --git a/sites/all/modules/views/plugins/views_plugin_argument_default_fixed.inc b/sites/all/modules/views/plugins/views_plugin_argument_default_fixed.inc index 0598f56ceca694e543f6d575ae8915ba28c5db67..86afd9e571c4608c1e89417858ddfef8bc497e94 100644 --- a/sites/all/modules/views/plugins/views_plugin_argument_default_fixed.inc +++ b/sites/all/modules/views/plugins/views_plugin_argument_default_fixed.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_default_fixed.inc,v 1.1.4.2 2010/01/28 22:45:04 dereine Exp $ /** * @file * Contains the fixed argument default plugin. @@ -19,7 +18,7 @@ class views_plugin_argument_default_fixed extends views_plugin_argument_default function options_form(&$form, &$form_state) { $form['argument'] = array( '#type' => 'textfield', - '#title' => t('Default argument'), + '#title' => t('Fixed value'), '#default_value' => $this->options['argument'], ); } @@ -40,5 +39,4 @@ class views_plugin_argument_default_fixed extends views_plugin_argument_default /** * @} - */ - + */ \ No newline at end of file diff --git a/sites/all/modules/views/plugins/views_plugin_argument_default_php.inc b/sites/all/modules/views/plugins/views_plugin_argument_default_php.inc index fee8d7fbcf1e53c59899b47db544c2ebfefc6a68..699dae73e7ae29d9a4f3bae00cfa2e863bfb8235 100644 --- a/sites/all/modules/views/plugins/views_plugin_argument_default_php.inc +++ b/sites/all/modules/views/plugins/views_plugin_argument_default_php.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_default_php.inc,v 1.1.6.4 2010/11/05 07:20:54 dereine Exp $ /** * @file * Contains the php code argument default plugin. @@ -19,10 +18,9 @@ class views_plugin_argument_default_php extends views_plugin_argument_default { function options_form(&$form, &$form_state) { $form['code'] = array( '#type' => 'textarea', - '#title' => t('PHP argument code'), + '#title' => t('PHP contextual filter code'), '#default_value' => $this->options['code'], - '#process' => array('ctools_dependent_process'), - '#description' => t('Enter PHP code that returns a value to use for this argument. Do not use <?php ?>. You must return only a single value for just this argument.'), + '#description' => t('Enter PHP code that returns a value to use for this filter. Do not use <?php ?>. You must return only a single value for just this filter.'), ); // Only do this if using one simple standard form gadget diff --git a/sites/all/modules/views/plugins/views_plugin_argument_validate.inc b/sites/all/modules/views/plugins/views_plugin_argument_validate.inc index 2cabb5789f8aa8657550b2132cce170eeefe9822..fd680949ff5cb8456fcd435d747ec753a7093def 100644 --- a/sites/all/modules/views/plugins/views_plugin_argument_validate.inc +++ b/sites/all/modules/views/plugins/views_plugin_argument_validate.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_validate.inc,v 1.2.4.2 2010/01/28 22:44:37 dereine Exp $ /** * @file * Contains the base argument validator plugin. @@ -52,7 +51,7 @@ class views_plugin_argument_validate extends views_plugin { /** * Provide the default form form for submitting options */ - function options_submit(&$form, &$form_state) { } + function options_submit(&$form, &$form_state, &$options = array()) { } /** * Convert options from the older style. @@ -80,7 +79,7 @@ class views_plugin_argument_validate extends views_plugin { if (!$this->access()) { $form[$option_name]['#disabled'] = TRUE; $form[$option_name]['#value'] = $form[$this->option_name]['#default_value']; - $form[$option_name]['#description'] .= ' <strong>' . t('Note: you do not have permission to modify this. If you change the default argument type, this setting will be lost and you will NOT be able to get it back.') . '</strong>'; + $form[$option_name]['#description'] .= ' <strong>' . t('Note: you do not have permission to modify this. If you change the default filter type, this setting will be lost and you will NOT be able to get it back.') . '</strong>'; } } diff --git a/sites/all/modules/views/plugins/views_plugin_argument_validate_numeric.inc b/sites/all/modules/views/plugins/views_plugin_argument_validate_numeric.inc index 56552371f15f74f5398afa08754f40199f57ed5a..32390996916bb98cd25320767a4f7c9b6b5e12c6 100644 --- a/sites/all/modules/views/plugins/views_plugin_argument_validate_numeric.inc +++ b/sites/all/modules/views/plugins/views_plugin_argument_validate_numeric.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_validate_numeric.inc,v 1.1.6.1 2010/01/28 22:44:37 dereine Exp $ /** * @file * Contains the numeric argument validator plugin. diff --git a/sites/all/modules/views/plugins/views_plugin_argument_validate_php.inc b/sites/all/modules/views/plugins/views_plugin_argument_validate_php.inc index 8f4222b6376733d9703c7605fb7bad5c0fbe18f0..a4c3ae86044ce54d66981fb0eaa73e29ef02a624 100644 --- a/sites/all/modules/views/plugins/views_plugin_argument_validate_php.inc +++ b/sites/all/modules/views/plugins/views_plugin_argument_validate_php.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_argument_validate_php.inc,v 1.1.6.2 2010/01/28 22:44:37 dereine Exp $ /** * @file * Contains the php code argument validator plugin. diff --git a/sites/all/modules/views/plugins/views_plugin_cache.inc b/sites/all/modules/views/plugins/views_plugin_cache.inc index 1bbed02c03eaea4b2aec52c81d6d6748d0d3a78b..1b17c07c835d902ee996b668f9b8dd2a9e42b45f 100644 --- a/sites/all/modules/views/plugins/views_plugin_cache.inc +++ b/sites/all/modules/views/plugins/views_plugin_cache.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_cache.inc,v 1.5.4.5 2010/10/12 23:23:52 merlinofchaos Exp $ /** * The base plugin to handle caching. @@ -113,7 +112,7 @@ class views_plugin_cache extends views_plugin { if (!$cutoff || $cache->created > $cutoff) { $this->view->result = $cache->data['result']; $this->view->total_rows = $cache->data['total_rows']; - $this->view->set_current_page = $cache->data['current_page']; + $this->view->set_current_page($cache->data['current_page']); $this->view->execute_time = 0; return TRUE; } diff --git a/sites/all/modules/views/plugins/views_plugin_cache_none.inc b/sites/all/modules/views/plugins/views_plugin_cache_none.inc index bcfd8a7f59d1b9981e15d09b0d00ecf67637cdaf..9cc2757ff4d2a18d8f4fc351015c6183b90f6fc2 100644 --- a/sites/all/modules/views/plugins/views_plugin_cache_none.inc +++ b/sites/all/modules/views/plugins/views_plugin_cache_none.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_cache_none.inc,v 1.2.4.1 2009/11/02 22:01:27 merlinofchaos Exp $ /** * Caching plugin that provides no caching at all. diff --git a/sites/all/modules/views/plugins/views_plugin_cache_time.inc b/sites/all/modules/views/plugins/views_plugin_cache_time.inc index 2857feff699e101c3c5942950fda0256d80397e0..c758b096b12a44b24d59ec352653c74ba788f06b 100644 --- a/sites/all/modules/views/plugins/views_plugin_cache_time.inc +++ b/sites/all/modules/views/plugins/views_plugin_cache_time.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_cache_time.inc,v 1.3.4.4 2010/11/18 00:56:20 merlinofchaos Exp $ /** * Simple caching of query results for Views displays. diff --git a/sites/all/modules/views/plugins/views_plugin_display.inc b/sites/all/modules/views/plugins/views_plugin_display.inc index 0660ce06ab98720e527656e67e9c5db421875740..210dbcb70bbc57007838d605220e843bb02ed5ca 100644 --- a/sites/all/modules/views/plugins/views_plugin_display.inc +++ b/sites/all/modules/views/plugins/views_plugin_display.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_display.inc,v 1.27.4.49 2011/01/05 20:36:27 dereine Exp $ /** * @file * Contains the base display plugin. @@ -25,6 +24,13 @@ * @ingroup views_display_plugins */ class views_plugin_display extends views_plugin { + /** + * The top object of a view. + * + * @var view + */ + var $view = NULL; + var $handlers = array(); function init(&$view, &$display, $options = NULL) { @@ -248,7 +254,17 @@ class views_plugin_display extends views_plugin { * Can this display accept attachments? */ function accept_attachments() { - return !empty($this->definition['accept attachments']); + if (empty($this->definition['accept attachments'])) { + return FALSE; + } + if (!empty($this->view->argument) && $this->get_option('hide_attachment_summary')) { + foreach ($this->view->argument as $argument_id => $argument) { + if ($argument->needs_style_plugin() && empty($argument->argument_validated)) { + return FALSE; + } + } + } + return TRUE; } /** @@ -268,6 +284,8 @@ class views_plugin_display extends views_plugin { 'enabled' => array('enabled'), 'css_class' => array('css_class'), 'use_ajax' => array('use_ajax'), + 'hide_attachment_summary' => array('hide_attachment_summary'), + 'group_by' => array('group_by'), 'query' => array('query'), 'items_per_page' => array('items_per_page', 'offset', 'use_pager', 'pager_element'), 'pager' => array('pager'), @@ -317,12 +335,13 @@ class views_plugin_display extends views_plugin { 'cache' => TRUE, 'query' => TRUE, 'title' => TRUE, - 'display_comment' => TRUE, + 'display_comment' => FALSE, 'enabled' => TRUE, 'css_class' => TRUE, 'display_description' => FALSE, 'use_ajax' => TRUE, + 'hide_attachment_summary' => TRUE, 'items_per_page' => TRUE, 'use_pager' => TRUE, 'offset' => TRUE, @@ -379,6 +398,10 @@ class views_plugin_display extends views_plugin { 'default' => FALSE, 'bool' => TRUE, ), + 'hide_attachment_summary' => array( + 'default' => FALSE, + 'bool' => TRUE, + ), 'items_per_page' => array( 'default' => 10, ), @@ -678,6 +701,9 @@ class views_plugin_display extends views_plugin { $plugin->init($this->view, $this->display, $options); } else { + $display_id = $this->is_defaulted($option_name) ? $this->display->id : 'default'; + $plugin->localization_keys = array($display_id, $type); + if (!isset($this->base_field)) { $views_data = views_fetch_data($this->view->base_table); $this->view->base_field = $views_data['table']['base']['field']; @@ -715,7 +741,15 @@ class views_plugin_display extends views_plugin { $this->handlers[$type] = array(); $types = views_object_types(); $plural = $types[$type]['plural']; + foreach ($this->get_option($plural) as $id => $info) { + // If this is during form submission and there are temporary options + // which can only appear if the view is in the edit cache, use those + // options instead. This is used for AJAX multi-step stuff. + if (isset($_POST['form_id']) && isset($this->view->temporary_options[$type][$id])) { + $info = $this->view->temporary_options[$type][$id]; + } + if ($info['id'] != $id) { $info['id'] = $id; } @@ -743,6 +777,11 @@ class views_plugin_display extends views_plugin { $handler = views_get_handler($info['table'], $info['field'], $handler_type, $override); if ($handler) { + // Special override for area types so they know where they come from. + if ($handler_type == 'area') { + $handler->handler_type = $type; + } + $handler->init($this->view, $info); $this->handlers[$type][$id] = &$handler; } @@ -836,39 +875,61 @@ class views_plugin_display extends views_plugin { */ function options_summary(&$categories, &$options) { $categories = array( - 'basic' => array( - 'title' => t('Basic settings'), + 'title' => array( + 'title' => t('Title'), + 'column' => 'first', + ), + 'format' => array( + 'title' => t('Format'), + 'column' => 'first', + ), + 'filters' => array( + 'title' => t('Filters'), + 'column' => 'first', ), - 'advanced' => array( - 'title' => t('Advanced settings'), + 'fields' => array( + 'title' => t('Fields'), + 'column' => 'first', ), - 'style' => array( - 'title' => t('Style settings'), + 'pager' => array( + 'title' => t('Pager'), + 'column' => 'second', ), 'exposed' => array( 'title' => t('Exposed form'), + 'column' => 'third', + 'build' => array( + '#weight' => 1, + ), + ), + 'access' => array( + 'title' => '', + 'column' => 'second', + 'build' => array( + '#weight' => -5, + ), + ), + 'other' => array( + 'title' => t('Other'), + 'column' => 'third', + 'build' => array( + '#weight' => 2, + ), ), ); if ($this->display->id != 'default') { $options['display_id'] = array( - 'category' => 'basic', + 'category' => 'other', 'title' => t('Machine Name'), 'value' => !empty($this->display->new_id) ? check_plain($this->display->new_id) : check_plain($this->display->id), 'desc' => t('Change the machine name of this display.'), ); } - $options['display_title'] = array( - 'category' => 'basic', - 'title' => t('Name'), - 'value' => check_plain($this->display->display_title), - 'desc' => t('Change the name of this display.'), - ); - $display_comment = drupal_substr($this->get_option('display_comment'), 0, 10); $options['display_comment'] = array( - 'category' => 'basic', + 'category' => 'other', 'title' => t('Comment'), 'value' => !empty($display_comment) ? $display_comment : t('No comment'), 'desc' => t('Comment or document this display.'), @@ -880,45 +941,51 @@ class views_plugin_display extends views_plugin { } $options['title'] = array( - 'category' => 'basic', + 'category' => 'title', 'title' => t('Title'), 'value' => $title, 'desc' => t('Change the title that this display will use.'), ); $options['enabled'] = array( - 'category' => 'basic', + 'category' => 'other', 'title' => t('Display status'), 'value' => $this->get_option('enabled') ? t('Enabled') : t('Disabled'), 'desc' => t('Define if this display is or is not enabled.'), ); $style_plugin = views_fetch_plugin_data('style', $this->get_option('style_plugin')); - $style_title = empty($style_plugin['title']) ? t('Missing style plugin') : $style_plugin['title']; + $style_plugin_instance = $this->get_plugin('style'); + $style_summary = empty($style_plugin['title']) ? t('Missing style plugin') : $style_plugin_instance->summary_title(); + $style_title = empty($style_plugin['title']) ? t('Missing style plugin') : $style_plugin_instance->plugin_title(); $style = ''; $options['style_plugin'] = array( - 'category' => 'style', - 'title' => t('Style'), + 'category' => 'format', + 'title' => t('Format'), 'value' => $style_title, - 'desc' => t('Change the style plugin.'), + 'setting' => $style_summary, + 'desc' => t('Change the way content is formatted.'), ); // This adds a 'Settings' link to the style_options setting if the style has options. if (!empty($style_plugin['uses options'])) { - $options['style_plugin']['links']['style_options'] = t('Change settings for this style'); + $options['style_plugin']['links']['style_options'] = t('Change settings for this format'); } if (!empty($style_plugin['uses row plugin'])) { $row_plugin = views_fetch_plugin_data('row', $this->get_option('row_plugin')); - $row_title = empty($row_plugin['title']) ? t('Missing style plugin') : $row_plugin['title']; + $row_plugin_instance = $this->get_plugin('row'); + $row_summary = empty($row_plugin['title']) ? t('Missing style plugin') : $row_plugin_instance->summary_title(); + $row_title = empty($row_plugin['title']) ? t('Missing style plugin') : $row_plugin_instance->plugin_title(); $options['row_plugin'] = array( - 'category' => 'style', - 'title' => t('Row style'), + 'category' => 'format', + 'title' => t('Show'), 'value' => $row_title, - 'desc' => t('Change the row plugin.'), + 'setting' => $row_summary, + 'desc' => t('Change the way each row in the view is styled.'), ); // This adds a 'Settings' link to the row_options setting if the row style has options. if (!empty($row_plugin['uses options'])) { @@ -927,12 +994,20 @@ class views_plugin_display extends views_plugin { } if (!empty($this->definition['use ajax'])) { $options['use_ajax'] = array( - 'category' => 'advanced', + 'category' => 'other', 'title' => t('Use AJAX'), 'value' => $this->get_option('use_ajax') ? t('Yes') : t('No'), 'desc' => t('Change whether or not this display will use AJAX.'), ); } + if (!empty($this->definition['accept attachments'])) { + $options['hide_attachment_summary'] = array( + 'category' => 'other', + 'title' => t('Hide attachments in summary'), + 'value' => $this->get_option('hide_attachment_summary') ? t('Yes') : t('No'), + 'desc' => t('Change whether or not to display attachments when displaying a contextual filter summary.'), + ); + } $pager_plugin = $this->get_plugin('pager'); if (!$pager_plugin) { @@ -943,9 +1018,10 @@ class views_plugin_display extends views_plugin { $pager_str = $pager_plugin->summary_title(); $options['pager'] = array( - 'category' => 'basic', + 'category' => 'pager', 'title' => t('Use pager'), - 'value' => $pager_str, + 'value' => $pager_plugin->plugin_title(), + 'setting' => $pager_str, 'desc' => t("Change this display's pager setting."), ); @@ -960,7 +1036,7 @@ class views_plugin_display extends views_plugin { if (!empty($this->definition['use more'])) { $options['use_more'] = array( - 'category' => 'basic', + 'category' => 'pager', 'title' => t('More link'), 'value' => $this->get_option('use_more') ? t('Yes') : t('No'), 'desc' => t('Specify whether this display will provide a "more" link.'), @@ -970,7 +1046,7 @@ class views_plugin_display extends views_plugin { $this->view->init_query(); if ($this->view->query->get_aggregation_info()) { $options['group_by'] = array( - 'category' => 'advanced', + 'category' => 'other', 'title' => t('Use grouping'), 'value' => $this->get_option('group_by') ? t('Yes') : t('No'), 'desc' => t('Allow grouping and aggregation (calculation) of fields.'), @@ -978,7 +1054,7 @@ class views_plugin_display extends views_plugin { } $options['query'] = array( - 'category' => 'advanced', + 'category' => 'other', 'title' => t('Query settings'), 'value' => t('Settings'), 'desc' => t('Allow to set some advanced settings for the query plugin'), @@ -993,9 +1069,10 @@ class views_plugin_display extends views_plugin { $access_str = $access_plugin->summary_title(); $options['access'] = array( - 'category' => 'basic', + 'category' => 'access', 'title' => t('Access'), - 'value' => $access_str, + 'value' => $access_plugin->plugin_title(), + 'setting' => $access_str, 'desc' => t('Specify access control type for this display.'), ); @@ -1012,9 +1089,10 @@ class views_plugin_display extends views_plugin { $cache_str = $cache_plugin->summary_title(); $options['cache'] = array( - 'category' => 'advanced', + 'category' => 'other', 'title' => t('Caching'), - 'value' => $cache_str, + 'value' => $cache_plugin->plugin_title(), + 'setting' => $cache_str, 'desc' => t('Specify caching type for this display.'), ); @@ -1042,7 +1120,7 @@ class views_plugin_display extends views_plugin { $display_id = $this->get_link_display(); $link_display = empty($this->view->display[$display_id]) ? t('None') : check_plain($this->view->display[$display_id]->display_title); $options['link_display'] = array( - 'category' => 'basic', + 'category' => 'other', 'title' => t('Link display'), 'value' => $link_display, 'desc' => t('Specify which display this display will link to.'), @@ -1068,7 +1146,8 @@ class views_plugin_display extends views_plugin { $options['exposed_form'] = array( 'category' => 'exposed', 'title' => t('Exposed form style'), - 'value' => $exposed_form_str, + 'value' => $exposed_form_plugin->plugin_title(), + 'setting' => $exposed_form_str, 'desc' => t('Select the kind of exposed filter to use.'), ); @@ -1082,14 +1161,14 @@ class views_plugin_display extends views_plugin { } $options['css_class'] = array( - 'category' => 'style', + 'category' => 'other', 'title' => t('CSS class'), 'value' => $css_class, 'desc' => t('Change the CSS class name(s) that will be added to this display.'), ); $options['analyze-theme'] = array( - 'category' => 'style', + 'category' => 'other', 'title' => t('Theme'), 'value' => t('Information'), 'desc' => t('Get information on how to theme this display'), @@ -1101,7 +1180,7 @@ class views_plugin_display extends views_plugin { */ function options_form(&$form, &$form_state) { if ($this->defaultable_sections($form_state['section'])) { - $this->add_override_button($form, $form_state, $form_state['section']); + views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); } $form['#title'] = check_plain($this->display->display_title) . ': '; @@ -1186,6 +1265,14 @@ class views_plugin_display extends views_plugin { '#default_value' => $this->get_option('use_ajax') ? 1 : 0, ); break; + case 'hide_attachment_summary': + $form['#title'] .= t('Hide attachments when displaying a contextual filter summary'); + $form['hide_attachment_summary'] = array( + '#type' => 'radios', + '#options' => array(1 => t('Yes'), 0 => t('No')), + '#default_value' => $this->get_option('hide_attachment_summary') ? 1 : 0, + ); + break; case 'use_more': $form['#title'] .= t('Add a more link to the bottom of the display.'); $form['use_more'] = array( @@ -1200,7 +1287,6 @@ class views_plugin_display extends views_plugin { '#description' => t("This will display the more link even if there are no more items to display."), '#default_value' => $this->get_option('use_more_always'), ); - $form['#title'] .= t('Text to use for the more link.'); $form['use_more_text'] = array( '#type' => 'textfield', '#title' => t('More link text'), @@ -1236,7 +1322,7 @@ class views_plugin_display extends views_plugin { if (!empty($access_plugin['uses options'])) { $form['markup'] = array( '#prefix' => '<div class="form-item description">', - '#markup' => t('You may also adjust the !settings for the currently selected access restriction by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'access_options'))), + '#markup' => t('You may also adjust the !settings for the currently selected access restriction.', array('!settings' => $this->option_link(t('settings'), 'access_options'))), '#suffix' => '</div>', ); } @@ -1280,7 +1366,7 @@ class views_plugin_display extends views_plugin { $form['markup'] = array( '#prefix' => '<div class="form-item description">', '#suffix' => '</div>', - '#markup' => t('You may also adjust the !settings for the currently selected cache mechanism by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'cache_options'))), + '#markup' => t('You may also adjust the !settings for the currently selected cache mechanism.', array('!settings' => $this->option_link(t('settings'), 'cache_options'))), ); } break; @@ -1344,7 +1430,7 @@ class views_plugin_display extends views_plugin { $style_plugin = views_fetch_plugin_data('style', $this->get_option('style_plugin')); if (!empty($style_plugin['uses options'])) { $form['markup'] = array( - '#markup' => '<div class="form-item description">' . t('You may also adjust the !settings for the currently selected style by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'style_options'))) . '</div>', + '#markup' => '<div class="form-item description">' . t('You may also adjust the !settings for the currently selected style.', array('!settings' => $this->option_link(t('settings'), 'style_options'))) . '</div>', ); } @@ -1388,7 +1474,7 @@ class views_plugin_display extends views_plugin { $row_plugin = views_fetch_plugin_data('row', $this->get_option('row_plugin')); if (!empty($row_plugin['uses options'])) { $form['markup'] = array( - '#markup' => '<div class="form-item description">' . t('You may also adjust the !settings for the currently selected row style by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'row_options'))) . '</div>', + '#markup' => '<div class="form-item description">' . t('You may also adjust the !settings for the currently selected row style.', array('!settings' => $this->option_link(t('settings'), 'row_options'))) . '</div>', ); } @@ -1700,7 +1786,7 @@ class views_plugin_display extends views_plugin { $form['markup'] = array( '#prefix' => '<div class="form-item description">', '#suffix' => '</div>', - '#value' => t('You may also adjust the !settings for the currently selected style by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'exposed_form_options'))), + '#markup' => t('You may also adjust the !settings for the currently selected style.', array('!settings' => $this->option_link(t('settings'), 'exposed_form_options'))), ); } break; @@ -1736,7 +1822,7 @@ class views_plugin_display extends views_plugin { $form['markup'] = array( '#prefix' => '<div class="form-item description">', '#suffix' => '</div>', - '#value' => t('You may also adjust the !settings for the currently selected pager by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'pager_options'))), + '#markup' => t('You may also adjust the !settings for the currently selected pager.', array('!settings' => $this->option_link(t('settings'), 'pager_options'))), ); } @@ -1803,7 +1889,7 @@ class views_plugin_display extends views_plugin { } foreach ($this->view->display as $id => $display) { - if ($id != $this->view->current_display && ($form_state['values']['display_id'] == $id || $form_state['values']['display_id'] == $display->new_id)) { + if ($id != $this->view->current_display && ($form_state['values']['display_id'] == $id || (isset($display->new_id) && $form_state['values']['display_id'] == $display->new_id))) { form_error($form['display_id'], t('Display id should be unique.')); } } @@ -1930,6 +2016,7 @@ class views_plugin_display extends views_plugin { break; case 'enabled': case 'use_ajax': + case 'hide_attachment_summary': $this->set_option($section, (bool)$form_state['values'][$section]); break; case 'use_more': @@ -2039,54 +2126,6 @@ class views_plugin_display extends views_plugin { } } - /** - * Add an override button for a given section, allowing the user to - * change whether this info is stored on the default display or on - * the current display. - */ - function add_override_button(&$form, &$form_state, $section) { - if ($this->is_default_display()) { - return; - } - - $form['override'] = array( - '#prefix' => '<div class="views-override clearfix">', - '#suffix' => '</div>', - ); - if ($this->is_defaulted($section)) { - $form['override']['button'] = array( - '#type' => 'submit', - '#value' => t('Override'), - '#submit' => array('views_ui_edit_display_form_override'), - ); - $help = ''; - if (module_exists('advanced_help')) { - $help = theme('advanced_help_topic', array('module' => 'views', 'topic' => 'overrides')); - } - $form['override']['markup'] = array( - '#markup' => '<div class="description">' . $help . t('Status: using default values.') . '</div>', - ); - - $form_state['update_name'] = t('Update default display'); - } - else { - $form['override']['button'] = array( - '#type' => 'submit', - '#value' => t('Use default'), - '#submit' => array('views_ui_edit_display_form_override'), - ); - $help = ''; - if (module_exists('advanced_help')) { - $help = theme('advanced_help_topic', array('module' => 'views', 'topic' => 'overrides')); - } - $form['override']['markup'] = array( - '#markup' => '<div class="description">' . $help . t('Status: using overridden values.') . '</div>', - ); - - $form_state['update_name'] = NULL; - } - } - /** * If override/revert was clicked, perform the proper toggle. */ @@ -2134,6 +2173,13 @@ class views_plugin_display extends views_plugin { */ function render_filters() { } + /** + * Not all display plugins will suppert pager rendering. + */ + function render_pager() { + return TRUE; + } + /** * Render the 'more' link */ @@ -2149,7 +2195,7 @@ class views_plugin_display extends views_plugin { $theme = views_theme_functions('views_more', $this->view, $this->display); $path = check_url(url($path, $url_options)); - return theme($theme, array('more_url' => $path, 'link_text' => $this->use_more_text())); + return theme($theme, array('more_url' => $path, 'link_text' => check_plain($this->use_more_text()))); } } } @@ -2235,7 +2281,7 @@ class views_plugin_display extends views_plugin { */ function pre_execute() { $this->view->set_use_ajax($this->use_ajax()); - if ($this->use_more()) { + if ($this->use_more() && !$this->use_more_always()) { $this->view->get_total_rows = TRUE; } $this->view->init_handlers(); @@ -2303,6 +2349,13 @@ class views_plugin_display extends views_plugin { } } + // Validate query plugin. + $query = $this->get_plugin('query'); + $result = $query->validate(); + if (!empty($result) && is_array($result)) { + $errors = array_merge($errors, $result); + } + // Validate handlers foreach (views_object_types() as $type => $info) { foreach ($this->get_handlers($type) as $handler) { @@ -2353,7 +2406,7 @@ class views_plugin_display extends views_plugin { function view_special_blocks($type) { if ($type == '-exp') { // avoid interfering with the admin forms. - if (arg(0) == 'admin' && arg(1) == 'build' && arg(2) == 'views') { + if (arg(0) == 'admin' && arg(1) == 'structure' && arg(2) == 'views') { return; } $this->view->init_handlers(); @@ -2583,4 +2636,3 @@ class views_plugin_display extends views_plugin { /** * @} */ - diff --git a/sites/all/modules/views/plugins/views_plugin_display_attachment.inc b/sites/all/modules/views/plugins/views_plugin_display_attachment.inc index 6cb34d71362f1b4091b2e7256a16bf7269946ce3..d05d1e64aff8b920431809e49938afa0bf3a5437 100644 --- a/sites/all/modules/views/plugins/views_plugin_display_attachment.inc +++ b/sites/all/modules/views/plugins/views_plugin_display_attachment.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_display_attachment.inc,v 1.6.4.3 2010/11/18 23:15:37 merlinofchaos Exp $ /** * @file * Contains the attachment display plugin. @@ -18,12 +17,12 @@ class views_plugin_display_attachment extends views_plugin_display { function option_definition () { $options = parent::option_definition(); + $options['displays'] = array('default' => array()); $options['attachment_position'] = array('default' => 'before'); $options['inherit_arguments'] = array('default' => TRUE); $options['inherit_exposed_filters'] = array('default' => FALSE); $options['inherit_pager'] = array('default' => FALSE); $options['render_pager'] = array('default' => FALSE); - $options['displays'] = array('default' => array()); return $options; } @@ -57,11 +56,42 @@ class views_plugin_display_attachment extends views_plugin_display { $categories['attachment'] = array( 'title' => t('Attachment settings'), + 'column' => 'second', + 'build' => array( + '#weight' => -10, + ), + ); + + $displays = array_filter($this->get_option('displays')); + if (count($displays) > 1) { + $attach_to = t('Multiple displays'); + } + elseif (count($displays) == 1) { + $display = array_shift($displays); + if (!empty($this->view->display[$display])) { + $attach_to = check_plain($this->view->display[$display]->display_title); + } + } + + if (!isset($attach_to)) { + $attach_to = t('Not defined'); + } + + $options['displays'] = array( + 'category' => 'attachment', + 'title' => t('Attach to'), + 'value' => $attach_to, + ); + + $options['attachment_position'] = array( + 'category' => 'attachment', + 'title' => t('Attachment position'), + 'value' => $this->attachment_positions($this->get_option('attachment_position')), ); $options['inherit_arguments'] = array( 'category' => 'attachment', - 'title' => t('Inherit arguments'), + 'title' => t('Inherit contextual filters'), 'value' => $this->get_option('inherit_arguments') ? t('Yes') : t('No'), ); @@ -72,43 +102,17 @@ class views_plugin_display_attachment extends views_plugin_display { ); $options['inherit_pager'] = array( - 'category' => 'attachment', + 'category' => 'pager', 'title' => t('Inherit pager'), 'value' => $this->get_option('inherit_pager') ? t('Yes') : t('No'), ); $options['render_pager'] = array( - 'category' => 'attachment', + 'category' => 'pager', 'title' => t('Render pager'), 'value' => $this->get_option('render_pager') ? t('Yes') : t('No'), ); - $options['attachment_position'] = array( - 'category' => 'attachment', - 'title' => t('Position'), - 'value' => $this->attachment_positions($this->get_option('attachment_position')), - ); - - $displays = array_filter($this->get_option('displays')); - if (count($displays) > 1) { - $attach_to = t('Multiple displays'); - } - elseif (count($displays) == 1) { - $display = array_shift($displays); - if (!empty($this->view->display[$display])) { - $attach_to = check_plain($this->view->display[$display]->display_title); - } - } - - if (!isset($attach_to)) { - $attach_to = t('None'); - } - - $options['displays'] = array( - 'category' => 'attachment', - 'title' => t('Attach to'), - 'value' => $attach_to, - ); } /** @@ -120,11 +124,11 @@ class views_plugin_display_attachment extends views_plugin_display { switch ($form_state['section']) { case 'inherit_arguments': - $form['#title'] .= t('Inherit arguments'); + $form['#title'] .= t('Inherit contextual filters'); $form['inherit_arguments'] = array( '#type' => 'checkbox', '#title' => t('Inherit'), - '#description' => t('Should this display inherit its arguments from the parent display to which it is attached?'), + '#description' => t('Should this display inherit its contextual filter values from the parent display to which it is attached?'), '#default_value' => $this->get_option('inherit_arguments'), ); break; diff --git a/sites/all/modules/views/plugins/views_plugin_display_block.inc b/sites/all/modules/views/plugins/views_plugin_display_block.inc index e05efd5a50ddf2f2a13f75b53d8b65d7a305af51..3c0ef0e976531bea09c91af61e453aa948bebd6e 100644 --- a/sites/all/modules/views/plugins/views_plugin_display_block.inc +++ b/sites/all/modules/views/plugins/views_plugin_display_block.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_display_block.inc,v 1.5.4.3 2010/08/04 05:54:08 dereine Exp $ /** * @file * Contains the block display plugin. @@ -64,6 +63,10 @@ class views_plugin_display_block extends views_plugin_display { $categories['block'] = array( 'title' => t('Block settings'), + 'column' => 'second', + 'build' => array( + '#weight' => -10, + ), ); $block_description = strip_tags($this->get_option('block_description')); @@ -72,12 +75,12 @@ class views_plugin_display_block extends views_plugin_display { } if (strlen($block_description) > 16) { - $block_description = substr($block_description, 0, 16) . '...'; + $block_description = drupal_substr($block_description, 0, 16) . '...'; } $options['block_description'] = array( 'category' => 'block', - 'title' => t('Admin'), + 'title' => t('Block name'), 'value' => $block_description, ); @@ -88,8 +91,8 @@ class views_plugin_display_block extends views_plugin_display { $types = $this->block_caching_modes(); $options['block_caching'] = array( - 'category' => 'block', - 'title' => t('Caching'), + 'category' => 'other', + 'title' => t('Block caching'), 'value' => $types[$this->get_cache_type()], ); } @@ -158,12 +161,15 @@ class views_plugin_display_block extends views_plugin_display { // It is very important to call the parent function here: parent::options_submit($form, $form_state); switch ($form_state['section']) { + case 'display_id': + $this->update_block_bid($form_state['view']->name, $this->display->id, $this->display->new_id); + break; case 'block_description': $this->set_option('block_description', $form_state['values']['block_description']); break; case 'block_caching': $this->set_option('block_caching', $form_state['values']['block_caching']); - $this->save_block_cache($form_state['view']->name.'-'.$form_state['display_id'], $form_state['values']['block_caching']); + $this->save_block_cache($form_state['view']->name . '-'. $form_state['display_id'], $form_state['values']['block_caching']); break; } } @@ -179,6 +185,23 @@ class views_plugin_display_block extends views_plugin_display { return FALSE; } + /** + * Update the block delta when you change the machine readable name of the display. + */ + function update_block_bid($name, $old_delta, $delta) { + $old_delta = $name . '-' . $old_delta; + $delta = $name . '-' . $delta; + if (strlen($old_delta) >= 32) { + $old_delta = md5($old_delta); + } + if (strlen($delta) >= 32) { + $delta = md5($delta); + } + db_update('block') + ->fields(array('delta' => $delta)) + ->condition('delta', $old_delta) + ->execute(); + } /** * Save the block cache setting in the blocks table if this block allready * exists in the blocks table. Dirty fix untill http://drupal.org/node/235673 gets in. diff --git a/sites/all/modules/views/plugins/views_plugin_display_default.inc b/sites/all/modules/views/plugins/views_plugin_display_default.inc index 2708967d79d8c2906f73c28afd43a2925bba9231..0d518e762795a97b47e57cc8ff974e77aaf4b43d 100644 --- a/sites/all/modules/views/plugins/views_plugin_display_default.inc +++ b/sites/all/modules/views/plugins/views_plugin_display_default.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_display_default.inc,v 1.1 2008/09/03 19:21:30 merlinofchaos Exp $ /** * @file * Contains the default display plugin. diff --git a/sites/all/modules/views/plugins/views_plugin_display_feed.inc b/sites/all/modules/views/plugins/views_plugin_display_feed.inc index 0d4f738a97f4ab26893bc8b8e32435abd6deb9f2..7eb99ae0665788e9eb28567bfe0d80d76eb2479d 100644 --- a/sites/all/modules/views/plugins/views_plugin_display_feed.inc +++ b/sites/all/modules/views/plugins/views_plugin_display_feed.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_display_feed.inc,v 1.7.4.5 2010/12/18 08:02:38 dereine Exp $ /** * @file * Contains the feed display plugin. @@ -13,6 +12,19 @@ * @ingroup views_display_plugins */ class views_plugin_display_feed extends views_plugin_display_page { + function init(&$view, &$display, $options = NULL) { + parent::init($view, $display, $options); + + // Set the default row style. Ideally this would be part of the option + // definition, but in this case it's dependent on the view's base table, + // which we don't know until init(). + $row_plugins = views_fetch_plugin_names('row', $this->get_style_type(), array($view->base_table)); + $default_row_plugin = key($row_plugins); + if ($this->options['row_plugin'] == '') { + $this->options['row_plugin'] = $default_row_plugin; + } + } + function uses_breadcrumb() { return FALSE; } function get_style_type() { return 'feed'; } @@ -87,6 +99,10 @@ class views_plugin_display_feed extends views_plugin_display_page { // category 'page' but let's override it so it says feed settings. $categories['page'] = array( 'title' => t('Feed settings'), + 'column' => 'second', + 'build' => array( + '#weight' => -10, + ), ); if ($this->get_option('sitename_title')) { @@ -136,7 +152,6 @@ class views_plugin_display_feed extends views_plugin_display_page { '#default_value' => $this->get_option('sitename_title'), ); $form['title'] = $title; - $form['title']['#process'] = array('ctools_dependent_process'); $form['title']['#dependency'] = array('edit-sitename-title' => array(FALSE)); break; case 'displays': @@ -155,7 +170,7 @@ class views_plugin_display_feed extends views_plugin_display_page { ); break; case 'path': - $form['path']['#description'] = t('This view will be displayed by visiting this path on your site. It is recommended that the path be something like "path/%/%/feed" or "path/%/%/rss.xml", putting one % in the path for each argument you have defined in the view.'); + $form['path']['#description'] = t('This view will be displayed by visiting this path on your site. It is recommended that the path be something like "path/%/%/feed" or "path/%/%/rss.xml", putting one % in the path for each contextual filter you have defined in the view.'); } } @@ -193,6 +208,10 @@ class views_plugin_display_feed extends views_plugin_display_page { $clone->set_display($this->display->id); $clone->build_title(); $plugin->attach_to($display_id, $this->get_path(), $clone->get_title()); + + // Clean up + $clone->destroy(); + unset($clone); } } 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 e7dabd40088698cd373b0c1d7877bcc286b33b1d..85f5bf9a7cb3287482366f6712b8b2ca937c0463 100644 --- a/sites/all/modules/views/plugins/views_plugin_display_page.inc +++ b/sites/all/modules/views/plugins/views_plugin_display_page.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_display_page.inc,v 1.8.4.14 2011/01/04 21:26:47 dereine Exp $ /** * @file * Contains the page display plugin. @@ -201,7 +200,7 @@ class views_plugin_display_page extends views_plugin_display { */ function execute() { // Let the world know that this is the page view we're using. - views_set_page_view($this); + views_set_page_view($this->view); // Prior to this being called, the $view should already be set to this // display, and arguments should be set on the view. @@ -230,6 +229,10 @@ class views_plugin_display_page extends views_plugin_display { $categories['page'] = array( 'title' => t('Page settings'), + 'column' => 'second', + 'build' => array( + '#weight' => -10, + ), ); $path = strip_tags($this->get_option('path')); @@ -277,6 +280,7 @@ class views_plugin_display_page extends views_plugin_display { // This adds a 'Settings' link to the style_options setting if the style has options. if ($menu['type'] == 'default tab') { + $options['menu']['setting'] = t('Parent menu item'); $options['menu']['links']['tab_options'] = t('Change settings for the parent menu'); } } @@ -294,7 +298,7 @@ class views_plugin_display_page extends views_plugin_display { $form['#help_topic'] = 'path'; $form['path'] = array( '#type' => 'textfield', - '#description' => t('This view will be displayed by visiting this path on your site. You may use "%" in your URL to represent values that will be used for arguments: For example, "node/%/feed".'), + '#description' => t('This view will be displayed by visiting this path on your site. You may use "%" in your URL to represent values that will be used for contextual filters: For example, "node/%/feed".'), '#default_value' => $this->get_option('path'), '#field_prefix' => '<span dir="ltr">' . url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q='), '#field_suffix' => '</span>‎', @@ -332,7 +336,6 @@ class views_plugin_display_page extends views_plugin_display { '#type' => 'textfield', '#default_value' => $menu['title'], '#description' => t('If set to normal or tab, enter the text to use for the menu item.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array('radio:menu[type]' => array('normal', 'tab', 'default tab')), ); $form['menu']['description'] = array( @@ -340,7 +343,6 @@ class views_plugin_display_page extends views_plugin_display { '#type' => 'textfield', '#default_value' => $menu['description'], '#description' => t("If set to normal or tab, enter the text to use for the menu item's description."), - '#process' => array('ctools_dependent_process'), '#dependency' => array('radio:menu[type]' => array('normal', 'tab', 'default tab')), ); @@ -352,7 +354,6 @@ class views_plugin_display_page extends views_plugin_display { '#options' => menu_get_menus(), '#default_value' => $menu['name'], '#description' => t('Insert item into an available menu.'), // - '#process' => array('form_process_select', 'ctools_dependent_process'), '#dependency' => array('radio:menu[type]' => array('normal')), ); } @@ -371,7 +372,6 @@ class views_plugin_display_page extends views_plugin_display { '#type' => 'textfield', '#default_value' => isset($menu['weight']) ? $menu['weight'] : 0, '#description' => t('The lower the weight the higher/further left it will appear.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array('radio:menu[type]' => array('normal', 'tab', 'default tab')), ); break; @@ -405,7 +405,6 @@ class views_plugin_display_page extends views_plugin_display { '#type' => 'textfield', '#default_value' => $tab_options['title'], '#description' => t('If creating a parent menu item, enter the title of the item.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array('radio:tab_options[type]' => array('normal', 'tab')), ); $form['tab_options']['description'] = array( @@ -413,7 +412,6 @@ class views_plugin_display_page extends views_plugin_display { '#type' => 'textfield', '#default_value' => $tab_options['description'], '#description' => t('If creating a parent menu item, enter the description of the item.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array('radio:tab_options[type]' => array('normal', 'tab')), ); // Only display the menu selector if menu module is enabled. @@ -424,7 +422,6 @@ class views_plugin_display_page extends views_plugin_display { '#options' => menu_get_menus(), '#default_value' => $tab_options['name'], '#description' => t('Insert item into an available menu.'), - '#process' => array('form_process_select', 'ctools_dependent_process'), '#dependency' => array('radio:tab_options[type]' => array('normal')), ); } @@ -434,7 +431,7 @@ class views_plugin_display_page extends views_plugin_display { '#value' => $tab_options['name'], ); $form['tab_options']['markup'] = array( - '#value' => t('Menu selection requires the activation of menu module.'), + '#markup' => t('Menu selection requires the activation of menu module.'), ); } $form['tab_options']['weight'] = array( @@ -444,7 +441,6 @@ class views_plugin_display_page extends views_plugin_display { '#default_value' => $tab_options['weight'], '#size' => 5, '#description' => t('If the parent menu item is a tab, enter the weight of the tab. The lower the number, the more to the left it will be.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array('radio:tab_options[type]' => array('tab')), ); break; @@ -514,13 +510,13 @@ class views_plugin_display_page extends views_plugin_display { $menu = $this->get_option('menu'); if (!empty($menu['type']) && $menu['type'] != 'none' && empty($menu['title'])) { - $errors[] = t('Display @display is set to use a menu but the menu title is not set.', array('@display' => $this->display->display_title)); + $errors[] = t('Display @display is set to use a menu but the menu link text is not set.', array('@display' => $this->display->display_title)); } if ($menu['type'] == 'default tab') { $tab_options = $this->get_option('tab_options'); if (!empty($tab_options['type']) && $tab_options['type'] != 'none' && empty($tab_options['title'])) { - $errors[] = t('Display @display is set to use a parent menu but the parent menu title is not set.', array('@display' => $this->display->display_title)); + $errors[] = t('Display @display is set to use a parent menu but the parent menu link text is not set.', array('@display' => $this->display->display_title)); } } diff --git a/sites/all/modules/views/plugins/views_plugin_exposed_form.inc b/sites/all/modules/views/plugins/views_plugin_exposed_form.inc index 8bef2f1b610bbb3424bbe498b52e083568950616..fae1f0403b1b42f54ae007f94adc4b355c22f60c 100644 --- a/sites/all/modules/views/plugins/views_plugin_exposed_form.inc +++ b/sites/all/modules/views/plugins/views_plugin_exposed_form.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_exposed_form.inc,v 1.2.2.18 2010/12/01 20:05:06 dereine Exp $ /** * The base plugin to handle exposed filter forms. @@ -21,20 +20,12 @@ class views_plugin_exposed_form extends views_plugin { $this->unpack_options($this->options, $options); } - /** - * Return a string to display as the clickable title for the - * control. - */ - function summary_title() { - return t('Unknown'); - } - function option_definition() { $options = parent::option_definition(); $options['submit_button'] = array('default' => t('Apply'), 'translatable' => TRUE); $options['reset_button'] = array('default' => FALSE, 'bool' => TRUE); $options['reset_button_label'] = array('default' => 'Reset', 'translatable' => TRUE); - $options['exposed_sorts_label'] = array('default' => 'Sort By', 'translatable' => TRUE); + $options['exposed_sorts_label'] = array('default' => 'Sort by', 'translatable' => TRUE); $options['sort_asc_label'] = array('default' => 'Asc', 'translatable' => TRUE); $options['sort_desc_label'] = array('default' => 'Desc', 'translatable' => TRUE); return $options; @@ -65,7 +56,6 @@ class views_plugin_exposed_form extends views_plugin { '#dependency' => array( 'edit-exposed-form-options-reset-button' => array(1) ), - '#process' => array('ctools_dependent_process'), ); $form['exposed_sorts_label'] = array( @@ -193,12 +183,17 @@ class views_plugin_exposed_form extends views_plugin { 'ASC' => $this->options['sort_asc_label'], 'DESC' => $this->options['sort_desc_label'], ); - $first_sort = reset($this->view->sort); + if (isset($form_state['input']['sort_by']) && isset($this->view->sort[$form_state['input']['sort_by']])) { + $default_sort_order = $this->view->sort[$form_state['input']['sort_by']]->options['order']; + } else { + $first_sort = reset($this->view->sort); + $default_sort_order = $first_sort->options['order']; + } $form['sort_order'] = array( '#type' => 'select', '#options' => $sort_order, '#title' => t('Order'), - '#default_value' => $first_sort->options['order'], + '#default_value' => $default_sort_order, ); $form['submit']['#weight'] = 10; if (isset($form['reset'])) { diff --git a/sites/all/modules/views/plugins/views_plugin_exposed_form_basic.inc b/sites/all/modules/views/plugins/views_plugin_exposed_form_basic.inc index 6e617f67d6846d6faa5dfb7cf9bc7ce604d91efa..71d4224df9ad84b8f68d2c117f0a0970661bbae9 100644 --- a/sites/all/modules/views/plugins/views_plugin_exposed_form_basic.inc +++ b/sites/all/modules/views/plugins/views_plugin_exposed_form_basic.inc @@ -1,13 +1,6 @@ <?php -// $Id: views_plugin_exposed_form_basic.inc,v 1.2.2.2 2009/12/26 20:36:39 dereine Exp $ /** * Exposed form plugin that provides basic exposed form */ -class views_plugin_exposed_form_basic extends views_plugin_exposed_form { - - function summary_title() { - return t('Basic'); - } - -} +class views_plugin_exposed_form_basic extends views_plugin_exposed_form { } diff --git a/sites/all/modules/views/plugins/views_plugin_exposed_form_input_required.inc b/sites/all/modules/views/plugins/views_plugin_exposed_form_input_required.inc index 89b5611e4841a9bc820239b6394b1e5b9636dd90..3774b406aa84662da3c5d85e18451ea54c03d071 100644 --- a/sites/all/modules/views/plugins/views_plugin_exposed_form_input_required.inc +++ b/sites/all/modules/views/plugins/views_plugin_exposed_form_input_required.inc @@ -1,15 +1,10 @@ <?php -// $Id: views_plugin_exposed_form_input_required.inc,v 1.2.2.8 2010/11/16 01:09:28 merlinofchaos Exp $ /** * Exposed form plugin that provides basic exposed form */ class views_plugin_exposed_form_input_required extends views_plugin_exposed_form { - function summary_title() { - return t('Input required'); - } - function option_definition() { $options = parent::option_definition(); diff --git a/sites/all/modules/views/plugins/views_plugin_localization.inc b/sites/all/modules/views/plugins/views_plugin_localization.inc index 0dd1416c40fe4180fe82923830869fe5414239d4..5b86402145d4568850060149eb2e8e9783ffa650 100644 --- a/sites/all/modules/views/plugins/views_plugin_localization.inc +++ b/sites/all/modules/views/plugins/views_plugin_localization.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_localization.inc,v 1.1.4.2 2010/12/01 20:05:06 dereine Exp $ /** * @file diff --git a/sites/all/modules/views/plugins/views_plugin_localization_core.inc b/sites/all/modules/views/plugins/views_plugin_localization_core.inc index 769e7d73199250f223fa910a55af3b6f8f9afec0..9c90e2b68001a2a5660c610737487fe5986e0740 100644 --- a/sites/all/modules/views/plugins/views_plugin_localization_core.inc +++ b/sites/all/modules/views/plugins/views_plugin_localization_core.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_localization_core.inc,v 1.1.4.2 2010/12/01 20:05:06 dereine Exp $ /** * @file @@ -23,7 +22,7 @@ class views_plugin_localization_core extends views_plugin_localization { * view name, display_id, and a property, e.g., 'header'. */ function translate_string($string, $keys = array()) { - return t($string); + return t($string); } /** @@ -46,7 +45,9 @@ class views_plugin_localization_core extends views_plugin_localization { $languages = language_list(); $cached_language = $language; unset($languages['en']); - $language = current($languages); + if (!empty($languages)) { + $language = current($languages); + } } t($string); diff --git a/sites/all/modules/views/plugins/views_plugin_localization_none.inc b/sites/all/modules/views/plugins/views_plugin_localization_none.inc index 1e090926ce03030a777573833fe83abaf5a9d951..620352a261a24c413cc93ffa8389da6a5bec5bf5 100644 --- a/sites/all/modules/views/plugins/views_plugin_localization_none.inc +++ b/sites/all/modules/views/plugins/views_plugin_localization_none.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_localization_none.inc,v 1.1.4.2 2010/12/01 20:05:06 dereine Exp $ /** * @file diff --git a/sites/all/modules/views/plugins/views_plugin_pager.inc b/sites/all/modules/views/plugins/views_plugin_pager.inc index f4ba7d7a2b3992ce30b51a849b486c7fdf6748c8..d639e54265d295ef10297889521edac5941d3eac 100644 --- a/sites/all/modules/views/plugins/views_plugin_pager.inc +++ b/sites/all/modules/views/plugins/views_plugin_pager.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_pager.inc,v 1.1.4.7 2010/04/29 18:39:26 merlinofchaos Exp $ /** * The base plugin to handle 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 4dcbee450d348f1990eb2667f720604f96c056bc..a0a448ff453c2c5cb7d9811931c91258335095c9 100644 --- a/sites/all/modules/views/plugins/views_plugin_pager_full.inc +++ b/sites/all/modules/views/plugins/views_plugin_pager_full.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_pager_full.inc,v 1.1.4.14 2010/12/16 20:32:17 dereine Exp $ /** * The plugin to handle full pager. @@ -9,9 +8,9 @@ class views_plugin_pager_full extends views_plugin_pager { function summary_title() { if (!empty($this->options['offset'])) { - return format_plural($this->options['items_per_page'], 'Paged, @count item, skip @skip', 'Paged, @count items, skip @skip', array('@count' => $this->options['items_per_page'], '@skip' => $this->options['offset'])); + return format_plural($this->options['items_per_page'], '@count item, skip @skip', 'Paged, @count items, skip @skip', array('@count' => $this->options['items_per_page'], '@skip' => $this->options['offset'])); } - return format_plural($this->options['items_per_page'], 'Paged, @count item', 'Paged, @count items', array('@count' => $this->options['items_per_page'])); + return format_plural($this->options['items_per_page'], '@count item', 'Paged, @count items', array('@count' => $this->options['items_per_page'])); } function option_definition() { @@ -90,7 +89,6 @@ class views_plugin_pager_full extends views_plugin_pager { '#required' => TRUE, '#description' => t('Label to use in the exposed items per page form element.'), '#default_value' => $this->options['expose']['items_per_page_label'], - '#process' => array('ctools_dependent_process'), '#dependency' => array( 'edit-pager-options-expose-items-per-page' => array(1) ), @@ -102,7 +100,6 @@ class views_plugin_pager_full extends views_plugin_pager { '#required' => TRUE, '#description' => t('Set between which values the user can choose when determining the items per page. Separated by comma.'), '#default_value' => $this->options['expose']['items_per_page_options'], - '#process' => array('ctools_dependent_process'), '#dependency' => array( 'edit-pager-options-expose-items-per-page' => array(1) ), @@ -121,7 +118,6 @@ class views_plugin_pager_full extends views_plugin_pager { '#title' => t('All items label'), '#description' => t('Which label will be used to display all items'), '#default_value' => $this->options['expose']['items_per_page_options_all_label'], - '#process' => array('ctools_dependent_process'), '#dependency' => array( 'edit-items-per-page-options-all' => array(1), ), @@ -140,7 +136,6 @@ class views_plugin_pager_full extends views_plugin_pager { '#required' => TRUE, '#description' => t('Label to use in the exposed offset form element.'), '#default_value' => $this->options['expose']['offset_label'], - '#process' => array('ctools_dependent_process'), '#dependency' => array( 'edit-pager-options-expose-offset' => array(1) ), diff --git a/sites/all/modules/views/plugins/views_plugin_pager_mini.inc b/sites/all/modules/views/plugins/views_plugin_pager_mini.inc index 1ada3bc84700d9f625b6fd4f277a0fd4843ed0b2..82c83d1c9385e14d42869623ccf6f8f557c8874f 100644 --- a/sites/all/modules/views/plugins/views_plugin_pager_mini.inc +++ b/sites/all/modules/views/plugins/views_plugin_pager_mini.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_pager_mini.inc,v 1.1.4.5 2011/01/04 00:00:20 dereine Exp $ /** * The plugin to handle full pager. diff --git a/sites/all/modules/views/plugins/views_plugin_pager_none.inc b/sites/all/modules/views/plugins/views_plugin_pager_none.inc index dd3275bb942d3dcc624ec6b513bf8e7423294239..6d56aeeeebbbdaadc7aa1d96fda3736bc7c39430 100644 --- a/sites/all/modules/views/plugins/views_plugin_pager_none.inc +++ b/sites/all/modules/views/plugins/views_plugin_pager_none.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_pager_none.inc,v 1.1.4.3 2010/11/06 17:56:10 dereine Exp $ /** * Plugin for views without pagers. diff --git a/sites/all/modules/views/plugins/views_plugin_pager_some.inc b/sites/all/modules/views/plugins/views_plugin_pager_some.inc index a2001d25ff37176df05ae1362f99fe07578dd8f2..28ed1a39b57c0b423b6484a61bd3c87aed2e38c2 100644 --- a/sites/all/modules/views/plugins/views_plugin_pager_some.inc +++ b/sites/all/modules/views/plugins/views_plugin_pager_some.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_pager_some.inc,v 1.1.4.3 2010/11/18 23:15:37 merlinofchaos Exp $ /** * Plugin for views without pagers. diff --git a/sites/all/modules/views/plugins/views_plugin_query.inc b/sites/all/modules/views/plugins/views_plugin_query.inc index 0c5e3d05e2e5878b9cc38121d9e884b03758bfb2..66680ecfc70d34f39a3ac44719c861a5941c7053 100644 --- a/sites/all/modules/views/plugins/views_plugin_query.inc +++ b/sites/all/modules/views/plugins/views_plugin_query.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_query.inc,v 1.1.4.13 2011/01/04 01:11:34 merlinofchaos Exp $ /** * @file views_plugin_query.inc * Defines the base query class, which is the underlying layer in a View. @@ -96,11 +95,11 @@ class views_plugin_query extends views_plugin { /** * Render the pager, if necessary. */ - function render_pager() { + function render_pager($exposed_input) { if (!empty($this->pager) && $this->pager->use_pager()) { - $exposed_input = isset($this->view->exposed_data_raw) ? $this->view->exposed_data_raw : NULL; return $this->pager->render($exposed_input); } + return ''; } 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 bd0497eb7cd98a08b7a08b2d0dae73dc5d01358d..6be8657b457c74fdd18af8e6f9f14204f67decf2 100644 --- a/sites/all/modules/views/plugins/views_plugin_query_default.inc +++ b/sites/all/modules/views/plugins/views_plugin_query_default.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_query_default.inc,v 1.1.4.39 2011/01/06 00:37:05 dereine Exp $ /** * @file views_plugin_query_default.inc * Defines the default query object which builds SQL to execute using the @@ -73,6 +72,13 @@ class views_plugin_query_default extends views_plugin_query { */ var $get_count_optimized = NULL; + /** + * The current used pager plugin. + * + * @var views_plugin_pager + */ + var $pager = NULL; + /** * Constructor; Create the basic query object and fill with default values. */ @@ -173,6 +179,9 @@ class views_plugin_query_default extends views_plugin_query { $options['field_language'] = array( 'default' => '***CURRENT_LANGUAGE***', ); + $options['field_language_add_to_query'] = array( + 'default' => 1, + ); return $options; } @@ -183,7 +192,7 @@ class views_plugin_query_default extends views_plugin_query { function options_form(&$form, &$form_state) { $form['disable_sql_rewrite'] = array( '#title' => t('Disable SQL rewriting'), - '#description' => t('Disabling SQL rewriting will disable node_access checks as well as other modules that implement hook_db_rewrite_sql().'), + '#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>', @@ -219,7 +228,7 @@ class views_plugin_query_default extends views_plugin_query { $languages = array( '***CURRENT_LANGUAGE***' => t("Current user's language"), '***DEFAULT_LANGUAGE***' => t("Default site language"), - LANGUAGE_NONE => t('No language') + LANGUAGE_NONE => t('Language neutral'), ); $languages = array_merge($languages, locale_language_list()); @@ -230,6 +239,11 @@ class views_plugin_query_default extends views_plugin_query { '#options' => $languages, '#default_value' => $this->options['field_language'], ); + $form['field_language_add_to_query'] = array( + '#type' => 'checkbox', + '#title' => t('When needed, add the field language condition to the query.'), + '#default_value' => $this->options['field_language_add_to_query'], + ); } } @@ -347,11 +361,11 @@ class views_plugin_query_default extends views_plugin_query { } /** - * Add a table to the query, without ensuring the path. + * Add a table to the query without ensuring the path. * - * This function will test to ensure that the path back to the primary - * table is valid and exists; if you do not wish for this testing to - * occur, use $query->queue_table() instead. + * This is a pretty internal function to Views and add_table() or + * ensure_table() should be used instead of this one, unless you are + * absolutely sure this is what you want. * * @param $table * The name of the table to add. It needs to exist in the global table @@ -933,6 +947,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 * @param $field * The field or formula to sort on. If already a field, enter NULL * and put in the alias. @@ -946,7 +961,7 @@ class views_plugin_query_default extends views_plugin_query { * @param $params * Any params that should be passed through to the add_field. */ - function add_orderby($table, $field, $order, $alias = '', $params = array()) { + function add_orderby($table, $field = NULL, $order = 'ASC', $alias = '', $params = array()) { if ($table) { $this->ensure_table($table); } @@ -1115,6 +1130,7 @@ class views_plugin_query_default extends views_plugin_query { if (empty($this->no_distinct) && $this->distinct && !empty($this->fields)) { $base_field_alias = $this->add_field($this->base_table, $this->base_field); $this->add_groupby($base_field_alias); + $distinct = TRUE; } /** @@ -1138,18 +1154,25 @@ class views_plugin_query_default extends views_plugin_query { } $options = array(); - // Detect an external database. + $target = 'default'; + $key = 'default'; + // Detect an external database and set the if (isset($this->view->base_database)) { - $options['target'] = $this->view->base_database; + $key = $this->view->base_database; } // Set the slave target if the slave option is set if (!empty($this->options['slave'])) { - $options['target'] = 'slave'; + $target = 'slave'; } // Go ahead and build the query. - $query = db_select($this->base_table, $this->base_table, $options)->addTag('views'); + // db_select doesn't support to specify the key, so use getConnection directly. + $query = Database::getConnection($target, $key)->select($this->base_table, $this->base_table, $options)->addTag('views'); + + if (!empty($distinct)) { + $query->distinct(); + } $joins = $where = $having = $orderby = $groupby = ''; $fields = $distinct = array(); @@ -1169,7 +1192,7 @@ class views_plugin_query_default extends views_plugin_query { if (count($this->having)) { $this->has_aggregate = TRUE; } - if ($this->has_aggregate || $this->groupby) { + if ($this->has_aggregate && (!empty($this->groupby) || !empty($non_aggregates))) { $groupby = array_unique(array_merge($this->groupby, $non_aggregates)); foreach ($groupby as $field) { $query->groupBy($field); @@ -1183,7 +1206,12 @@ class views_plugin_query_default extends views_plugin_query { // we only add the orderby if we're not counting. if ($this->orderby) { foreach ($this->orderby as $order) { - $query->orderBy($order['field'], $order['direction']); + if ($order['field'] == 'rand_') { + $query->orderRandom(); + } + else { + $query->orderBy($order['field'], $order['direction']); + } } } } @@ -1231,6 +1259,9 @@ class views_plugin_query_default extends views_plugin_query { $this->set_distinct(); } + // Store the view in the object to be able to use it later. + $this->view = $view; + $view->init_pager(); // Let the pager modify the query to add limits. @@ -1267,9 +1298,18 @@ class views_plugin_query_default extends views_plugin_query { $items = array(); if ($query) { $additional_arguments = module_invoke_all('views_query_substitutions', $view); + + // Count queries must be run through the preExecute() method. + // If not, then hook_query_node_access_alter() may munge the count by + // adding a distinct against an empty query string + // (e.g. COUNT DISTINCT(1) ...) and no pager will return. + // See pager.inc > PagerDefault::execute() + // http://api.drupal.org/api/drupal/includes--pager.inc/function/PagerDefault::execute/7 + // See http://drupal.org/node/1046170. + $count_query->preExecute(); + // Build the count query. $count_query = $count_query->countQuery(); - // $count_query->distinct = FALSE; // Add additional arguments as a fake condition. // XXX: this doesn't work... because PDO mandates that all bound arguments diff --git a/sites/all/modules/views/plugins/views_plugin_row.inc b/sites/all/modules/views/plugins/views_plugin_row.inc index 55d9303a752f9bd27db190835f475ba34c523011..36b02b11773d6e5c78039864e95fe0ae45886b7f 100644 --- a/sites/all/modules/views/plugins/views_plugin_row.inc +++ b/sites/all/modules/views/plugins/views_plugin_row.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_row.inc,v 1.4.4.4 2010/05/12 22:29:46 dereine Exp $ /** * @file * Contains the base row style plugin. diff --git a/sites/all/modules/views/plugins/views_plugin_row_fields.inc b/sites/all/modules/views/plugins/views_plugin_row_fields.inc index 9e3db8b9fb69c0de9fe90118cee607f0bde650c7..307ee5fee9012794ff208921c32b0a29666f9fd4 100644 --- a/sites/all/modules/views/plugins/views_plugin_row_fields.inc +++ b/sites/all/modules/views/plugins/views_plugin_row_fields.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_row_fields.inc,v 1.2.4.4 2010/12/04 07:39:35 dereine Exp $ /** * @file * Contains the base row style plugin. diff --git a/sites/all/modules/views/plugins/views_plugin_style.inc b/sites/all/modules/views/plugins/views_plugin_style.inc index 390ddf8dde982454fd1ced1343c0a7e1f0687030..5fdece56eb6707309264e8f9067d0f36d86fd033 100644 --- a/sites/all/modules/views/plugins/views_plugin_style.inc +++ b/sites/all/modules/views/plugins/views_plugin_style.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_style.inc,v 1.8.4.10 2010/12/10 08:12:31 dereine Exp $ /** * @defgroup views_style_plugins Views' style plugins @@ -101,12 +100,18 @@ class views_plugin_style extends views_plugin { * Return the token replaced row class for the specified row. */ function get_row_class($row_index) { - $class = $this->options['row_class']; - if ($this->uses_fields() && $this->view->field) { - $class = $this->tokenize_value($class, $row_index); - } + if ($this->uses_row_class()) { + $class = $this->options['row_class']; + if ($this->uses_fields() && $this->view->field) { + $class = $this->tokenize_value($class, $row_index); + } - return drupal_clean_css_identifier($class); + $classes = explode(' ', $class); + foreach ($classes as &$class) { + $class = drupal_clean_css_identifier($class); + } + return implode(' ', $classes); + } } /** @@ -128,6 +133,13 @@ class views_plugin_style extends views_plugin { return $value; } + /** + * Should the output of the style plugin be rendered even if it's a empty view. + */ + function even_empty() { + return !empty($this->definition['even empty']); + } + function option_definition() { $options = parent::option_definition(); $options['grouping'] = array('default' => ''); diff --git a/sites/all/modules/views/plugins/views_plugin_style_default.inc b/sites/all/modules/views/plugins/views_plugin_style_default.inc index 0e2d83a64c8a56fe44d583b196d92a80cae25b60..e8c9db83066c03823f79b3fde40b40b1f500117f 100644 --- a/sites/all/modules/views/plugins/views_plugin_style_default.inc +++ b/sites/all/modules/views/plugins/views_plugin_style_default.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_style_default.inc,v 1.2 2008/09/30 19:47:11 merlinofchaos Exp $ /** * @file * Contains the default style plugin. diff --git a/sites/all/modules/views/plugins/views_plugin_style_grid.inc b/sites/all/modules/views/plugins/views_plugin_style_grid.inc index 08cebd8f7cfada06f486f5cd64b6e908652fe7f9..91722f2671c31d85c0052c834e623342a464f2b2 100644 --- a/sites/all/modules/views/plugins/views_plugin_style_grid.inc +++ b/sites/all/modules/views/plugins/views_plugin_style_grid.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_style_grid.inc,v 1.1.6.2 2010/12/10 08:19:15 dereine Exp $ /** * @file * Contains the grid style plugin. @@ -46,7 +45,7 @@ class views_plugin_style_grid extends views_plugin_style { $form['fill_single_line'] = array( '#type' => 'checkbox', '#title' => t('Fill up single line'), - '#description' => t('If you disable this option a grid with only one row will have the amount of items as tds. If you disable it this can cause problems with your css.'), + '#description' => t('If you disable this option, a grid with only one row will have the same number of table cells (<TD>) as items. Disabling it can cause problems with your CSS.'), '#default_value' => !empty($this->options['fill_single_line']), ); diff --git a/sites/all/modules/views/plugins/views_plugin_style_jump_menu.inc b/sites/all/modules/views/plugins/views_plugin_style_jump_menu.inc index 19e1cd3397f44f7d94cf7170e1351b431d491c7d..f8df2f64525fd691bfd25dc7421bd9795937bc68 100644 --- a/sites/all/modules/views/plugins/views_plugin_style_jump_menu.inc +++ b/sites/all/modules/views/plugins/views_plugin_style_jump_menu.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_style_jump_menu.inc,v 1.1.6.7 2010/12/14 00:47:26 merlinofchaos Exp $ /** * @file * Contains the table style plugin. @@ -31,15 +30,15 @@ class views_plugin_style_jump_menu extends views_plugin_style { $handlers = $this->display->handler->get_handlers('field'); if (empty($handlers)) { $form['error_markup'] = array( - '#value' => t('You need at least one field before you can configure your jump menu settings'), - '#prefix' => '<div class="error form-item description">', + '#markup' => t('You need at least one field before you can configure your jump menu settings'), + '#prefix' => '<div class="error messages">', '#suffix' => '</div>', ); return; } $form['markup'] = array( - '#value' => t('To properly configure a jump menu, you must select one field that will represent the path to utilize. You should then set that field to exclude. 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.'), + '#markup' => t('To properly configure a jump menu, you must select one field that will represent the path to utilize. You should then set that field to exclude. 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.'), '#prefix' => '<div class="form-item description">', '#suffix' => '</div>', ); @@ -77,7 +76,7 @@ class views_plugin_style_jump_menu extends views_plugin_style { $form['default_value'] = array( '#type' => 'checkbox', - '#title' => t('Select the current argument.'), + '#title' => t('Select the current contextual filter value.'), '#default_value' => !empty($this->options['default_value']), '#description' => t('If checked, the current path will be displayed as the default option in the jump menu, if applicable.'), ); @@ -89,29 +88,7 @@ class views_plugin_style_jump_menu extends views_plugin_style { * This is overridden so that we can render our grouping specially. */ function render() { - $result = $this->view->result; - // Group the rows according to the grouping field, if specified. - $fields = $this->render_fields($result); - $sets = array(); - if ($this->options['grouping']) { - foreach ($result 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[$this->options['grouping']])) { - $grouping = strip_tags($this->get_field($index, $this->options['grouping'])); - if ($this->view->field[$this->options['grouping']]->options['label']) { - $grouping = $this->view->field[$this->options['grouping']]->options['label'] . ': ' . $grouping; - } - } - $sets[$grouping][] = $row; - } - } - else { - // Create a single group with an empty grouping field. - $sets[''] = $result; - } + $sets = $this->render_grouping($this->view->result, $this->options['grouping']); // Turn this all into an $options array for the jump menu. $this->view->row_index = 0; @@ -119,7 +96,8 @@ class views_plugin_style_jump_menu extends views_plugin_style { $paths = array(); foreach ($sets as $title => $records) { - foreach ($records as $row) { + foreach ($records as $row_index => $row) { + $this->view->row_index = $row_index; $path = strip_tags($this->get_field($this->view->row_index, $this->options['path'])); // Putting a '/' in front messes up url() so let's take that out // so users don't shoot themselves in the foot. @@ -127,18 +105,10 @@ class views_plugin_style_jump_menu extends views_plugin_style { $path = substr($path, 1); } - // use parse_url() to preserve query and fragment in case the user + // use drupal_parse_url() to preserve query and fragment in case the user // wants to do fun tricks. - $url = parse_url($path); - $url_options = array(); - if (isset($url['query'])) { - $path = strtr($path, array('?' . $url['query'] => '')); - $url_options['query'] = $url['query']; - } - if (isset($url['fragment'])) { - $path = strtr($path, array('#' . $url['fragment'] => '')); - $url_options['fragment'] = $url['fragment']; - } + $url_options = drupal_parse_url($path); + $path = $url_options['path']; $path = url($path, $url_options); $field = strip_tags($this->row_plugin->render($row)); @@ -167,7 +137,8 @@ class views_plugin_style_jump_menu extends views_plugin_style { 'default_value' => $default_value, ); - return drupal_render(drupal_get_form('ctools_jump_menu', $options, $settings)); + $form = drupal_get_form('ctools_jump_menu', $options, $settings); + return drupal_render($form); } function render_set($title, $records) { diff --git a/sites/all/modules/views/plugins/views_plugin_style_list.inc b/sites/all/modules/views/plugins/views_plugin_style_list.inc index eac331c5e221566619f80aef39198a7b8dc3a3a6..2b21ee85c7df1b63e34fbf5897d4db6a2e39d6e1 100644 --- a/sites/all/modules/views/plugins/views_plugin_style_list.inc +++ b/sites/all/modules/views/plugins/views_plugin_style_list.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_style_list.inc,v 1.1.6.1 2010/12/04 07:39:35 dereine Exp $ /** * @file * Contains the list style plugin. 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 7be2dedb040ae1a72ba45345934ac60afe275e70..0a0598e2b3b8f510dbb81b3517121ae00a15a203 100644 --- a/sites/all/modules/views/plugins/views_plugin_style_rss.inc +++ b/sites/all/modules/views/plugins/views_plugin_style_rss.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_style_rss.inc,v 1.2.6.7 2010/12/18 08:02:38 dereine Exp $ /** * @file * Contains the RSS style plugin. @@ -57,7 +56,6 @@ class views_plugin_style_rss extends views_plugin_style { '#title' => t('RSS description'), '#default_value' => $this->options['description'], '#description' => t('This will appear in the RSS feed itself.'), - '#process' => array('ctools_dependent_process'), '#dependency' => array('edit-style-options-override' => array(FALSE)), ); } 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 3279bd4ebfb7c932816dfa69b292105e4793025f..527dd3b42d0b1397fc06701b1f3526845d49eca8 100644 --- a/sites/all/modules/views/plugins/views_plugin_style_summary.inc +++ b/sites/all/modules/views/plugins/views_plugin_style_summary.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_style_summary.inc,v 1.1.6.6 2010/11/05 07:20:54 dereine Exp $ /** * @file * Contains the default summary style plugin, which displays items in an HTML list. @@ -53,7 +52,6 @@ class views_plugin_style_summary extends views_plugin_style { '#type' => 'textfield', '#title' => t('Items to display'), '#default_value' => $this->options['items_per_page'], - '#process' => array('ctools_dependent_process'), '#dependency' => array('edit-style-options-override' => array(TRUE)), ); } 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 3dc06b4e7a056aefa21057d2816eab2370866774..688a6cfa4625ef109b572e3a0b2cf80898d88f2b 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_style_summary_jump_menu.inc,v 1.1.6.6 2010/12/14 00:47:26 merlinofchaos Exp $ /** * @file * Contains the default summary style plugin, which displays items in an HTML list. @@ -25,9 +24,10 @@ class views_plugin_style_summary_jump_menu extends views_plugin_style { } function query() { + // Copy the offset option. $pager = array( 'type' => 'none', - 'options' => array(), + 'options' => $this->display->handler->options['pager']['options'], ); $this->display->handler->set_option('pager', $pager); } @@ -72,9 +72,9 @@ class views_plugin_style_summary_jump_menu extends views_plugin_style { $form['default_value'] = array( '#type' => 'checkbox', - '#title' => t('Select the current argument.'), + '#title' => t('Select the current contextual filter value.'), '#default_value' => !empty($this->options['default_value']), - '#description' => t('If checked, the current argument setting will be displayed as the default option in the jump menu, if applicable.'), + '#description' => t('If checked, the current contextual filter value will be displayed as the default option in the jump menu, if applicable.'), ); } @@ -115,7 +115,8 @@ class views_plugin_style_summary_jump_menu extends views_plugin_style { 'default_value' => $default_value, ); - return drupal_get_form('ctools_jump_menu', $options, $settings); + $form = drupal_get_form('ctools_jump_menu', $options, $settings); + return drupal_render($form); } } diff --git a/sites/all/modules/views/plugins/views_plugin_style_summary_unformatted.inc b/sites/all/modules/views/plugins/views_plugin_style_summary_unformatted.inc index 00fb69933c0b5c1cfe83969ef8a9160272caa4ca..69a8d721d9a8d24eebb466c85135da1452e95293 100644 --- a/sites/all/modules/views/plugins/views_plugin_style_summary_unformatted.inc +++ b/sites/all/modules/views/plugins/views_plugin_style_summary_unformatted.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_style_summary_unformatted.inc,v 1.1 2008/09/03 19:21:30 merlinofchaos Exp $ /** * @file * Contains the unformatted summary style plugin. 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 db3f8528d09a0e707c8853b1a87ee75787edb831..e0b784bc01552e7d675f02e406f7ae12ce30e97f 100644 --- a/sites/all/modules/views/plugins/views_plugin_style_table.inc +++ b/sites/all/modules/views/plugins/views_plugin_style_table.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_style_table.inc,v 1.7.4.12 2010/12/10 08:19:15 dereine Exp $ /** * @file * Contains the table style plugin. @@ -21,6 +20,7 @@ class views_plugin_style_table extends views_plugin_style { $options['sticky'] = array('default' => FALSE); $options['order'] = array('default' => 'asc'); $options['summary'] = array('default' => ''); + $options['empty_table'] = array('default' => FALSE); return $options; } @@ -138,7 +138,7 @@ class views_plugin_style_table extends views_plugin_style { $handlers = $this->display->handler->get_handlers('field'); if (empty($handlers)) { $form['error_markup'] = array( - '#markup' => '<div class="error form-item description">' . t('You need at least one field before you can configure your table settings') . '</div>', + '#markup' => '<div class="error messages">' . t('You need at least one field before you can configure your table settings') . '</div>', ); return; } @@ -204,14 +204,12 @@ class views_plugin_style_table extends views_plugin_style { $form['info'][$field]['sortable'] = array( '#type' => 'checkbox', '#default_value' => !empty($this->options['info'][$field]['sortable']), - '#process' => array('form_process_checkbox', 'ctools_dependent_process'), '#dependency' => array($id => array($field)), ); $form['info'][$field]['default_sort_order'] = array( '#type' => 'select', '#options' => array('asc' => t('Ascending'), 'desc' => t('Descending')), '#default_value' => !empty($this->options['info'][$field]['default_sort_order']) ? $this->options['info'][$field]['default_sort_order'] : 'asc', - '#process' => array('ctools_dependent_process'), '#dependency_count' => 2, '#dependency' => array($id => array($field), 'edit-style-options-info-' . $safe . '-sortable' => array(1)), ); @@ -225,7 +223,6 @@ class views_plugin_style_table extends views_plugin_style { // because 'radio' doesn't fully support '#id' =( '#attributes' => array('id' => $radio_id), '#default_value' => $default, - '#process' => array('ctools_dependent_process'), '#dependency' => array($id => array($field)), ); } @@ -238,14 +235,12 @@ class views_plugin_style_table extends views_plugin_style { 'views-align-center' => t('Center'), 'views-align-right' => t('Right'), ), - '#process' => array('form_process_select', 'ctools_dependent_process'), '#dependency' => array($id => array($field)), ); $form['info'][$field]['separator'] = array( '#type' => 'textfield', '#size' => 10, '#default_value' => isset($this->options['info'][$field]['separator']) ? $this->options['info'][$field]['separator'] : '', - '#process' => array('ctools_dependent_process'), '#dependency' => array($id => array($field)), ); @@ -264,8 +259,19 @@ class views_plugin_style_table extends views_plugin_style { '#default_value' => $default, ); + $form['empty_table'] = array( + '#type' => 'checkbox', + '#title' => t('Show the empty text in the table.'), + '#default_value' => $this->options['empty_table'], + '#description' => t('Per default the table is hidden for an empty view. With this option it is posible to show an empty table with the text in it.'), + ); + $form['description_markup'] = array( '#markup' => '<div class="description form-item">' . t('Place fields into columns; you may combine multiple fields into the same column. If you do, the separator in the column specified will be used to separate the fields. Check the sortable box to make that column click sortable, and check the default sort radio to determine which column will be sorted by default, if any. You may control column order and field labels in the fields section.') . '</div>', ); } + + function even_empty() { + return parent::even_empty() || !empty($this->options['empty_table']); + } } diff --git a/sites/all/modules/views/plugins/views_wizard/comment.inc b/sites/all/modules/views/plugins/views_wizard/comment.inc new file mode 100644 index 0000000000000000000000000000000000000000..a91078849af3c858000d1f0e201794094c47ee65 --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/comment.inc @@ -0,0 +1,44 @@ +<?php + +/** + * @file + * Views wizard for comment views. + */ + +// Parent plugin. +if (module_exists('comment')) { + $plugin = array( + 'name' => 'comment', + 'base_table' => 'comment', + 'created_column' => 'created', + 'form_wizard_class' => array( + 'file' => 'views_ui_comment_views_wizard.class.php', + 'class' => 'ViewsUiCommentViewsWizard', + ), + 'title' => t('Comments'), + 'filters' => array( + 'status' => array( + 'value' => COMMENT_PUBLISHED, + 'table' => 'comment', + 'field' => 'status', + ), + 'status_node' => array( + 'value' => NODE_PUBLISHED, + 'table' => 'node', + 'field' => 'status', + 'relationship' => 'nid', + ), + ), + 'path_field' => array( + 'id' => 'cid', + 'table' => 'comment', + 'field' => 'cid', + 'exclude' => TRUE, + 'link_to_comment' => FALSE, + 'alter' => array( + 'alter_text' => 1, + 'text' => 'comment/[cid]#comment-[cid]', + ), + ), + ); +} diff --git a/sites/all/modules/views/plugins/views_wizard/file_managed.inc b/sites/all/modules/views/plugins/views_wizard/file_managed.inc new file mode 100644 index 0000000000000000000000000000000000000000..049ce1b523db159d0023ee6eb4f2822ef0e7e02c --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/file_managed.inc @@ -0,0 +1,26 @@ +<?php + +/** + * @file + * Views wizard for managed file views. + */ + +$plugin = array( + 'name' => 'file_managed', + 'base_table' => 'file_managed', + 'created_column' => 'timestamp', + 'form_wizard_class' => array( + 'file' => 'views_ui_file_managed_views_wizard.class.php', + 'class' => 'ViewsUiFileManagedViewsWizard', + ), + 'title' => t('Files'), + 'filters' => array( + ), + 'path_field' => array( + 'id' => 'uri', + 'table' => 'file_managed', + 'field' => 'uri', + 'exclude' => TRUE, + 'file_download_path' => TRUE, + ), +); diff --git a/sites/all/modules/views/plugins/views_wizard/node.inc b/sites/all/modules/views/plugins/views_wizard/node.inc new file mode 100644 index 0000000000000000000000000000000000000000..ccca48dec999114ee95105e10aed6b635765537d --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/node.inc @@ -0,0 +1,42 @@ +<?php + +/** + * @file + * Views wizard for node views. + */ + +$plugin = array( + 'name' => 'node', + 'base_table' => 'node', + 'created_column' => 'created', + 'available_sorts' => array( + 'title:DESC' => t('Title') + ), + 'form_wizard_class' => array( + 'file' => 'views_ui_node_views_wizard.class.php', + 'class' => 'ViewsUiNodeViewsWizard', + ), + 'title' => t('Content'), + 'filters' => array( + 'status' => array( + 'value' => NODE_PUBLISHED, + 'table' => 'node', + 'field' => 'status', + ), + ), + 'path_field' => array( + 'id' => 'nid', + 'table' => 'node', + 'field' => 'nid', + 'exclude' => TRUE, + 'link_to_node' => FALSE, + 'alter' => array( + 'alter_text' => 1, + 'text' => 'node/[nid]', + ), + ), +); + +if (module_exists('statistics')) { + $plugin['available_sorts']['node_counter-totalcount:DESC'] = t('Number of hits'); +} diff --git a/sites/all/modules/views/plugins/views_wizard/node_revision.inc b/sites/all/modules/views/plugins/views_wizard/node_revision.inc new file mode 100644 index 0000000000000000000000000000000000000000..ddf1d61ce25b2a43465b869cfc12bf03603951f7 --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/node_revision.inc @@ -0,0 +1,43 @@ +<?php + +/** + * @file + * Views wizard for node revision views. + */ + +$plugin = array( + 'name' => 'node_revision', + 'base_table' => 'node_revision', + 'created_column' => 'timestamp', + 'form_wizard_class' => array( + 'file' => 'views_ui_node_revision_views_wizard.class.php', + 'class' => 'ViewsUiNodeRevisionViewsWizard', + ), + 'title' => t('Content revisions'), + 'filters' => array( + 'status' => array( + 'value' => '1', + 'table' => 'node', // @todo - unclear if this should be node or node_revision + 'field' => 'status', + ), + ), + 'path_field' => array( + 'id' => 'vid', + 'table' => 'node_revision', + 'field' => 'vid', + 'exclude' => TRUE, + 'alter' => array( + 'alter_text' => 1, + 'text' => 'node/[nid]/revisions/[vid]/view', + ), + ), + 'path_fields_supplemental' => array( + array( + 'id' => 'nid', + 'table' => 'node', + 'field' => 'nid', + 'exclude' => TRUE, + 'link_to_node' => FALSE, + ), + ), +); diff --git a/sites/all/modules/views/plugins/views_wizard/taxonomy_term.inc b/sites/all/modules/views/plugins/views_wizard/taxonomy_term.inc new file mode 100644 index 0000000000000000000000000000000000000000..599e3543660e71ca22c804ba01cfe35c0b0a343b --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/taxonomy_term.inc @@ -0,0 +1,30 @@ +<?php + +/** + * @file + * Views wizard for taxonomy term views. + */ + +if (module_exists('taxonomy')) { + $plugin = array( + 'name' => 'taxonomy_term', + 'base_table' => 'taxonomy_term_data', + 'form_wizard_class' => array( + 'file' => 'views_ui_taxonomy_term_views_wizard.class.php', + 'class' => 'ViewsUiTaxonomyTermViewsWizard', + ), + 'title' => t('Taxonomy terms'), + 'filters' => array( + ), + 'path_field' => array( + 'id' => 'tid', + 'table' => 'taxonomy_term_data', + 'field' => 'tid', + 'exclude' => TRUE, + 'alter' => array( + 'alter_text' => 1, + 'text' => 'taxonomy/term/[tid]', + ), + ), + ); +} diff --git a/sites/all/modules/views/plugins/views_wizard/users.inc b/sites/all/modules/views/plugins/views_wizard/users.inc new file mode 100644 index 0000000000000000000000000000000000000000..038fb7cb97fbe283091ea713d5975e829c2beb6f --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/users.inc @@ -0,0 +1,36 @@ +<?php + +/** + * @file + * Views wizard for user views. + */ + +$plugin = array( + 'name' => 'users', + 'base_table' => 'users', + 'created_column' => 'created', + 'form_wizard_class' => array( + 'file' => 'views_ui_users_views_wizard.class.php', + 'class' => 'ViewsUiUsersViewsWizard', + ), + 'title' => t('Users'), + 'filters' => array( + 'status' => array( + 'value' => '1', + 'table' => 'users', + 'field' => 'status', + ), + ), + 'path_field' => array( + 'id' => 'uid', + 'table' => 'users', + 'field' => 'uid', + 'exclude' => TRUE, + 'link_to_user' => FALSE, + 'alter' => array( + 'alter_text' => 1, + 'text' => 'user/[uid]', + ), + ), +); + 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 new file mode 100644 index 0000000000000000000000000000000000000000..cac9a7d5d4c367f28c665ca99412a6c64993d0a1 --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/views_ui_base_views_wizard.class.php @@ -0,0 +1,875 @@ +<?php + +interface ViewsWizardInterface { + function __construct($plugin); + + /** + * For AJAX callbacks to build other elements in the "show" form. + */ + function build_form($form, &$form_state); + + /** + * Validate form and values. + * + * @return an array of form errors. + */ + function validate($form, &$form_state); + + /** + * Create a new View from form values. + * + * @return a view object. + * + * @throws ViewsWizardException in the event of a problem. + */ + function create_view($form, &$form_state); +} + +/** + * A custom exception class for our errors. + */ +class ViewsWizardException extends Exception { +} + +/** + * A very generic Views Wizard class - can be constructed for any base table. + */ +class ViewsUiBaseViewsWizard implements ViewsWizardInterface { + protected $base_table; + protected $entity_type; + protected $entity_info = array(); + protected $validated_views = array(); + protected $plugin = array(); + protected $filter_defaults = array( + 'id' => NULL, + 'expose' => array('operator' => FALSE), + 'group' => 0, + ); + + function __construct($plugin) { + $this->base_table = $plugin['base_table']; + $default = $this->filter_defaults; + + if (isset($plugin['filters'])) { + foreach ($plugin['filters'] as $name => $info) { + $default['id'] = $name; + $plugin['filters'][$name] = $info + $default; + } + } + + $this->plugin = $plugin; + + $entities = entity_get_info(); + foreach ($entities as $entity_type => $entity_info) { + if ($this->base_table == $entity_info['base table']) { + $this->entity_info = $entity_info; + $this->entity_type = $entity_type; + } + } + } + + function build_form($form, &$form_state) { + $style_options = views_fetch_plugin_names('style', 'normal', array($this->base_table)); + $feed_row_options = views_fetch_plugin_names('row', 'feed', array($this->base_table)); + $path_prefix = url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q='); + + // Add filters and sorts which apply to the view as a whole. + $this->build_filters($form, $form_state); + $this->build_sorts($form, $form_state); + + $form['displays']['page'] = array( + '#type' => 'fieldset', + '#attributes' => array('class' => array('views-attachment', 'fieldset-no-legend'),), + '#tree' => TRUE, + ); + $form['displays']['page']['create'] = array( + '#title' => t('Create a page'), + '#type' => 'checkbox', + '#attributes' => array('class' => array('strong')), + '#default_value' => TRUE, + '#id' => 'edit-page-create', + ); + + // All options for the page display are included in this container so they + // can be hidden en masse when the "Create a page" checkbox is unchecked. + $form['displays']['page']['options'] = array( + '#type' => 'container', + '#attributes' => array('class' => array('options-set'),), + '#dependency' => array( + 'edit-page-create' => array(1), + ), + '#pre_render' => array('ctools_dependent_pre_render'), + '#prefix' => '<div><div id="edit-page-wrapper">', + '#suffix' => '</div></div>', + '#parents' => array('page'), + ); + + $form['displays']['page']['options']['title'] = array( + '#title' => t('Page title'), + '#type' => 'textfield', + ); + $form['displays']['page']['options']['path'] = array( + '#title' => t('Path'), + '#type' => 'textfield', + '#field_prefix' => $path_prefix, + ); + $form['displays']['page']['options']['style'] = array( + '#type' => 'fieldset', + '#attributes' => array('class' => array('container-inline', 'fieldset-no-legend')), + ); + + // Create the dropdown for choosing the display format. + $form['displays']['page']['options']['style']['style_plugin'] = array( + '#title' => t('Display format'), + '#help_topic' => 'style', + '#type' => 'select', + '#options' => $style_options, + ); + $style_form = &$form['displays']['page']['options']['style']; + $style_form['style_plugin']['#default_value'] = views_ui_get_selected($form_state, array('page', 'style', 'style_plugin'), 'default', $style_form['style_plugin']); + // Changing this dropdown updates $form['displays']['page']['options'] via + // AJAX. + views_ui_add_ajax_trigger($style_form, 'style_plugin', array('displays', 'page', 'options')); + + $this->build_form_style($form, $form_state, 'page'); + $form['displays']['page']['options']['items_per_page'] = array( + '#title' => t('Items per page'), + '#type' => 'textfield', + '#default_value' => '10', + '#size' => 5, + '#element_validate' => array('_element_validate_integer_positive'), + ); + $form['displays']['page']['options']['link'] = array( + '#title' => t('Create a menu link'), + '#type' => 'checkbox', + '#id' => 'edit-page-link', + ); + $form['displays']['page']['options']['link_properties'] = array( + '#type' => 'container', + '#dependency' => array( + 'edit-page-link' => array(1), + ), + '#pre_render' => array('ctools_dependent_pre_render'), + '#prefix' => '<div id="edit-page-link-properties-wrapper">', + '#suffix' => '</div>', + ); + if (module_exists('menu')) { + $menu_options = menu_get_menus(); + } + else { + // These are not yet translated. + $menu_options = menu_list_system_menus(); + foreach ($menu_options as $name => $title) { + $menu_options[$name] = t($title); + } + } + $form['displays']['page']['options']['link_properties']['menu_name'] = array( + '#title' => t('Menu'), + '#type' => 'select', + '#options' => $menu_options, + ); + $form['displays']['page']['options']['link_properties']['title'] = array( + '#title' => t('Link text'), + '#type' => 'textfield', + ); + // Only offer a feed if we have at least one available feed row style. + if ($feed_row_options) { + $form['displays']['page']['options']['feed'] = array( + '#title' => t('Include an RSS feed'), + '#type' => 'checkbox', + '#id' => 'edit-page-feed', + ); + $form['displays']['page']['options']['feed_properties'] = array( + '#type' => 'container', + '#dependency' => array( + 'edit-page-feed' => array(1), + ), + '#pre_render' => array('ctools_dependent_pre_render'), + '#prefix' => '<div id="edit-page-feed-properties-wrapper">', + '#suffix' => '</div>', + ); + $form['displays']['page']['options']['feed_properties']['path'] = array( + '#title' => t('Feed path'), + '#type' => 'textfield', + '#field_prefix' => $path_prefix, + ); + // This will almost never be visible. + $form['displays']['page']['options']['feed_properties']['row_plugin'] = array( + '#title' => t('Feed row style'), + '#type' => 'select', + '#options' => $feed_row_options, + '#default_value' => key($feed_row_options), + '#access' => (count($feed_row_options) > 1), + '#dependency' => array( + 'edit-page-feed' => array(1), + ), + '#pre_render' => array('ctools_dependent_pre_render'), + '#prefix' => '<div id="edit-page-feed-properties-row-plugin-wrapper">', + '#suffix' => '</div>', + ); + } + + $form['displays']['block'] = array( + '#type' => 'fieldset', + '#attributes' => array('class' => array('views-attachment', 'fieldset-no-legend'),), + '#tree' => TRUE, + ); + $form['displays']['block']['create'] = array( + '#title' => t('Create a block'), + '#type' => 'checkbox', + '#attributes' => array('class' => array('strong')), + '#id' => 'edit-block-create', + ); + + // All options for the block display are included in this container so they + // can be hidden en masse when the "Create a block" checkbox is unchecked. + $form['displays']['block']['options'] = array( + '#type' => 'container', + '#attributes' => array('class' => array('options-set'),), + '#dependency' => array( + 'edit-block-create' => array(1), + ), + '#pre_render' => array('ctools_dependent_pre_render'), + '#prefix' => '<div id="edit-block-wrapper">', + '#suffix' => '</div>', + '#parents' => array('block'), + ); + + $form['displays']['block']['options']['title'] = array( + '#title' => t('Block title'), + '#type' => 'textfield', + ); + $form['displays']['block']['options']['style'] = array( + '#type' => 'fieldset', + '#attributes' => array('class' => array('container-inline', 'fieldset-no-legend')), + ); + + // Create the dropdown for choosing the display format. + $form['displays']['block']['options']['style']['style_plugin'] = array( + '#title' => t('Display format'), + '#help_topic' => 'style', + '#type' => 'select', + '#options' => $style_options, + ); + $style_form = &$form['displays']['block']['options']['style']; + $style_form['style_plugin']['#default_value'] = views_ui_get_selected($form_state, array('block', 'style', 'style_plugin'), 'default', $style_form['style_plugin']); + // Changing this dropdown updates $form['displays']['block']['options'] via + // AJAX. + views_ui_add_ajax_trigger($style_form, 'style_plugin', array('displays', 'block', 'options')); + + $this->build_form_style($form, $form_state, 'block'); + $form['displays']['block']['options']['items_per_page'] = array( + '#title' => t('Items per page'), + '#type' => 'textfield', + '#default_value' => '5', + '#size' => 5, + '#element_validate' => array('_element_validate_integer_positive'), + ); + + return $form; + } + + /** + * Build the part of the form that builds the display format options. + */ + protected function build_form_style(&$form, &$form_state, $type) { + $style_form =& $form['displays'][$type]['options']['style']; + $style = $style_form['style_plugin']['#default_value']; + $style_plugin = views_get_plugin('style', $style); + if (isset($style_plugin) && $style_plugin->uses_row_plugin()) { + $options = $this->row_style_options($type); + $style_form['row_plugin'] = array( + '#type' => 'select', + '#title' => t('of'), + '#options' => $options, + '#access' => count($options) > 1, + ); + // For the block display, the default value should be "titles (linked)", + // if it's available (since that's the most common use case). + $block_with_linked_titles_available = ($type == 'block' && isset($options['titles_linked'])); + $default_value = $block_with_linked_titles_available ? 'titles_linked' : key($options); + $style_form['row_plugin']['#default_value'] = views_ui_get_selected($form_state, array($type, 'style', 'row_plugin'), $default_value, $style_form['row_plugin']); + // Changing this dropdown updates the individual row options via AJAX. + views_ui_add_ajax_trigger($style_form, 'row_plugin', array('displays', $type, 'options', 'style', 'row_options')); + + // This is the region that can be updated by AJAX. The base class doesn't + // add anything here, but child classes can. + $style_form['row_options'] = array( + '#theme_wrappers' => array('container'), + ); + } + elseif ($style_plugin->uses_fields()) { + $style_form['row_plugin'] = array('#markup' => '<span>' . t('of fields') . '</span>'); + } + } + + /** + * Add possible row style options. + * + * Per default use fields with base field. + */ + protected function row_style_options($type) { + $data = views_fetch_data($this->base_table); + // Get all available row plugins by default. + $options = views_fetch_plugin_names('row', 'normal', array($this->base_table)); + return $options; + } + + /** + * Build the part of the form that allows the user to select the view's filters. + * + * By default, this adds "of type" and "tagged with" filters (when they are + * available). + */ + protected function build_filters(&$form, &$form_state) { + // Find all the fields we are allowed to filter by. + $fields = views_fetch_fields($this->base_table, 'filter'); + + $entity_info = $this->entity_info; + // If the current base table support bundles and has more than one (like user). + if (isset($entity_info['bundle keys']) && isset($entity_info['bundles'])) { + // Get all bundles and their human readable names. + $options = array('all' => t('All')); + foreach ($entity_info['bundles'] as $type => $bundle) { + $options[$type] = $bundle['label']; + } + $form['displays']['show']['type'] = array( + '#type' => 'select', + '#title' => t('of type'), + '#options' => $options, + ); + $selected_bundle = views_ui_get_selected($form_state, array('show', 'type'), 'all', $form['displays']['show']['type']); + $form['displays']['show']['type']['#default_value'] = $selected_bundle; + // Changing this dropdown updates the entire content of $form['displays'] + // via AJAX, since each bundle might have entirely different fields + // attached to it, etc. + views_ui_add_ajax_trigger($form['displays']['show'], 'type', array('displays')); + } + + // Check if we are allowed to filter by taxonomy, and if so, add the + // "tagged with" filter to the view. + // + // We construct this filter using taxonomy_index.tid (which limits the + // filtering to a specific vocabulary) rather than taxonomy_term_data.name + // (which matches terms in any vocabulary). This is because it is a more + // commonly-used filter that works better with the autocomplete UI, and + // also to avoid confusion with other vocabularies on the site that may + // have terms with the same name but are not used for free tagging. + // + // The downside is that if there *is* more than one vocabulary on the site + // that is used for free tagging, the wizard will only be able to make the + // "tagged with" filter apply to one of them (see below for the method it + // uses to choose). + if (isset($fields['taxonomy_index.tid'])) { + // Check if this view will be displaying fieldable entities. + if (!empty($entity_info['fieldable'])) { + // Find all "tag-like" taxonomy fields associated with the view's + // entities. If a particular entity type (i.e., bundle) has been + // selected above, then we only search for taxonomy fields associated + // with that bundle. Otherwise, we use all bundles. + $bundles = array_keys($entity_info['bundles']); + // Double check that this is a real bundle before using it (since above + // we added a dummy option 'all' to the bundle list on the form). + if (isset($selected_bundle) && in_array($selected_bundle, $bundles)) { + $bundles = array($selected_bundle); + } + $tag_fields = array(); + foreach ($bundles as $bundle) { + foreach (field_info_instances($this->entity_type, $bundle) as $instance) { + // We define "tag-like" taxonomy fields as ones that use the + // "Autocomplete term widget (tagging)" widget. + if ($instance['widget']['type'] == 'taxonomy_autocomplete') { + $tag_fields[] = $instance['field_name']; + } + } + } + $tag_fields = array_unique($tag_fields); + if (!empty($tag_fields)) { + // If there is more than one "tag-like" taxonomy field available to + // the view, we can only make our filter apply to one of them (as + // described above). We choose 'field_tags' if it is available, since + // that is created by the Standard install profile in core and also + // commonly used by contrib modules; thus, it is most likely to be + // associated with the "main" free-tagging vocabulary on the site. + if (in_array('field_tags', $tag_fields)) { + $tag_field_name = 'field_tags'; + } + else { + $tag_field_name = reset($tag_fields); + } + // Add the autocomplete textfield to the wizard. + $form['displays']['show']['tagged_with'] = array( + '#type' => 'textfield', + '#title' => t('tagged with'), + '#autocomplete_path' => 'taxonomy/autocomplete/' . $tag_field_name, + '#size' => 30, + '#maxlength' => 1024, + '#field_name' => $tag_field_name, + '#element_validate' => array('views_ui_taxonomy_autocomplete_validate'), + ); + } + } + } + } + + /** + * Build the part of the form that allows the user to select the view's sort order. + * + * By default, this adds a "sorted by [date]" filter (when it is available). + */ + protected function build_sorts(&$form, &$form_state) { + // Check if we are allowed to sort by creation date. + $sorts = array(); + if (!empty($this->plugin['created_column'])) { + $sorts = array( + $this->plugin['created_column'] . ':DESC' => t('Newest first'), + $this->plugin['created_column'] . ':ASC' => t('Oldest first'), + ); + if (isset($this->plugin['available_sorts'])) { + $sorts += $this->plugin['available_sorts']; + } + } + if (!empty($sorts)) { + $form['displays']['show']['sort'] = array( + '#type' => 'select', + '#title' => t('sorted by'), + '#options' => $sorts, + '#default_value' => isset($this->plugin['created_column']) ? $this->plugin['created_column'] . ':DESC' : NULL, + ); + } + } + + protected function instantiate_view($form, &$form_state) { + // Build the basic view properties. + $view = views_new_view(); + $view->name = $form_state['values']['name']; + $view->human_name = $form_state['values']['human_name']; + $view->description = $form_state['values']['description']; + $view->tag = 'default'; + $view->core = VERSION; + $view->base_table = $this->base_table; + + // Build all display options for this view. + $display_options = $this->build_display_options($form, $form_state); + + // Allow the fully built options to be altered. This happens before adding + // the options to the view, so that once they are eventually added we will + // be able to get all the overrides correct. + $this->alter_display_options($display_options, $form, $form_state); + + $this->add_displays($view, $display_options, $form, $form_state); + + return $view; + } + + /** + * Build an array of display options for the view. + * + * @return + * An array whose keys are the names of each display and whose values are + * arrays of options for that display. + */ + protected function build_display_options($form, $form_state) { + // Display: Master + $display_options['default'] = $this->default_display_options($form, $form_state); + $display_options['default'] += array( + 'filters' => array(), + 'sorts' => array(), + ); + $display_options['default']['filters'] += $this->default_display_filters($form, $form_state); + $display_options['default']['sorts'] += $this->default_display_sorts($form, $form_state); + + // Display: Page + if (!empty($form_state['values']['page']['create'])) { + $display_options['page'] = $this->page_display_options($form, $form_state); + + // Display: Feed (attached to the page) + if (!empty($form_state['values']['page']['feed'])) { + $display_options['feed'] = $this->page_feed_display_options($form, $form_state); + } + } + + // Display: Block + if (!empty($form_state['values']['block']['create'])) { + $display_options['block'] = $this->block_display_options($form, $form_state); + } + + return $display_options; + } + + /** + * Alter the full array of display options before they are added to the view. + */ + protected function alter_display_options(&$display_options, $form, $form_state) { + // If any of the displays use jump menus, we want to add fields to the view + // that store the path that will be used in the jump menu. The fields to + // use for this are defined by the plugin. + if (isset($this->plugin['path_field'])) { + $path_field = $this->plugin['path_field']; + $path_fields_added = FALSE; + foreach ($display_options as $display_type => $options) { + if (!empty($options['style_plugin']) && $options['style_plugin'] == 'jump_menu') { + // Regardless of how many displays have jump menus, we only need to + // add a single set of path fields to the view. + if (!$path_fields_added) { + // The plugin might provide supplemental fields that it needs to + // generate the path (for example, node revisions need the node ID + // as well as the revision ID). We need to add these first so they + // are available as replacement patterns in the main path field. + $path_fields = !empty($this->plugin['path_fields_supplemental']) ? $this->plugin['path_fields_supplemental'] : array(); + $path_fields[] = &$path_field; + + // Generate a unique ID for each field so we don't overwrite + // existing ones. + foreach ($path_fields as &$field) { + $field['id'] = view::generate_item_id($field['id'], $display_options['default']['fields']); + $display_options['default']['fields'][$field['id']] = $field; + } + + $path_fields_added = TRUE; + } + + // Configure the style plugin to use the path field to generate the + // jump menu path. + $display_options[$display_type]['style_options']['path'] = $path_field['id']; + } + } + } + } + + /** + * Add the array of display options to the view, with appropriate overrides. + */ + protected function add_displays($view, $display_options, $form, $form_state) { + // Display: Master + $default_display = $view->new_display('default', 'Master', 'default'); + foreach ($display_options['default'] as $option => $value) { + $default_display->set_option($option, $value); + } + + // Display: Page + if (isset($display_options['page'])) { + $display = $view->new_display('page', 'Page', 'page'); + // The page display is usually the main one (from the user's point of + // view). Its options should therefore become the overall view defaults, + // so that new displays which are added later automatically inherit them. + $this->set_default_options($display_options['page'], $display, $default_display); + + // Display: Feed (attached to the page) + if (isset($display_options['feed'])) { + $display = $view->new_display('feed', 'Feed', 'feed'); + $this->set_override_options($display_options['feed'], $display, $default_display); + } + } + + // Display: Block + if (isset($display_options['block'])) { + $display = $view->new_display('block', 'Block', 'block'); + // When there is no page, the block display options should become the + // overall view defaults. + if (!isset($display_options['page'])) { + $this->set_default_options($display_options['block'], $display, $default_display); + } + else { + $this->set_override_options($display_options['block'], $display, $default_display); + } + } + } + + /** + * Most subclasses will need to override this method to provide some fields + * or a different row plugin. + */ + protected function default_display_options($form, $form_state) { + $display_options = array(); + $display_options['access']['type'] = 'none'; + $display_options['cache']['type'] = 'none'; + $display_options['query']['type'] = 'views_query'; + $display_options['exposed_form']['type'] = 'basic'; + $display_options['pager']['type'] = 'full'; + $display_options['style_plugin'] = 'default'; + $display_options['row_plugin'] = 'fields'; + + // Add a least one field so the view validates and the user has already a preview. + // Therefore the basefield could provide 'defaults][field]' in it's base settings. + // If there is nothing like this choose the first field with a field handler. + $data = views_fetch_data($this->base_table); + if (isset($data['table']['base']['defaults']['field'])) { + $field = $data['table']['base']['defaults']['field']; + } + else { + foreach ($data as $field => $field_data) { + if (isset($field_data['field']['handler'])) { + break; + } + } + } + $display_options['fields'][$field] = array( + 'table' => $this->base_table, + 'field' => $field, + 'id' => $field, + ); + + return $display_options; + } + + protected function default_display_filters($form, $form_state) { + $filters = array(); + + // Add any filters provided by the plugin. + if (isset($this->plugin['filters'])) { + foreach ($this->plugin['filters'] as $name => $info) { + $filters[$name] = $info; + } + } + + // Add any filters specified by the user when filling out the wizard. + $filters = array_merge($filters, $this->default_display_filters_user($form, $form_state)); + + return $filters; + } + + protected function default_display_filters_user($form, $form_state) { + $filters = array(); + + if (!empty($form_state['values']['show']['type']) && $form_state['values']['show']['type'] != 'all') { + $bundle_key = $this->entity_info['bundle keys']['bundle']; + // Figure out the table where $bundle_key lives. It may not be the same as + // the base table for the view; the taxonomy vocabulary machine_name, for + // example, is stored in taxonomy_vocabulary, not taxonomy_term_data. + $fields = views_fetch_fields($this->base_table, 'filter'); + if (isset($fields[$this->base_table . '.' . $bundle_key])) { + $table = $this->base_table; + } + else { + foreach ($fields as $field_name => $value) { + if ($pos = strpos($field_name, '.' . $bundle_key)) { + $table = substr($field_name, 0, $pos); + break; + } + } + } + $filters[$bundle_key] = array( + 'id' => $bundle_key, + 'table' => $table, + 'field' => $bundle_key, + 'value' => drupal_map_assoc(array($form_state['values']['show']['type'])), + ); + } + if (!empty($form_state['values']['show']['tagged_with']['tids'])) { + $filters['tid'] = array( + 'id' => 'tid', + 'table' => 'taxonomy_index', + 'field' => 'tid', + 'value' => $form_state['values']['show']['tagged_with']['tids'], + 'vocabulary' => $form_state['values']['show']['tagged_with']['vocabulary'], + ); + // If the user entered more than one valid term in the autocomplete + // field, they probably intended both of them to be applied. + if (count($form_state['values']['show']['tagged_with']['tids']) > 1) { + $filters['tid']['operator'] = 'and'; + // Sort the terms so the filter will be displayed as it normally would + // on the edit screen. + sort($filters['tid']['value']); + } + } + + return $filters; + } + + protected function default_display_sorts($form, $form_state) { + $sorts = array(); + + // Add any sorts provided by the plugin. + if (isset($this->plugin['sorts'])) { + foreach ($this->plugin['sorts'] as $name => $info) { + $sorts[$name] = $info; + } + } + + // Add any sorts specified by the user when filling out the wizard. + $sorts = array_merge($sorts, $this->default_display_sorts_user($form, $form_state)); + + return $sorts; + } + + protected function default_display_sorts_user($form, $form_state) { + $sorts = array(); + + if (!empty($form_state['values']['show']['sort'])) { + list($column, $sort) = explode(':', $form_state['values']['show']['sort']); + // Column either be a column-name or the table-columnn-ame. + $column = explode('-', $column); + if (count($column) > 1) { + $table = $column[0]; + $column = $column[1]; + } + else { + $table = $this->base_table; + $column = $column[0]; + } + + $sorts[$column] = array( + 'id' => $column, + 'table' => $table, + 'field' => $column, + 'order' => $sort, + ); + } + + return $sorts; + } + + protected function page_display_options($form, $form_state) { + $display_options = array(); + $page = $form_state['values']['page']; + $display_options['title'] = $page['title']; + $display_options['path'] = $page['path']; + $display_options['style_plugin'] = $page['style']['style_plugin']; + // Not every style plugin supports row style plugins. + $display_options['row_plugin'] = isset($page['style']['row_plugin']) ? $page['style']['row_plugin'] : 'fields'; + $display_options['pager']['type'] = 'full'; + $display_options['pager']['options']['items_per_page'] = $page['items_per_page']; + if (!empty($page['link'])) { + $display_options['menu']['type'] = 'normal'; + $display_options['menu']['title'] = $page['link_properties']['title']; + $display_options['menu']['name'] = $page['link_properties']['menu_name']; + } + return $display_options; + } + + protected function block_display_options($form, $form_state) { + $display_options = array(); + $block = $form_state['values']['block']; + $display_options['title'] = $block['title']; + $display_options['style_plugin'] = $block['style']['style_plugin']; + $display_options['row_plugin'] = isset($block['style']['row_plugin']) ? $block['style']['row_plugin'] : 'fields'; + $display_options['pager']['type'] = 'full'; + $display_options['pager']['options']['items_per_page'] = $block['items_per_page']; + return $display_options; + } + + protected function page_feed_display_options($form, $form_state) { + $display_options = array(); + $display_options['pager']['type'] = 'some'; + $display_options['style_plugin'] = 'rss'; + $display_options['row_plugin'] = $form_state['values']['page']['feed_properties']['row_plugin']; + $display_options['path'] = $form_state['values']['page']['feed_properties']['path']; + $display_options['title'] = $form_state['values']['page']['title']; + $display_options['displays'] = array( + 'default' => 'default', + 'page' => 'page', + ); + return $display_options; + } + + /** + * Sets options for a display and makes them the default options if possible. + * + * This function can be used to set options for a display when it is desired + * that the options also become the defaults for the view whenever possible. + * This should be done for the "primary" display created in the view wizard, + * so that new displays which the user adds later will be similar to this + * one. + * + * @param $options + * An array whose keys are the name of each option and whose values are the + * desired values to set. + * @param $display + * The display which the options will be applied to. The default display + * will actually be assigned the options (and this display will inherit + * them) when possible. + * @param $default_display + * The default display, which will store the options when possible. + */ + protected function set_default_options($options, $display, $default_display) { + foreach ($options as $option => $value) { + // If the default display supports this option, set the value there. + // Otherwise, set it on the provided display. + $default_value = $default_display->get_option($option); + if (isset($default_value)) { + $default_display->set_option($option, $value); + } + else { + $display->set_option($option, $value); + } + } + } + + /** + * Sets options for a display, inheriting from the defaults when possible. + * + * This function can be used to set options for a display when it is desired + * that the options inherit from the default display whenever possible. This + * avoids setting too many options as overrides, which will be harder for the + * user to modify later. For example, if $this->set_default_options() was + * previously called on a page display and then this function is called on a + * block display, and if the user entered the same title for both displays in + * the views wizard, then the view will wind up with the title stored as the + * default (with the page and block both inheriting from it). + * + * @param $options + * An array whose keys are the name of each option and whose values are the + * desired values. + * @param $display + * The display which the options will apply to. It will get the options by + * inheritance from the default display when possible. + * @param $default_display + * The default display, from which the options will be inherited when + * possible. + */ + protected function set_override_options($options, $display, $default_display) { + foreach ($options as $option => $value) { + // Only override the default value if it is different from the value that + // was provided. + $default_value = $default_display->get_option($option); + if (!isset($default_value)) { + $display->set_option($option, $value); + } + elseif ($default_value !== $value) { + $display->override_option($option, $value); + } + } + } + + protected function retrieve_validated_view($form, $form_state, $unset = TRUE) { + $key = hash('sha256', serialize($form_state['values'])); + $view = (isset($this->validated_views[$key]) ? $this->validated_views[$key] : NULL); + if ($unset) { + unset($this->validated_views[$key]); + } + return $view; + } + + protected function set_validated_view($form, $form_state, $view) { + $key = hash('sha256', serialize($form_state['values'])); + $this->validated_views[$key] = $view; + } + + /** + * Instantiates a view and validates values. + */ + function validate($form, &$form_state) { + $view = $this->instantiate_view($form, $form_state); + $errors = $view->validate(); + if (!is_array($errors) || empty($errors)) { + $this->set_validated_view($form, $form_state, $view); + return array(); + } + return $errors; + } + + /** + * Create a View from values that have been already submitted to validate(). + * + * @throws ViewsWizardException if the values have not been validated. + */ + function create_view($form, &$form_state) { + $view = $this->retrieve_validated_view($form, $form_state); + if (empty($view)) { + throw new ViewsWizardException(t('Attempted to create_view with values that have not been validated')); + } + return $view; + } + +} diff --git a/sites/all/modules/views/plugins/views_wizard/views_ui_comment_views_wizard.class.php b/sites/all/modules/views/plugins/views_wizard/views_ui_comment_views_wizard.class.php new file mode 100644 index 0000000000000000000000000000000000000000..be8e74339d2ba412dd4e644661038412beab9e72 --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/views_ui_comment_views_wizard.class.php @@ -0,0 +1,99 @@ +<?php + +class ViewsUiCommentViewsWizard extends ViewsUiBaseViewsWizard { + + protected function row_style_options($type) { + $options = array(); + $options['comment'] = t('comments'); + $options['fields'] = t('fields'); + return $options; + } + + protected function build_form_style(&$form, &$form_state, $type) { + parent::build_form_style($form, $form_state, $type); + $style_form =& $form['displays'][$type]['options']['style']; + // Some style plugins don't support row plugins so stop here if that's the + // case. + if (!isset($style_form['row_plugin']['#default_value'])) { + return; + } + $row_plugin = $style_form['row_plugin']['#default_value']; + switch ($row_plugin) { + case 'comment': + $style_form['row_options']['links'] = array( + '#type' => 'select', + '#title_display' => 'invisible', + '#title' => t('Should links be displayed below each comment'), + '#options' => array( + 1 => t('with links (allow users to reply to the comment, etc.)'), + 0 => t('without links'), + ), + '#default_value' => 1, + ); + break; + } + } + + protected function page_display_options($form, $form_state) { + $display_options = parent::page_display_options($form, $form_state); + $row_plugin = isset($form_state['values']['page']['style']['row_plugin']) ? $form_state['values']['page']['style']['row_plugin'] : NULL; + $row_options = isset($form_state['values']['page']['style']['row_options']) ? $form_state['values']['page']['style']['row_options'] : array(); + $this->display_options_row($display_options, $row_plugin, $row_options); + return $display_options; + } + + protected function block_display_options($form, $form_state) { + $display_options = parent::block_display_options($form, $form_state); + $row_plugin = isset($form_state['values']['block']['style']['row_plugin']) ? $form_state['values']['block']['style']['row_plugin'] : NULL; + $row_options = isset($form_state['values']['block']['style']['row_options']) ? $form_state['values']['block']['style']['row_options'] : array(); + $this->display_options_row($display_options, $row_plugin, $row_options); + return $display_options; + } + + /** + * Set the row style and row style plugins to the display_options. + */ + protected function display_options_row(&$display_options, $row_plugin, $row_options) { + switch ($row_plugin) { + case 'comment': + $display_options['row_plugin'] = 'comment'; + $display_options['row_options']['links'] = !empty($row_options['links']); + break; + } + } + + protected function default_display_options($form, $form_state) { + $display_options = parent::default_display_options($form, $form_state); + + // Add permission-based access control. + $display_options['access']['type'] = 'perm'; + + // Add a relationship to nodes. + $display_options['relationships']['nid']['id'] = 'nid'; + $display_options['relationships']['nid']['table'] = 'comment'; + $display_options['relationships']['nid']['field'] = 'nid'; + $display_options['relationships']['nid']['required'] = 1; + + // Remove the default fields, since we are customizing them here. + unset($display_options['fields']); + + /* Field: Comment: Title */ + $display_options['fields']['subject']['id'] = 'subject'; + $display_options['fields']['subject']['table'] = 'comment'; + $display_options['fields']['subject']['field'] = 'subject'; + $display_options['fields']['subject']['label'] = ''; + $display_options['fields']['subject']['alter']['alter_text'] = 0; + $display_options['fields']['subject']['alter']['make_link'] = 0; + $display_options['fields']['subject']['alter']['absolute'] = 0; + $display_options['fields']['subject']['alter']['trim'] = 0; + $display_options['fields']['subject']['alter']['word_boundary'] = 0; + $display_options['fields']['subject']['alter']['ellipsis'] = 0; + $display_options['fields']['subject']['alter']['strip_tags'] = 0; + $display_options['fields']['subject']['alter']['html'] = 0; + $display_options['fields']['subject']['hide_empty'] = 0; + $display_options['fields']['subject']['empty_zero'] = 0; + $display_options['fields']['subject']['link_to_comment'] = 1; + + return $display_options; + } +} diff --git a/sites/all/modules/views/plugins/views_wizard/views_ui_file_managed_views_wizard.class.php b/sites/all/modules/views/plugins/views_wizard/views_ui_file_managed_views_wizard.class.php new file mode 100644 index 0000000000000000000000000000000000000000..9894d779f4762e8f8e4d1386096bf8e0453dc52d --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/views_ui_file_managed_views_wizard.class.php @@ -0,0 +1,32 @@ +<?php + +class ViewsUiFileManagedViewsWizard extends ViewsUiBaseViewsWizard { + protected function default_display_options($form, $form_state) { + $display_options = parent::default_display_options($form, $form_state); + + // Add permission-based access control. + $display_options['access']['type'] = 'perm'; + + // Remove the default fields, since we are customizing them here. + unset($display_options['fields']); + + /* Field: File: Name */ + $display_options['fields']['filename']['id'] = 'filename'; + $display_options['fields']['filename']['table'] = 'file_managed'; + $display_options['fields']['filename']['field'] = 'filename'; + $display_options['fields']['filename']['label'] = ''; + $display_options['fields']['filename']['alter']['alter_text'] = 0; + $display_options['fields']['filename']['alter']['make_link'] = 0; + $display_options['fields']['filename']['alter']['absolute'] = 0; + $display_options['fields']['filename']['alter']['trim'] = 0; + $display_options['fields']['filename']['alter']['word_boundary'] = 0; + $display_options['fields']['filename']['alter']['ellipsis'] = 0; + $display_options['fields']['filename']['alter']['strip_tags'] = 0; + $display_options['fields']['filename']['alter']['html'] = 0; + $display_options['fields']['filename']['hide_empty'] = 0; + $display_options['fields']['filename']['empty_zero'] = 0; + $display_options['fields']['filename']['link_to_file'] = 1; + + return $display_options; + } +} diff --git a/sites/all/modules/views/plugins/views_wizard/views_ui_node_revision_views_wizard.class.php b/sites/all/modules/views/plugins/views_wizard/views_ui_node_revision_views_wizard.class.php new file mode 100644 index 0000000000000000000000000000000000000000..f465e6b451806638de6acbef59d599f3ff17fa57 --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/views_ui_node_revision_views_wizard.class.php @@ -0,0 +1,50 @@ +<?php + +class ViewsUiNodeRevisionViewsWizard extends ViewsUiNodeViewsWizard { + + protected function default_display_options($form, $form_state) { + $display_options = parent::default_display_options($form, $form_state); + + // Add permission-based access control. + $display_options['access']['type'] = 'perm'; + $display_options['access']['perm'] = 'view revisions'; + + // Remove the default fields, since we are customizing them here. + unset($display_options['fields']); + + /* Field: Content revision: Created date */ + $display_options['fields']['timestamp']['id'] = 'timestamp'; + $display_options['fields']['timestamp']['table'] = 'node_revision'; + $display_options['fields']['timestamp']['field'] = 'timestamp'; + $display_options['fields']['timestamp']['alter']['alter_text'] = 0; + $display_options['fields']['timestamp']['alter']['make_link'] = 0; + $display_options['fields']['timestamp']['alter']['absolute'] = 0; + $display_options['fields']['timestamp']['alter']['trim'] = 0; + $display_options['fields']['timestamp']['alter']['word_boundary'] = 0; + $display_options['fields']['timestamp']['alter']['ellipsis'] = 0; + $display_options['fields']['timestamp']['alter']['strip_tags'] = 0; + $display_options['fields']['timestamp']['alter']['html'] = 0; + $display_options['fields']['timestamp']['hide_empty'] = 0; + $display_options['fields']['timestamp']['empty_zero'] = 0; + + /* Field: Content revision: Title */ + $display_options['fields']['title']['id'] = 'title'; + $display_options['fields']['title']['table'] = 'node_revision'; + $display_options['fields']['title']['field'] = 'title'; + $display_options['fields']['title']['label'] = ''; + $display_options['fields']['title']['alter']['alter_text'] = 0; + $display_options['fields']['title']['alter']['make_link'] = 0; + $display_options['fields']['title']['alter']['absolute'] = 0; + $display_options['fields']['title']['alter']['trim'] = 0; + $display_options['fields']['title']['alter']['word_boundary'] = 0; + $display_options['fields']['title']['alter']['ellipsis'] = 0; + $display_options['fields']['title']['alter']['strip_tags'] = 0; + $display_options['fields']['title']['alter']['html'] = 0; + $display_options['fields']['title']['hide_empty'] = 0; + $display_options['fields']['title']['empty_zero'] = 0; + $display_options['fields']['title']['link_to_node'] = 0; + $display_options['fields']['title']['link_to_node_revision'] = 1; + + return $display_options; + } +} diff --git a/sites/all/modules/views/plugins/views_wizard/views_ui_node_views_wizard.class.php b/sites/all/modules/views/plugins/views_wizard/views_ui_node_views_wizard.class.php new file mode 100644 index 0000000000000000000000000000000000000000..14f97f6050a416a530061b0950abe458954da8b2 --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/views_ui_node_views_wizard.class.php @@ -0,0 +1,128 @@ +<?php + +class ViewsUiNodeViewsWizard extends ViewsUiBaseViewsWizard { + + protected function row_style_options($type) { + $options = array(); + $options['teasers'] = t('teasers'); + $options['full_posts'] = t('full posts'); + $options['titles'] = t('titles'); + $options['titles_linked'] = t('titles (linked)'); + $options['fields'] = t('fields'); + return $options; + } + + protected function build_form_style(&$form, &$form_state, $type) { + parent::build_form_style($form, $form_state, $type); + $style_form =& $form['displays'][$type]['options']['style']; + // Some style plugins don't support row plugins so stop here if that's the + // case. + if (!isset($style_form['row_plugin']['#default_value'])) { + return; + } + $row_plugin = $style_form['row_plugin']['#default_value']; + switch ($row_plugin) { + case 'full_posts': + case 'teasers': + $style_form['row_options']['links'] = array( + '#type' => 'select', + '#title_display' => 'invisible', + '#title' => t('Should links be displayed below each node'), + '#options' => array( + 1 => t('with links (allow users to add comments, etc.)'), + 0 => t('without links'), + ), + '#default_value' => 1, + ); + $style_form['row_options']['comments'] = array( + '#type' => 'select', + '#title_display' => 'invisible', + '#title' => t('Should comments be displayed below each node'), + '#options' => array( + 1 => t('with comments'), + 0 => t('without comments'), + ), + '#default_value' => 0, + ); + break; + } + } + + /** + * @override + */ + protected function default_display_options($form, $form_state) { + $display_options = parent::default_display_options($form, $form_state); + + // Add permission-based access control. + $display_options['access']['type'] = 'perm'; + + // Remove the default fields, since we are customizing them here. + unset($display_options['fields']); + + // Add the title field, so that the display has content if the user switches + // to a row style that uses fields. + /* Field: Content: Title */ + $display_options['fields']['title']['id'] = 'title'; + $display_options['fields']['title']['table'] = 'node'; + $display_options['fields']['title']['field'] = 'title'; + $display_options['fields']['title']['label'] = ''; + $display_options['fields']['title']['alter']['alter_text'] = 0; + $display_options['fields']['title']['alter']['make_link'] = 0; + $display_options['fields']['title']['alter']['absolute'] = 0; + $display_options['fields']['title']['alter']['trim'] = 0; + $display_options['fields']['title']['alter']['word_boundary'] = 0; + $display_options['fields']['title']['alter']['ellipsis'] = 0; + $display_options['fields']['title']['alter']['strip_tags'] = 0; + $display_options['fields']['title']['alter']['html'] = 0; + $display_options['fields']['title']['hide_empty'] = 0; + $display_options['fields']['title']['empty_zero'] = 0; + $display_options['fields']['title']['link_to_node'] = 1; + + return $display_options; + } + + protected function page_display_options($form, $form_state) { + $display_options = parent::page_display_options($form, $form_state); + $row_plugin = isset($form_state['values']['page']['style']['row_plugin']) ? $form_state['values']['page']['style']['row_plugin'] : NULL; + $row_options = isset($form_state['values']['page']['style']['row_options']) ? $form_state['values']['page']['style']['row_options'] : array(); + $this->display_options_row($display_options, $row_plugin, $row_options); + return $display_options; + } + + protected function block_display_options($form, $form_state) { + $display_options = parent::block_display_options($form, $form_state); + $row_plugin = isset($form_state['values']['block']['style']['row_plugin']) ? $form_state['values']['block']['style']['row_plugin'] : NULL; + $row_options = isset($form_state['values']['block']['style']['row_options']) ? $form_state['values']['block']['style']['row_options'] : array(); + $this->display_options_row($display_options, $row_plugin, $row_options); + return $display_options; + } + + /** + * Set the row style and row style plugins to the display_options. + */ + protected function display_options_row(&$display_options, $row_plugin, $row_options) { + switch ($row_plugin) { + case 'full_posts': + $display_options['row_plugin'] = 'node'; + $display_options['row_options']['build_mode'] = 'full'; + $display_options['row_options']['links'] = !empty($row_options['links']); + $display_options['row_options']['comments'] = !empty($row_options['comments']); + break; + case 'teasers': + $display_options['row_plugin'] = 'node'; + $display_options['row_options']['build_mode'] = 'teaser'; + $display_options['row_options']['links'] = !empty($row_options['links']); + $display_options['row_options']['comments'] = !empty($row_options['comments']); + break; + case 'titles_linked': + $display_options['row_plugin'] = 'fields'; + $display_options['field']['title']['link_to_node'] = 1; + break; + case 'titles': + $display_options['row_plugin'] = 'fields'; + $display_options['field']['title']['link_to_node'] = 0; + break; + } + } +} diff --git a/sites/all/modules/views/plugins/views_wizard/views_ui_taxonomy_term_views_wizard.class.php b/sites/all/modules/views/plugins/views_wizard/views_ui_taxonomy_term_views_wizard.class.php new file mode 100644 index 0000000000000000000000000000000000000000..6310e8cc122bf9a10a5b0953ae7cee814ed7eff3 --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/views_ui_taxonomy_term_views_wizard.class.php @@ -0,0 +1,33 @@ +<?php + +class ViewsUiTaxonomyTermViewsWizard extends ViewsUiBaseViewsWizard { + + protected function default_display_options($form, $form_state) { + $display_options = parent::default_display_options($form, $form_state); + + // Add permission-based access control. + $display_options['access']['type'] = 'perm'; + + // Remove the default fields, since we are customizing them here. + unset($display_options['fields']); + + /* Field: Taxonomy: Term */ + $display_options['fields']['name']['id'] = 'name'; + $display_options['fields']['name']['table'] = 'taxonomy_term_data'; + $display_options['fields']['name']['field'] = 'name'; + $display_options['fields']['name']['label'] = ''; + $display_options['fields']['name']['alter']['alter_text'] = 0; + $display_options['fields']['name']['alter']['make_link'] = 0; + $display_options['fields']['name']['alter']['absolute'] = 0; + $display_options['fields']['name']['alter']['trim'] = 0; + $display_options['fields']['name']['alter']['word_boundary'] = 0; + $display_options['fields']['name']['alter']['ellipsis'] = 0; + $display_options['fields']['name']['alter']['strip_tags'] = 0; + $display_options['fields']['name']['alter']['html'] = 0; + $display_options['fields']['name']['hide_empty'] = 0; + $display_options['fields']['name']['empty_zero'] = 0; + $display_options['fields']['name']['link_to_taxonomy'] = 1; + + return $display_options; + } +} diff --git a/sites/all/modules/views/plugins/views_wizard/views_ui_users_views_wizard.class.php b/sites/all/modules/views/plugins/views_wizard/views_ui_users_views_wizard.class.php new file mode 100644 index 0000000000000000000000000000000000000000..1134a242528c2d259f23fe673b13b0018e840aec --- /dev/null +++ b/sites/all/modules/views/plugins/views_wizard/views_ui_users_views_wizard.class.php @@ -0,0 +1,34 @@ +<?php + +class ViewsUiUsersViewsWizard extends ViewsUiBaseViewsWizard { + protected function default_display_options($form, $form_state) { + $display_options = parent::default_display_options($form, $form_state); + + // Add permission-based access control. + $display_options['access']['type'] = 'perm'; + $display_options['access']['perm'] = 'access user profiles'; + + // Remove the default fields, since we are customizing them here. + unset($display_options['fields']); + + /* Field: User: Name */ + $display_options['fields']['name']['id'] = 'name'; + $display_options['fields']['name']['table'] = 'users'; + $display_options['fields']['name']['field'] = 'name'; + $display_options['fields']['name']['label'] = ''; + $display_options['fields']['name']['alter']['alter_text'] = 0; + $display_options['fields']['name']['alter']['make_link'] = 0; + $display_options['fields']['name']['alter']['absolute'] = 0; + $display_options['fields']['name']['alter']['trim'] = 0; + $display_options['fields']['name']['alter']['word_boundary'] = 0; + $display_options['fields']['name']['alter']['ellipsis'] = 0; + $display_options['fields']['name']['alter']['strip_tags'] = 0; + $display_options['fields']['name']['alter']['html'] = 0; + $display_options['fields']['name']['hide_empty'] = 0; + $display_options['fields']['name']['empty_zero'] = 0; + $display_options['fields']['name']['link_to_user'] = 1; + $display_options['fields']['name']['overwrite_anonymous'] = 0; + + return $display_options; + } +} 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 862144cd3373ec78969894516008417063a73fb4..983b37ddb6a81b6183da5294d041b5a2ce5d6fc1 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,4 @@ <?php -// $Id: views_handler_area_text.test,v 1.1.2.1 2010/11/07 11:32:25 dereine Exp $ class ViewsHandlerAreaTextTest extends ViewsSqlTest { public static function getInfo() { diff --git a/sites/all/modules/views/tests/handlers/views_handler_argument_null.test b/sites/all/modules/views/tests/handlers/views_handler_argument_null.test index 73f87ae3444b553c0ddaa5a7fac42a201785532a..6a978bd4086aeb29e226caf4356cfb577d0f153e 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_argument_null.test +++ b/sites/all/modules/views/tests/handlers/views_handler_argument_null.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_argument_null.test,v 1.1.2.1 2010/11/07 11:32:25 dereine Exp $ class ViewsHandlerArgumentNullTest extends ViewsSqlTest { public static function getInfo() { 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 516edb0b40cb4ee6e9c6eb971252d072f7064e32..1b910b87f2c58bd44f73d48e11b5e0178f7ae2b8 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_boolean.test,v 1.1.2.1 2010/11/07 11:32:25 dereine Exp $ class ViewsHandlerFieldBooleanTest extends ViewsSqlTest { public static function getInfo() { diff --git a/sites/all/modules/views/tests/handlers/views_handler_field_counter.test b/sites/all/modules/views/tests/handlers/views_handler_field_counter.test index 0cffb96c234d7341ecf998fca5115ae3a5ebfe5e..4db982be4930bd38cf9f1b25822b8980ade876bc 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_field_counter.test +++ b/sites/all/modules/views/tests/handlers/views_handler_field_counter.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_counter.test,v 1.1.2.2 2010/12/27 08:43:31 dereine Exp $ class viewsHandlerFilterCounterTest extends ViewsSqlTest { public static function getInfo() { diff --git a/sites/all/modules/views/tests/handlers/views_handler_field_custom.test b/sites/all/modules/views/tests/handlers/views_handler_field_custom.test index 017efa56dd44e8d213c60c763032351be26b5174..6a5ab307e968cb45436abb859e6e54fcbdda06a7 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_field_custom.test +++ b/sites/all/modules/views/tests/handlers/views_handler_field_custom.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_custom.test,v 1.1.2.1 2010/11/07 11:32:25 dereine Exp $ class ViewsHandlerFieldCustomTest extends ViewsSqlTest { public static function getInfo() { diff --git a/sites/all/modules/views/tests/handlers/views_handler_field_date.test b/sites/all/modules/views/tests/handlers/views_handler_field_date.test index 1f2dbe2780a67eb796de2500004d61991306042d..0b9bde53aacd49bf1e05b34a2a35c12e9d56fef1 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_field_date.test +++ b/sites/all/modules/views/tests/handlers/views_handler_field_date.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_date.test,v 1.1.2.1 2010/11/07 11:32:25 dereine Exp $ class ViewsHandlerFieldDateTest extends ViewsSqlTest { public static function getInfo() { diff --git a/sites/all/modules/views/tests/handlers/views_handler_field_file_size.test b/sites/all/modules/views/tests/handlers/views_handler_field_file_size.test index 7a3b030f76e33a6b5466f006c0dba99807091961..ae2569e13c652de9b7d4dab676654a1f33864bbd 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_field_file_size.test +++ b/sites/all/modules/views/tests/handlers/views_handler_field_file_size.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_file_size.test,v 1.1.2.1 2010/11/07 11:32:25 dereine Exp $ /** * @see CommonXssUnitTest diff --git a/sites/all/modules/views/tests/handlers/views_handler_field_math.test b/sites/all/modules/views/tests/handlers/views_handler_field_math.test index 839ab1289586ff2b63c8fa7bc6baa63e01143217..26e756524b1a285a3ee82e6940eb5ebb2267bfdc 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_field_math.test +++ b/sites/all/modules/views/tests/handlers/views_handler_field_math.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_math.test,v 1.1.2.1 2010/12/24 14:05:39 dereine Exp $ class ViewsHandlerFieldMath extends ViewsSqlTest { public static function getInfo() { diff --git a/sites/all/modules/views/tests/handlers/views_handler_field_url.test b/sites/all/modules/views/tests/handlers/views_handler_field_url.test index de2cce9ded27385d745ae19fbf8a30413e6f965e..35bffa7d95bf0d71c378cf62aba383436fcc6bd6 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_field_url.test +++ b/sites/all/modules/views/tests/handlers/views_handler_field_url.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_url.test,v 1.1.2.1 2010/11/07 11:32:25 dereine Exp $ class ViewsHandlerFieldUrlTest extends ViewsSqlTest { public static function getInfo() { diff --git a/sites/all/modules/views/tests/handlers/views_handler_field_xss.test b/sites/all/modules/views/tests/handlers/views_handler_field_xss.test index 0855f031cc8144464a50035f1c691a00e1f694d3..e4a6488bcf53a18dd6b0c8a7e8c91090234c2f81 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_field_xss.test +++ b/sites/all/modules/views/tests/handlers/views_handler_field_xss.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_field_xss.test,v 1.1.2.1 2010/11/07 11:32:25 dereine Exp $ /** * @see CommonXssUnitTest diff --git a/sites/all/modules/views/tests/handlers/views_handler_filter_date.test b/sites/all/modules/views/tests/handlers/views_handler_filter_date.test index 7eaee58fa193a0f517a281811aa0cb34dd2eab33..cbc0da51d1ae24d51d896f456dcc8a25059c4025 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_filter_date.test +++ b/sites/all/modules/views/tests/handlers/views_handler_filter_date.test @@ -1,11 +1,7 @@ <?php -// $Id: views_handler_filter_date.test,v 1.1.4.3 2010/11/25 20:07:44 dereine Exp $ /** * Tests the handler filter_date. - * - * @TODO - * Convert to "beatles". */ class ViewsHandlerFilterDateTest extends ViewsSqlTest { public static function getInfo() { @@ -47,7 +43,7 @@ class ViewsHandlerFilterDateTest extends ViewsSqlTest { array('nid' => $this->nodes[3]->nid), ); $this->assertIdenticalResultset($view, $expected_result, $this->map); - $view->delete(); + $view->destroy(); // Test offset for between operator. $view->set_display('default'); @@ -61,7 +57,7 @@ class ViewsHandlerFilterDateTest extends ViewsSqlTest { array('nid' => $this->nodes[3]->nid), ); $this->assertIdenticalResultset($view, $expected_result, $this->map); - $view->delete(); + $view->destroy(); } @@ -81,9 +77,9 @@ class ViewsHandlerFilterDateTest extends ViewsSqlTest { array('nid' => $this->nodes[1]->nid), ); $this->assertIdenticalResultset($view, $expected_result, $this->map); - $view->delete(); + $view->destroy(); - // Test between with just min. + // Test between with just max. $view = $this->views_test_between(); $view->set_display('default'); $view->init_handlers(); @@ -95,7 +91,7 @@ class ViewsHandlerFilterDateTest extends ViewsSqlTest { array('nid' => $this->nodes[1]->nid), ); $this->assertIdenticalResultset($view, $expected_result, $this->map); - $view->delete(); + $view->destroy(); // Test not between with min and max. $view = $this->views_test_between(); @@ -111,9 +107,9 @@ class ViewsHandlerFilterDateTest extends ViewsSqlTest { array('nid' => $this->nodes[3]->nid), ); $this->assertIdenticalResultset($view, $expected_result, $this->map); - $view->delete(); + $view->destroy(); - // Test not between with min. + // Test not between with just max. $view = $this->views_test_between(); $view->set_display('default'); $view->init_handlers(); @@ -126,7 +122,7 @@ class ViewsHandlerFilterDateTest extends ViewsSqlTest { array('nid' => $this->nodes[3]->nid), ); $this->assertIdenticalResultset($view, $expected_result, $this->map); - $view->delete(); + $view->destroy(); } /** @@ -139,13 +135,13 @@ class ViewsHandlerFilterDateTest extends ViewsSqlTest { $admin_user = $this->drupalCreateUser(array('administer views', 'administer site configuration')); $this->drupalLogin($admin_user); menu_rebuild(); - $this->drupalGet('admin/structure/views/edit/test_filter_date_between'); + $this->drupalGet('admin/structure/views/view/test_filter_date_between/edit'); $this->drupalGet('admin/structure/views/nojs/config-item/test_filter_date_between/default/filter/created'); $edit = array(); // Generate a definitive wrong value, which should be checked by validation. $edit['options[value][value]'] = $this->randomString() . '-------'; - $this->drupalPost(NULL, $edit, t('Update')); + $this->drupalPost(NULL, $edit, t('Apply')); $this->assertText(t('Invalid date format.'), 'Take sure that validation is runned and the invalidate date format is identified.'); } @@ -158,8 +154,8 @@ class ViewsHandlerFilterDateTest extends ViewsSqlTest { $view->api_version = '3.0-alpha1'; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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'; @@ -167,18 +163,18 @@ class ViewsHandlerFilterDateTest extends ViewsSqlTest { $handler->display->display_options['pager']['type'] = 'full'; $handler->display->display_options['style_plugin'] = 'default'; $handler->display->display_options['row_plugin'] = 'fields'; - /* Field: Node: Nid */ + /* Field: Content: Nid */ $handler->display->display_options['fields']['nid']['id'] = 'nid'; $handler->display->display_options['fields']['nid']['table'] = 'node'; $handler->display->display_options['fields']['nid']['field'] = 'nid'; - /* Filter: Node: Updated date */ + /* Filter: Content: Updated date */ $handler->display->display_options['filters']['created']['id'] = 'created'; $handler->display->display_options['filters']['created']['table'] = 'node'; $handler->display->display_options['filters']['created']['field'] = 'created'; return $view; } - + function views_test_offset() { $view = $this->views_test_between(); return $view; diff --git a/sites/all/modules/views/tests/handlers/views_handler_filter_equality.test b/sites/all/modules/views/tests/handlers/views_handler_filter_equality.test index 769e091a70128d3b088c6b0ec4e79aa51b27dac9..91a8d7b0f4a8799672a5bac058b6d030b33f22f2 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_filter_equality.test +++ b/sites/all/modules/views/tests/handlers/views_handler_filter_equality.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_equality.test,v 1.1.2.1 2010/12/26 22:41:40 dereine Exp $ class viewsHandlerFilterEqualityTest extends ViewsSqlTest { public static function getInfo() { diff --git a/sites/all/modules/views/tests/handlers/views_handler_filter_in_operator.test b/sites/all/modules/views/tests/handlers/views_handler_filter_in_operator.test index c78e031f2f10372329d6e7138dcb7f00eba91738..04ac5de6f7b30e57dd9c12d261beb313c3a5108b 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_filter_in_operator.test +++ b/sites/all/modules/views/tests/handlers/views_handler_filter_in_operator.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_in_operator.test,v 1.1.2.1 2010/11/07 11:32:25 dereine Exp $ class ViewsHandlerFilterInOperator extends ViewsSqlTest { public static function getInfo() { diff --git a/sites/all/modules/views/tests/handlers/views_handler_filter_numeric.test b/sites/all/modules/views/tests/handlers/views_handler_filter_numeric.test index 05187d4e7fb204fa270c41309b30a79e9f1609e1..5ca3be4d8132150771c11fbe8c51c744b610db7a 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_filter_numeric.test +++ b/sites/all/modules/views/tests/handlers/views_handler_filter_numeric.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_numeric.test,v 1.1.2.1 2010/11/06 14:31:59 dereine Exp $ class viewsHandlerFilterNumericTest extends ViewsSqlTest { var $column_map = array(); 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 b5491f1852745e61ef3d3dbc5aa1721fc63cdab9..94102a095156cf2a04bdb7813e95e094854319a1 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_filter_string.test,v 1.1.2.1 2010/12/27 22:06:04 dereine Exp $ class viewsHandlerFilterStringTest extends ViewsSqlTest { var $column_map = array(); diff --git a/sites/all/modules/views/tests/handlers/views_handler_sort.test b/sites/all/modules/views/tests/handlers/views_handler_sort.test index e7410000ae871c84ee1f4f4b4dfbef248f88cf6a..ed9fd58d793382ab7296e83f8105def9a65ffb09 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_sort.test +++ b/sites/all/modules/views/tests/handlers/views_handler_sort.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_sort.test,v 1.1.2.1 2010/11/07 11:32:25 dereine Exp $ /** * Test for core views_handler_sort handler. 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 7f341ac717c224cba5f57c3191da5ace7f26842c..2d522fd8b19f6f9e63e94ad853060a96e537d6a0 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 @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_sort_date.test,v 1.1.2.1 2010/11/07 11:32:25 dereine Exp $ /** * Test for core views_handler_sort_date handler. diff --git a/sites/all/modules/views/tests/handlers/views_handler_sort_random.test b/sites/all/modules/views/tests/handlers/views_handler_sort_random.test index a38a361a3129e5594cd7269eec55c8c40ccc894c..4c179eaeb03afff7519ca6b101dd94ff95c851e7 100644 --- a/sites/all/modules/views/tests/handlers/views_handler_sort_random.test +++ b/sites/all/modules/views/tests/handlers/views_handler_sort_random.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handler_sort_random.test,v 1.1.2.1 2010/11/07 11:32:25 dereine Exp $ /** * Test for core views_handler_sort_random handler. diff --git a/sites/all/modules/views/tests/templates/views-view--frontpage.tpl.php b/sites/all/modules/views/tests/templates/views-view--frontpage.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..00d5f64a0d44679f4c66fbf7b16ae0a33b79329a --- /dev/null +++ b/sites/all/modules/views/tests/templates/views-view--frontpage.tpl.php @@ -0,0 +1,84 @@ +<?php +/** + * @file views-view.tpl.php + * Main view template + * + * Variables available: + * - $classes_array: An array of classes determined in + * template_preprocess_views_view(). Default classes are: + * .view + * .view-[css_name] + * .view-id-[view_name] + * .view-display-id-[display_name] + * .view-dom-id-[dom_id] + * - $classes: A string version of $classes_array for use in the class attribute + * - $css_name: A css-safe version of the view name. + * - $css_class: The user-specified classes names, if any + * - $header: The view header + * - $footer: The view footer + * - $rows: The results of the view query, if any + * - $empty: The empty text to display if the view is empty + * - $pager: The pager next/prev links to display, if any + * - $exposed: Exposed widget form/info to display + * - $feed_icon: Feed icon to display, if any + * - $more: A link to view more, if any + * + * @ingroup views_templates + */ +?> +<div class="<?php print $classes; ?>"> + <?php if ($header): ?> + <div class="view-header"> + <?php print $header; ?> + </div> + <?php endif; ?> + + <?php if ($exposed): ?> + <div class="view-filters"> + <?php print $exposed; ?> + </div> + <?php endif; ?> + + <?php if ($attachment_before): ?> + <div class="attachment attachment-before"> + <?php print $attachment_before; ?> + </div> + <?php endif; ?> + + <?php if ($rows): ?> + <div class="view-content"> + <?php print $rows; ?> + </div> + <?php elseif ($empty): ?> + <div class="view-empty"> + <?php print $empty; ?> + </div> + <?php endif; ?> + + <?php if ($pager): ?> + <?php print $pager; ?> + <?php endif; ?> + + <?php if ($attachment_after): ?> + <div class="attachment attachment-after"> + <?php print $attachment_after; ?> + </div> + <?php endif; ?> + + <?php if ($more): ?> + <?php print $more; ?> + <?php endif; ?> + + <?php if ($footer): ?> + <div class="view-footer"> + <?php print $footer; ?> + </div> + <?php endif; ?> + + <?php if ($feed_icon): ?> + <div class="feed-icon"> + <?php print $feed_icon; ?> + </div> + <?php endif; ?> + +</div> <?php /* class view */ ?> diff --git a/sites/all/modules/views/tests/test_plugins/views_test_plugin_access_test_dynamic.inc b/sites/all/modules/views/tests/test_plugins/views_test_plugin_access_test_dynamic.inc new file mode 100644 index 0000000000000000000000000000000000000000..5e5c29220d3797f26e28378ce6dd4aaba722b199 --- /dev/null +++ b/sites/all/modules/views/tests/test_plugins/views_test_plugin_access_test_dynamic.inc @@ -0,0 +1,18 @@ +<?php + +class views_test_plugin_access_test_dynamic extends views_plugin_access { + function option_definition() { + $options = parent::option_definition(); + $options['access'] = array('default' => FALSE); + + return $options; + } + + function access($account) { + return !empty($this->options['access']) && isset($this->view->args[0]) && $this->view->args[0] == variable_get('test_dynamic_access_argument1', NULL) && isset($this->view->args[1]) && $this->view->args[1] == variable_get('test_dynamic_access_argument2', NULL); + } + + function get_access_callback() { + return array('views_test_test_dynamic_access_callback', array(!empty($options['access']), 1, 2)); + } +} \ No newline at end of file diff --git a/sites/all/modules/views/tests/test_plugins/views_test_plugin_access_test_static.inc b/sites/all/modules/views/tests/test_plugins/views_test_plugin_access_test_static.inc new file mode 100644 index 0000000000000000000000000000000000000000..f42c3001be1e0533d352122ee48bb88f66c0cde4 --- /dev/null +++ b/sites/all/modules/views/tests/test_plugins/views_test_plugin_access_test_static.inc @@ -0,0 +1,18 @@ +<?php + +class views_test_plugin_access_test_static extends views_plugin_access { + function option_definition() { + $options = parent::option_definition(); + $options['access'] = array('default' => FALSE); + + return $options; + } + + function access($account) { + return !empty($this->options['access']); + } + + function get_access_callback() { + return array('views_test_test_static_access_callback', array(!empty($options['access']))); + } +} \ No newline at end of file diff --git a/sites/all/modules/views/tests/user/views_user_argument_default.test b/sites/all/modules/views/tests/user/views_user_argument_default.test index 3a57a956d69b39648721da2eae9925aaecde95b0..d326b5870db6f05d551701dad4a6dd3637ab4486 100644 --- a/sites/all/modules/views/tests/user/views_user_argument_default.test +++ b/sites/all/modules/views/tests/user/views_user_argument_default.test @@ -1,5 +1,4 @@ <?php -// $Id: views_user_argument_default.test,v 1.1.4.4 2010/11/13 17:53:07 dereine Exp $ /** * @file * Tests views user argument default plugin. @@ -18,7 +17,7 @@ class viewsUserArgumentDefault extends ViewsSqlTest { // Create a user to test. $account = $this->drupalCreateUser(); - // Switch the user, we have to check the global user too, because drupalLogin is only for the simpletest browser. + // Switch the user, we have to check the global user too, because drupalLogin is only for the simpletest browser. $this->drupalLogin($account); global $user; $admin = $user; @@ -48,8 +47,8 @@ class viewsUserArgumentDefault extends ViewsSqlTest { $view->api_version = '3.0-alpha1'; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -59,7 +58,7 @@ class viewsUserArgumentDefault extends ViewsSqlTest { $handler->display->display_options['pager']['options']['id'] = '0'; $handler->display->display_options['style_plugin'] = 'default'; $handler->display->display_options['row_plugin'] = 'fields'; - /* Field: Node: Title */ + /* Field: Content: Title */ $handler->display->display_options['fields']['title']['id'] = 'title'; $handler->display->display_options['fields']['title']['table'] = 'node'; $handler->display->display_options['fields']['title']['field'] = 'title'; 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 46fb81e9d35853b495ac30d4e0ce5e00fec6873e..0276d7bd99a1ab9108360885462bc9c0f0de49b6 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 @@ -1,5 +1,5 @@ <?php -// $Id + /** * @file * Tests views user argument argument handler. @@ -90,8 +90,8 @@ class viewsUserArgumentValidate extends viewsSqlTest { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -104,7 +104,7 @@ class viewsUserArgumentValidate extends viewsSqlTest { $handler->display->display_options['arguments']['null']['field'] = 'null'; $handler->display->display_options['arguments']['null']['style_plugin'] = 'default_summary'; $handler->display->display_options['arguments']['null']['default_argument_type'] = 'fixed'; - $handler->display->display_options['arguments']['null']['validate_type'] = 'user'; + $handler->display->display_options['arguments']['null']['validate']['type'] = 'user'; $handler->display->display_options['arguments']['null']['validate_options']['type'] = $argtype; $handler->display->display_options['arguments']['null']['must_not_be'] = 0; diff --git a/sites/all/modules/views/tests/views_access.test b/sites/all/modules/views/tests/views_access.test index 27fcc33063eaf42d5489e7f3ba89aef930b5c23b..4350fb6b33d60ab246e59deb145547f8fdaa928c 100644 --- a/sites/all/modules/views/tests/views_access.test +++ b/sites/all/modules/views/tests/views_access.test @@ -1,5 +1,4 @@ <?php -// $Id: views_access.test,v 1.1.4.6 2011/01/04 21:26:47 dereine Exp $ /** * Basic test for pluggable access. @@ -165,8 +164,8 @@ class ViewsAccessTest extends ViewsSqlTest { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -188,8 +187,8 @@ class ViewsAccessTest extends ViewsSqlTest { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* Display: Master */ + $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['access']['type'] = 'perm'; $handler->display->display_options['access']['perm'] = 'views_test test permission'; $handler->display->display_options['cache']['type'] = 'none'; @@ -212,8 +211,8 @@ class ViewsAccessTest extends ViewsSqlTest { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* Display: Master */ + $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['access']['type'] = 'role'; $handler->display->display_options['access']['role'] = array( $this->normal_role => $this->normal_role, @@ -238,8 +237,8 @@ class ViewsAccessTest extends ViewsSqlTest { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* Display: Master */ + $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['access']['type'] = 'test_dynamic'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['exposed_form']['type'] = 'basic'; @@ -264,8 +263,8 @@ class ViewsAccessTest extends ViewsSqlTest { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* Display: Master */ + $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['access']['type'] = 'test_static'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['exposed_form']['type'] = 'basic'; diff --git a/sites/all/modules/views/tests/views_analyze.test b/sites/all/modules/views/tests/views_analyze.test index 31539a37b0fbd3436672cb7b04d7d587c35eb346..934566066b5e2f95eed1aef38b2886abb4bad9c4 100644 --- a/sites/all/modules/views/tests/views_analyze.test +++ b/sites/all/modules/views/tests/views_analyze.test @@ -1,5 +1,4 @@ <?php -// $Id: views_analyze.test,v 1.1.2.1 2010/11/20 21:40:58 dereine Exp $ /** * @file * Tests the views analyse system. @@ -18,7 +17,7 @@ class ViewsAnalyzeTest extends viewsSqlTest { parent::setUp('views_ui'); module_enable(array('views_ui')); // @TODO Figure out why it's required to clear the cache here. - views_module_include('views_default.inc', TRUE); + views_module_include('views_default', TRUE); views_get_all_views(TRUE); menu_rebuild(); @@ -35,11 +34,11 @@ class ViewsAnalyzeTest extends viewsSqlTest { $view = views_get_view('frontpage'); $view->save(); - $this->drupalGet('admin/structure/views/edit/frontpage'); - $this->helperButtonHasLabel('edit-submit', t('Analyze')); + $this->drupalGet('admin/structure/views/view/frontpage/edit'); + $this->assertLink(t('analyze')); // This redirects the user to the form. - $this->drupalPost(NULL, array(), t('Analyze')); + $this->clickLink(t('analyze')); $this->assertText(t('View analysis')); // This redirects the user back to the main views edit page. diff --git a/sites/all/modules/views/tests/views_argument_default.test b/sites/all/modules/views/tests/views_argument_default.test index 44f975b298126978f3de437b6482ac54adb6bc72..5c04701fb95473544d8e477af2041b93811e0f7c 100644 --- a/sites/all/modules/views/tests/views_argument_default.test +++ b/sites/all/modules/views/tests/views_argument_default.test @@ -1,5 +1,4 @@ <?php -// $Id: views_argument_default.test,v 1.1.2.3 2010/05/24 19:58:36 dereine Exp $ /** * Basic test for pluggable argument default. @@ -29,7 +28,7 @@ class ViewsArgumentDefaultTest extends ViewsSqlTest { $view->execute_display(); $view->destroy(); - $this->assertEqual($view->args[0], $this->random, t('Fixed argument should be used by default.')); + $this->assertEqual($view->args[0], $this->random, 'Fixed argument should be used by default.'); // Take sure that a normal argument provided is used $view = $this->view_argument_default_fixed(); @@ -38,7 +37,7 @@ class ViewsArgumentDefaultTest extends ViewsSqlTest { $random_string = $this->randomString(); $view->execute_display('default', array($random_string)); - $this->assertEqual($view->args[0], $random_string, t('Provided argumetn should be used.')); + $this->assertEqual($view->args[0], $random_string, 'Provided argument should be used.'); } /** @@ -66,8 +65,8 @@ class ViewsArgumentDefaultTest extends ViewsSqlTest { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -77,7 +76,7 @@ class ViewsArgumentDefaultTest extends ViewsSqlTest { $handler->display->display_options['pager']['options']['id'] = '0'; $handler->display->display_options['style_plugin'] = 'default'; $handler->display->display_options['row_plugin'] = 'fields'; - /* Field: Node: Title */ + /* Field: Content: Title */ $handler->display->display_options['fields']['title']['id'] = 'title'; $handler->display->display_options['fields']['title']['table'] = 'node'; $handler->display->display_options['fields']['title']['field'] = 'title'; @@ -103,5 +102,4 @@ class ViewsArgumentDefaultTest extends ViewsSqlTest { return $view; } -} - +} \ No newline at end of file diff --git a/sites/all/modules/views/tests/views_argument_validator.test b/sites/all/modules/views/tests/views_argument_validator.test index a046f9d9f8c95604f285be5482c85998bf620236..47fce73067aa2f93e12de131a163750b2f165c71 100644 --- a/sites/all/modules/views/tests/views_argument_validator.test +++ b/sites/all/modules/views/tests/views_argument_validator.test @@ -1,5 +1,4 @@ <?php -// $Id: views_argument_validator.test,v 1.1.4.6 2010/05/24 19:58:36 dereine Exp $ class viewsArgumentValidatorTest extends ViewsSqlTest { public static function getInfo() { @@ -45,8 +44,8 @@ class viewsArgumentValidatorTest extends ViewsSqlTest { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -77,8 +76,8 @@ class viewsArgumentValidatorTest extends ViewsSqlTest { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; diff --git a/sites/all/modules/views/tests/views_basic.test b/sites/all/modules/views/tests/views_basic.test index 61187d6005aa4463874ddccb322f653014c51c52..22d3a2aa79ab82c302b55d0c0e8ff722821556d0 100644 --- a/sites/all/modules/views/tests/views_basic.test +++ b/sites/all/modules/views/tests/views_basic.test @@ -1,5 +1,4 @@ <?php -// $Id: views_basic.test,v 1.1.4.4 2010/05/24 11:18:18 dereine Exp $ /** * Basic test class for Views query builder tests. diff --git a/sites/all/modules/views/tests/views_cache.test b/sites/all/modules/views/tests/views_cache.test index e5c9f2551a01fda9e1c43f1e2f79d99f683adb6e..f2e39c583068d507e1856c351b3bb019b71851ae 100644 --- a/sites/all/modules/views/tests/views_cache.test +++ b/sites/all/modules/views/tests/views_cache.test @@ -1,5 +1,4 @@ <?php -// $Id: views_cache.test,v 1.1.4.3 2010/05/24 19:58:36 dereine Exp $ /** * @file * test cache system. @@ -31,7 +30,7 @@ class ViewsCacheTest extends ViewsSqlTest { $view->base_table = 'views_test'; // Set up the fields we need. - $display = $view->new_display('default', 'Defaults', 'default'); + $display = $view->new_display('default', 'Master', 'default'); $display->override_option('fields', array( 'id' => array( 'id' => 'id', diff --git a/sites/all/modules/views/tests/views_exposed_form.test b/sites/all/modules/views/tests/views_exposed_form.test index b11cc1eab36972d4787319bc1bba9a96e9816f72..a1fb9922b92022e289c6ee319ac0388e671857b3 100644 --- a/sites/all/modules/views/tests/views_exposed_form.test +++ b/sites/all/modules/views/tests/views_exposed_form.test @@ -1,5 +1,4 @@ <?php -// $Id: views_exposed_form.test,v 1.1.2.6 2010/11/25 20:07:44 dereine Exp $ /** * @file * Test exposed forms. @@ -17,7 +16,7 @@ class ViewsExposedFormTest extends ViewsSqlTest { parent::setUp('views_ui'); module_enable(array('views_ui')); // @TODO Figure out why it's required to clear the cache here. - views_module_include('views_default.inc', TRUE); + views_module_include('views_default', TRUE); views_get_all_views(TRUE); menu_rebuild(); } @@ -63,34 +62,34 @@ class ViewsExposedFormTest extends ViewsSqlTest { $this->drupalGet('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/filter/type'); // Be sure that the button is called exposed - $this->helperButtonHasLabel('edit-options-expose-button-button', t('Expose')); + $this->helperButtonHasLabel('edit-options-expose-button-button', t('Expose filter')); - // Click the Expose button. - $this->drupalPost('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/filter/type', $edit, t('Expose')); + // Click the Expose filter button. + $this->drupalPost('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/filter/type', $edit, t('Expose filter')); // Check the label of the expose button - $this->helperButtonHasLabel('edit-options-expose-button-button', t('Hide')); + $this->helperButtonHasLabel('edit-options-expose-button-button', t('Hide filter')); // Check the validations of the filter handler. $edit = array(); $edit['options[expose][identifier]'] = ''; - $this->drupalPost(NULL, $edit, t('Update')); + $this->drupalPost(NULL, $edit, t('Apply')); $this->assertText(t('The identifier is required if the filter is exposed.')); - + $edit = array(); $edit['options[expose][identifier]'] = 'value'; - $this->drupalPost(NULL, $edit, t('Update')); + $this->drupalPost(NULL, $edit, t('Apply')); $this->assertText(t('This identifier is not allowed.')); // Now check the sort criteria. $this->drupalGet('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/sort/created'); - $this->helperButtonHasLabel('edit-options-expose-button-button', t('Expose')); + $this->helperButtonHasLabel('edit-options-expose-button-button', t('Expose sort')); $this->assertNoFieldById('edit-options-expose-label', '', t('Take sure no label field is shown')); - // Click the Expose button. + // Click the Expose sort button. $edit = array(); - $this->drupalPost('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/sort/created', $edit, t('Expose')); + $this->drupalPost('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/sort/created', $edit, t('Expose sort')); // Check the label of the expose button - $this->helperButtonHasLabel('edit-options-expose-button-button', t('Hide')); + $this->helperButtonHasLabel('edit-options-expose-button-button', t('Hide sort')); $this->assertFieldById('edit-options-expose-label', '', t('Take sure a label field is shown')); } } diff --git a/sites/all/modules/views/tests/views_glossary.test b/sites/all/modules/views/tests/views_glossary.test index 981637bc7d5f4655705a7e51e70a039ceb6d18b0..939f0ae66e8e6bf8c81428502f8cd842d5b73fa8 100644 --- a/sites/all/modules/views/tests/views_glossary.test +++ b/sites/all/modules/views/tests/views_glossary.test @@ -1,5 +1,4 @@ <?php -// $Id: views_glossary.test,v 1.1.4.4 2010/03/14 11:45:38 dereine Exp $ /** * @file * Test glossary view ( summary of arguments ) diff --git a/sites/all/modules/views/tests/views_groupby.test b/sites/all/modules/views/tests/views_groupby.test index 6b9f7df6087aadeb8abed3d4b9a9e0581f4004a5..9f6e0f97b365c1c440471d84873ddd1bab6b1e63 100644 --- a/sites/all/modules/views/tests/views_groupby.test +++ b/sites/all/modules/views/tests/views_groupby.test @@ -1,5 +1,4 @@ <?php -// $Id: views_groupby.test,v 1.1.4.4 2010/05/24 19:58:36 dereine Exp $ class ViewsQueryGroupByTest extends ViewsSqlTest { public static function getInfo() { @@ -68,8 +67,8 @@ class ViewsQueryGroupByTest extends ViewsSqlTest { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* Display: Master */ + $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['group_by'] = TRUE; $handler->display->display_options['access']['type'] = 'none'; $handler->display->display_options['cache']['type'] = 'none'; @@ -77,7 +76,7 @@ class ViewsQueryGroupByTest extends ViewsSqlTest { $handler->display->display_options['pager']['type'] = 'some'; $handler->display->display_options['style_plugin'] = 'default'; $handler->display->display_options['row_plugin'] = 'fields'; - /* Field: Node: Nid */ + /* Field: Content: Nid */ $handler->display->display_options['fields']['nid']['id'] = 'nid'; $handler->display->display_options['fields']['nid']['table'] = 'node'; $handler->display->display_options['fields']['nid']['field'] = 'title'; @@ -91,7 +90,7 @@ class ViewsQueryGroupByTest extends ViewsSqlTest { $handler->display->display_options['fields']['nid']['hide_empty'] = 0; $handler->display->display_options['fields']['nid']['empty_zero'] = 0; $handler->display->display_options['fields']['nid']['link_to_node'] = 0; - /* Argument: Node: Type */ + /* Argument: Content: Type */ $handler->display->display_options['arguments']['type']['id'] = 'type'; $handler->display->display_options['arguments']['type']['table'] = 'node'; $handler->display->display_options['arguments']['type']['field'] = 'type'; @@ -151,8 +150,8 @@ class ViewsQueryGroupByTest extends ViewsSqlTest { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* Display: Master */ + $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['group_by'] = TRUE; $handler->display->display_options['access']['type'] = 'none'; $handler->display->display_options['cache']['type'] = 'none'; @@ -160,7 +159,7 @@ class ViewsQueryGroupByTest extends ViewsSqlTest { $handler->display->display_options['pager']['type'] = 'some'; $handler->display->display_options['style_plugin'] = 'default'; $handler->display->display_options['row_plugin'] = 'fields'; - /* Field: Node: Nid */ + /* Field: Content: Nid */ $handler->display->display_options['fields']['nid']['id'] = 'nid'; $handler->display->display_options['fields']['nid']['table'] = 'node'; $handler->display->display_options['fields']['nid']['field'] = 'nid'; @@ -175,7 +174,7 @@ class ViewsQueryGroupByTest extends ViewsSqlTest { $handler->display->display_options['fields']['nid']['hide_empty'] = 0; $handler->display->display_options['fields']['nid']['empty_zero'] = 0; $handler->display->display_options['fields']['nid']['link_to_node'] = 0; - /* Field: Node: Type */ + /* Field: Content: Type */ $handler->display->display_options['fields']['type']['id'] = 'type'; $handler->display->display_options['fields']['type']['table'] = 'node'; $handler->display->display_options['fields']['type']['field'] = 'type'; @@ -221,15 +220,15 @@ class ViewsQueryGroupByTest extends ViewsSqlTest { menu_rebuild(); $this->drupalGet('admin/structure/views'); - $this->drupalGet('admin/structure/views/edit/test_views_groupby_save'); + $this->drupalGet('admin/structure/views/view/test_views_groupby_save/edit'); $edit = array( 'group_by' => TRUE, ); - $this->drupalPost('admin/structure/views/nojs/display/test_views_groupby_save/default/group_by', $edit, t('Update')); + $this->drupalPost('admin/structure/views/nojs/display/test_views_groupby_save/default/group_by', $edit, t('Apply')); - $this->drupalGet('admin/structure/views/edit/test_views_groupby_save'); - $this->drupalPost('admin/structure/views/edit/test_views_groupby_save', array(), t('Save')); + $this->drupalGet('admin/structure/views/view/test_views_groupby_save/edit'); + $this->drupalPost('admin/structure/views/view/test_views_groupby_save/edit', array(), t('Save')); $this->drupalGet('admin/structure/views/nojs/display/test_views_groupby_save/default/group_by'); } @@ -266,8 +265,8 @@ class ViewsQueryGroupByTest extends ViewsSqlTest { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* Display: Master */ + $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['group_by'] = TRUE; $handler->display->display_options['access']['type'] = 'none'; $handler->display->display_options['cache']['type'] = 'none'; @@ -299,6 +298,4 @@ class ViewsQueryGroupByTest extends ViewsSqlTest { return $view; } -} - - +} \ No newline at end of file diff --git a/sites/all/modules/views/tests/views_handlers.test b/sites/all/modules/views/tests/views_handlers.test index 20a78c986a98b8baac85960c8b3ea90df74e8659..8a6c33267c6443c2ff9b3976ccbc80cb06d13ea3 100644 --- a/sites/all/modules/views/tests/views_handlers.test +++ b/sites/all/modules/views/tests/views_handlers.test @@ -1,5 +1,4 @@ <?php -// $Id: views_handlers.test,v 1.1.4.4 2010/05/24 19:58:36 dereine Exp $ /** * @file @@ -32,8 +31,55 @@ class ViewsHandlersTest extends ViewsSqlTest { $edit = array( 'options[expose][reduce]' => TRUE, ); - $this->drupalPost($path, $edit, t('Update')); + $this->drupalPost($path, $edit, t('Apply')); $this->drupalGet($path); $this->assertFieldByName('options[expose][reduce]', TRUE); } + + function test_views_break_phrase_string() { + $empty_stdclass = new stdClass(); + $empty_stdclass->operator = 'or'; + $empty_stdclass->value = array(); + + $null = NULL; + // check defaults + $this->assertEqual($empty_stdclass, views_break_phrase_string('', $null)); + + $handler = views_get_handler('node', 'title', 'argument'); + $this->assertEqual($handler, views_break_phrase_string('', $handler)); + + // test ors + $this->assertEqualValue(array('word1', 'word2', 'word'), views_break_phrase_string('word1 word2+word', $handler)); + $this->assertEqual('or', $handler->operator); + $this->assertEqualValue(array('word1', 'word2', 'word'), views_break_phrase_string('word1+word2+word', $handler)); + $this->assertEqual('or', $handler->operator); + $this->assertEqualValue(array('word1', 'word2', 'word'), views_break_phrase_string('word1 word2 word', $handler)); + $this->assertEqual('or', $handler->operator); + $this->assertEqualValue(array('word1', 'word2', 'word'), views_break_phrase_string('word1 word2++word', $handler)); + $this->assertEqual('or', $handler->operator); + + // test ands. + $this->assertEqualValue(array('word1', 'word2', 'word'), views_break_phrase_string('word1,word2,word', $handler)); + $this->assertEqual('and', $handler->operator); + $this->assertEqualValue(array('word1', 'word2', 'word'), views_break_phrase_string('word1,,word2,word', $handler)); + $this->assertEqual('and', $handler->operator); + } + + /** + * Check to see if two values are equal. + * + * @param $first + * The first value to check. + * @param $second + * The second value to check. + * @param $message + * The message to display along with the assertion. + * @param $group + * The type of assertion - examples are "Browser", "PHP". + * @return + * TRUE if the assertion succeeded, FALSE otherwise. + */ + protected function assertEqualValue($first, $handler, $message = '', $group = 'Other') { + return $this->assert($first == $handler->value, $message ? $message : t('First value is equal to second value'), $group); + } } diff --git a/sites/all/modules/views/tests/views_module.test b/sites/all/modules/views/tests/views_module.test index 8bfdca2e1d1f83fe756b62f8c23c7ee65468d30d..8a8e36ada5d1ac38a94f0c9f5193bd3b5c44951f 100644 --- a/sites/all/modules/views/tests/views_module.test +++ b/sites/all/modules/views/tests/views_module.test @@ -1,5 +1,4 @@ <?php -// $Id: views_module.test,v 1.1.2.3 2010/12/17 21:51:42 dereine Exp $ module_load_include('test', 'views', 'tests/views_query'); class viewsModuleTest extends ViewsSqlTest { public static function getInfo() { @@ -14,6 +13,19 @@ class viewsModuleTest extends ViewsSqlTest { parent::setUp(); } + public function viewsData() { + $data = parent::viewsData(); + $data['views_test_previous'] = array(); + $data['views_test_previous']['id']['field']['moved to'] = array('views_test', 'id'); + $data['views_test_previous']['id']['filter']['moved to'] = array('views_test', 'id'); + $data['views_test']['age_previous']['field']['moved to'] = array('views_test', 'age'); + $data['views_test']['age_previous']['sort']['moved to'] = array('views_test', 'age'); + $data['views_test_previous']['name_previous']['field']['moved to'] = array('views_test', 'name'); + $data['views_test_previous']['name_previous']['argument']['moved to'] = array('views_test', 'name'); + + return $data; + } + public function test_views_trim_text() { // Test unicode, @see http://drupal.org/node/513396#comment-2839416 $text = array( @@ -76,4 +88,63 @@ class viewsModuleTest extends ViewsSqlTest { $registry = theme_get_registry(); $this->assertTrue(isset($registry['views_view__frontpage'])); } + + /** + * Test the views_get_handler method. + */ + function testviews_get_handler() { + $types = array('field', 'area', 'filter'); + foreach ($types as $type) { + $handler = views_get_handler($this->randomName(), $this->randomName(), $type); + $this->assertEqual('views_handler_' . $type . '_broken', get_class($handler), t('Take sure that a broken handler of type: @type are created', array('@type' => $type))); + } + + $views_data = $this->viewsData(); + $test_tables = array('views_test' => array('id', 'name')); + foreach ($test_tables as $table => $fields) { + foreach ($fields as $field) { + $data = $views_data[$table][$field]; + foreach ($data as $id => $field_data) { + if (!in_array($id, array('title', 'help'))) { + $handler = views_get_handler($table, $field, $id); + $this->assertInstanceHandler($handler, $table, $field, $id); + } + } + } + } + + // Test the automatic conversion feature. + + // Test the automatic table renaming. + $handler = views_get_handler('views_test_previous', 'id', 'field'); + $this->assertInstanceHandler($handler, 'views_test', 'id', 'field'); + $handler = views_get_handler('views_test_previous', 'id', 'filter'); + $this->assertInstanceHandler($handler, 'views_test', 'id', 'filter'); + + // Test the automatic field renaming. + $handler = views_get_handler('views_test', 'age_previous', 'field'); + $this->assertInstanceHandler($handler, 'views_test', 'age', 'field'); + $handler = views_get_handler('views_test', 'age_previous', 'sort'); + $this->assertInstanceHandler($handler, 'views_test', 'age', 'sort'); + + // Test the automatic table and field renaming. + $handler = views_get_handler('views_test_previous', 'name_previous', 'field'); + $this->assertInstanceHandler($handler, 'views_test', 'name', 'field'); + $handler = views_get_handler('views_test_previous', 'name_previous', 'argument'); + $this->assertInstanceHandler($handler, 'views_test', 'name', 'argument'); + + // Test the override handler feature. + $handler = views_get_handler('views_test', 'job', 'filter', 'views_handler_filter'); + $this->assertEqual('views_handler_filter', get_class($handler)); + } + + /** + * Ensure that a certain handler is a instance of a certain table/field. + */ + function assertInstanceHandler($handler, $table, $field, $id) { + $table_data = views_fetch_data($table); + $field_data = $table_data[$field][$id]; + + $this->assertEqual($field_data['handler'], get_class($handler)); + } } diff --git a/sites/all/modules/views/tests/views_pager.test b/sites/all/modules/views/tests/views_pager.test index 1b5360c764f643bf631622b3e82a415417788bc0..e02e43f62b171710f94451d46a92ab9dcb87eeab 100644 --- a/sites/all/modules/views/tests/views_pager.test +++ b/sites/all/modules/views/tests/views_pager.test @@ -1,5 +1,4 @@ <?php -// $Id: views_pager.test,v 1.1.2.6 2010/10/12 20:59:02 merlinofchaos Exp $ /** * @file * Tests the pluggable pager system @@ -28,13 +27,13 @@ class ViewsPagerTest extends DrupalWebTestCase { $this->drupalLogin($admin_user); // Test behaviour described in http://drupal.org/node/652712#comment-2354918. - $this->drupalGet('admin/structure/views/edit/frontpage'); + $this->drupalGet('admin/structure/views/view/frontpage/edit'); $edit = array( 'pager_options[items_per_page]' => 20, ); - $this->drupalPost('admin/structure/views/nojs/display/frontpage/default/pager_options', $edit, t('Update')); + $this->drupalPost('admin/structure/views/nojs/display/frontpage/default/pager_options', $edit, t('Apply')); $this->assertText('20 items'); // Change type and check whether the type is new type is stored. @@ -42,50 +41,48 @@ class ViewsPagerTest extends DrupalWebTestCase { $edit = array( 'pager[type]' => 'mini', ); - $this->drupalPost('admin/structure/views/nojs/display/frontpage/default/pager', $edit, t('Update')); - $this->drupalGet('admin/structure/views/edit/frontpage'); - $this->assertText('Mini pager', 'Changed pager plugin, should change some text'); + $this->drupalPost('admin/structure/views/nojs/display/frontpage/default/pager', $edit, t('Apply')); + $this->drupalGet('admin/structure/views/view/frontpage/edit'); + $this->assertText('Mini', 'Changed pager plugin, should change some text'); // Test behaviour described in http://drupal.org/node/652712#comment-2354400 $view = $this->viewsStorePagerSettings(); // Make it editable in the admin interface. $view->save(); - $this->drupalGet('admin/structure/views/test_store_pager_settings'); + $this->drupalGet('admin/structure/views/view/test_store_pager_settings/edit'); $edit = array(); $edit = array( 'pager[type]' => 'full', ); - $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/default/pager', $edit, t('Update')); - $this->drupalGet('admin/structure/views/edit/test_store_pager_settings'); - $this->assertText('Paged'); + $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/default/pager', $edit, t('Apply')); + $this->drupalGet('admin/structure/views/view/test_store_pager_settings/edit'); + $this->assertText('Full'); $edit = array( 'pager_options[items_per_page]' => 20, ); - $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/default/pager_options', $edit, t('Update')); + $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/default/pager_options', $edit, t('Apply')); $this->assertText('20 items'); // add new display and test the settings again, by override it. - $edit = array( - 'display' => 'page', - ); + $edit = array( ); // Add a display and override the pager settings. - $this->drupalPost('admin/structure/views/edit/test_store_pager_settings', $edit, t('Add display')); + $this->drupalPost('admin/structure/views/view/test_store_pager_settings/edit', $edit, t('Add Page')); $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/page_1/pager', array(), t('Override')); $edit = array( 'pager[type]' => 'mini', ); - $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/page_1/pager', $edit, t('Update')); - $this->drupalGet('admin/structure/views/edit/test_store_pager_settings'); - $this->assertText('Mini pager', 'Changed pager plugin, should change some text'); + $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/page_1/pager', $edit, t('Apply')); + $this->drupalGet('admin/structure/views/view/test_store_pager_settings/edit'); + $this->assertText('Mini', 'Changed pager plugin, should change some text'); $edit = array( 'pager_options[items_per_page]' => 10, ); - $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/default/pager_options', $edit, t('Update')); + $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/default/pager_options', $edit, t('Apply')); $this->assertText('20 items'); } @@ -101,8 +98,8 @@ class ViewsPagerTest extends DrupalWebTestCase { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -162,8 +159,8 @@ class ViewsPagerTest extends DrupalWebTestCase { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -220,8 +217,8 @@ class ViewsPagerTest extends DrupalWebTestCase { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -295,7 +292,7 @@ class ViewsPagerTest extends DrupalWebTestCase { $this->assertEqual($view->query->pager->get_items_per_page(), 0); $this->assertEqual(count($view->result), 11); } - + function viewPagerFullZeroItemsPerPage() { $view = new view; $view->name = 'view_pager_full_zero_items_per_page'; @@ -307,8 +304,8 @@ class ViewsPagerTest extends DrupalWebTestCase { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -318,7 +315,7 @@ class ViewsPagerTest extends DrupalWebTestCase { $handler->display->display_options['pager']['options']['id'] = '0'; $handler->display->display_options['style_plugin'] = 'default'; $handler->display->display_options['row_plugin'] = 'fields'; - /* Field: Node: Title */ + /* Field: Content: Title */ $handler->display->display_options['fields']['title']['id'] = 'title'; $handler->display->display_options['fields']['title']['table'] = 'node'; $handler->display->display_options['fields']['title']['field'] = 'title'; @@ -347,8 +344,8 @@ class ViewsPagerTest extends DrupalWebTestCase { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -373,8 +370,8 @@ class ViewsPagerTest extends DrupalWebTestCase { $view->api_version = 2; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -424,5 +421,4 @@ class ViewsPagerTest extends DrupalWebTestCase { $output = $view->render(); $this->assertEqual(preg_match('/<ul class="pager">/', $output), 0, t('The pager is not rendered.')); } -} - +} \ No newline at end of file diff --git a/sites/all/modules/views/tests/views_plugin_localization_test.inc b/sites/all/modules/views/tests/views_plugin_localization_test.inc index b2ce829f7763b8f92324b7e5f6563db33f5e1a85..fe53b50cdb0bd20b73ba23a988cd3b4f566d8481 100644 --- a/sites/all/modules/views/tests/views_plugin_localization_test.inc +++ b/sites/all/modules/views/tests/views_plugin_localization_test.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_plugin_localization_test.inc,v 1.1.4.2 2010/12/01 20:05:06 dereine Exp $ /** * A stump localisation plugin which has static variables to cache the input. diff --git a/sites/all/modules/views/tests/views_query.test b/sites/all/modules/views/tests/views_query.test index d3d52c5712b9feac0de2b2389c2b03b56aa043f9..4363721003d7daa9cedc18e861304e1b96cdc595 100644 --- a/sites/all/modules/views/tests/views_query.test +++ b/sites/all/modules/views/tests/views_query.test @@ -1,5 +1,4 @@ <?php -// $Id: views_query.test,v 1.1.2.17 2011/01/04 21:26:47 dereine Exp $ /** * @file @@ -147,14 +146,14 @@ abstract class ViewsSqlTest extends ViewsTestCase { /** * This function allows to enable views ui from a higher class which can't change the setup function anymore. - * + * * @TODO * Convert existing setUp functions. */ function enableViewsUi() { module_enable(array('views_ui')); // @TODO Figure out why it's required to clear the cache here. - views_module_include('views_default.inc', TRUE); + views_module_include('views_default', TRUE); views_get_all_views(TRUE); menu_rebuild(); } @@ -368,7 +367,7 @@ abstract class ViewsSqlTest extends ViewsTestCase { $view->base_table = 'views_test'; // Set up the fields we need. - $display = $view->new_display('default', 'Defaults', 'default'); + $display = $view->new_display('default', 'Master', 'default'); $display->override_option('fields', array( 'id' => array( 'id' => 'id', diff --git a/sites/all/modules/views/tests/views_test.info b/sites/all/modules/views/tests/views_test.info index 2ed22abdd10170522ab13d2f73fb720d89c3bc5a..3786faa7428c4e9aff25ad865a01bf9d5870b8c6 100644 --- a/sites/all/modules/views/tests/views_test.info +++ b/sites/all/modules/views/tests/views_test.info @@ -1,4 +1,3 @@ -; $Id: views_test.info,v 1.1.2.3 2010/12/23 17:52:53 dereine Exp $ name = Views Test description = Test module for Views. package = Views @@ -6,9 +5,9 @@ core = 7.x dependencies[] = views hidden = TRUE -; Information added by drupal.org packaging script on 2011-01-06 -version = "7.x-3.0-alpha1" +; Information added by drupal.org packaging script on 2011-03-28 +version = "7.x-3.0-beta3" core = "7.x" project = "views" -datestamp = "1294276880" +datestamp = "1301301970" diff --git a/sites/all/modules/views/tests/views_test.install b/sites/all/modules/views/tests/views_test.install index 348b4a83e5c1c23f53ae585418afaaf503d59bdc..3080b741218a50564182b7c7277ff25eecb6d38f 100644 --- a/sites/all/modules/views/tests/views_test.install +++ b/sites/all/modules/views/tests/views_test.install @@ -1,5 +1,4 @@ <?php -// $Id: views_test.install,v 1.1.2.3 2010/05/24 09:13:58 dereine Exp $ function views_test_schema() { return variable_get('views_test_schema', array()); diff --git a/sites/all/modules/views/tests/views_test.module b/sites/all/modules/views/tests/views_test.module index 924a48948dc61c76facc42c34d9f16815c95cee0..d5806eefe59683ae524fc901251ecb7f50132566 100644 --- a/sites/all/modules/views/tests/views_test.module +++ b/sites/all/modules/views/tests/views_test.module @@ -1,5 +1,4 @@ <?php -// $Id: views_test.module,v 1.1.2.9 2011/01/04 21:26:47 dereine Exp $ /** * Implements hook_permission(). @@ -27,7 +26,7 @@ function views_test_views_api() { * Implements hook_views_data() */ function views_test_views_data() { - return variable_get('views_test_views_data', array()); + return variable_get('views_test_views_data', array()); } /** diff --git a/sites/all/modules/views/tests/views_test.views_default.inc b/sites/all/modules/views/tests/views_test.views_default.inc index cc57330b4d84cbd2121a8984b30f3c20d9e9009f..ab77f1d66d9fe122362865088f3ffa4bcf19b9dd 100644 --- a/sites/all/modules/views/tests/views_test.views_default.inc +++ b/sites/all/modules/views/tests/views_test.views_default.inc @@ -1,5 +1,4 @@ <?php -// $Id: views_test.views_default.inc,v 1.1.2.5 2011/01/05 23:14:39 dereine Exp $ /** * @file * Test views @@ -20,8 +19,8 @@ function views_test_views_default_views() { $view->version = 7; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -42,8 +41,8 @@ function views_test_views_default_views() { $view->version = 7; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -53,13 +52,13 @@ function views_test_views_default_views() { $handler->display->display_options['row_plugin'] = 'node'; $handler->display->display_options['row_options']['links'] = 1; $handler->display->display_options['row_options']['comments'] = 0; - /* Filter: Node: Type */ + /* Filter: Content: Type */ $handler->display->display_options['filters']['type']['id'] = 'type'; $handler->display->display_options['filters']['type']['table'] = 'node'; $handler->display->display_options['filters']['type']['field'] = 'type'; $handler->display->display_options['filters']['type']['exposed'] = TRUE; - $handler->display->display_options['filters']['type']['expose']['operator'] = 'type_op'; - $handler->display->display_options['filters']['type']['expose']['label'] = 'Node: Type'; + $handler->display->display_options['filters']['type']['expose']['operator_id'] = 'type_op'; + $handler->display->display_options['filters']['type']['expose']['label'] = 'Content: Type'; /* Display: Page */ $handler = $view->new_display('page', 'Page', 'page_1'); @@ -78,8 +77,8 @@ function views_test_views_default_views() { $view->version = 7; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['exposed_form']['type'] = 'basic'; @@ -89,16 +88,16 @@ function views_test_views_default_views() { $handler->display->display_options['row_plugin'] = 'node'; $handler->display->display_options['row_options']['links'] = 1; $handler->display->display_options['row_options']['comments'] = 0; - /* Sort criterion: Node: Post date */ + /* Sort criterion: Content: Post date */ $handler->display->display_options['sorts']['created']['id'] = 'created'; $handler->display->display_options['sorts']['created']['table'] = 'node'; $handler->display->display_options['sorts']['created']['field'] = 'created'; - /* Filter: Node: Type */ + /* Filter: Content: Type */ $handler->display->display_options['filters']['type']['id'] = 'type'; $handler->display->display_options['filters']['type']['table'] = 'node'; $handler->display->display_options['filters']['type']['field'] = 'type'; - $handler->display->display_options['filters']['type']['expose']['operator'] = 'type_op'; - $handler->display->display_options['filters']['type']['expose']['label'] = 'Node: Type'; + $handler->display->display_options['filters']['type']['expose']['operator_id'] = 'type_op'; + $handler->display->display_options['filters']['type']['expose']['label'] = 'Content: Type'; $handler->display->display_options['filters']['type']['expose']['use_operator'] = TRUE; /* Display: Page */ @@ -118,21 +117,21 @@ function views_test_views_default_views() { $view->version = 7; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); + /* 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['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'; - /* Filter: Node: Type */ + /* Filter: Content: Type */ $handler->display->display_options['filters']['type']['id'] = 'type'; $handler->display->display_options['filters']['type']['table'] = 'node'; $handler->display->display_options['filters']['type']['field'] = 'type'; $handler->display->display_options['filters']['type']['exposed'] = TRUE; - $handler->display->display_options['filters']['type']['expose']['operator'] = 'type_op'; - $handler->display->display_options['filters']['type']['expose']['label'] = 'Node: Type'; + $handler->display->display_options['filters']['type']['expose']['operator_id'] = 'type_op'; + $handler->display->display_options['filters']['type']['expose']['label'] = 'Content: Type'; $handler->display->display_options['filters']['type']['expose']['use_operator'] = 0; $handler->display->display_options['filters']['type']['expose']['identifier'] = 'type'; $handler->display->display_options['filters']['type']['expose']['reduce'] = 0; @@ -140,5 +139,4 @@ function views_test_views_default_views() { $views[$view->name] = $view; return $views; -} - +} \ No newline at end of file diff --git a/sites/all/modules/views/tests/views_translatable.test b/sites/all/modules/views/tests/views_translatable.test index 2b7c85fd5571b489c618b72756625fac27b05dbb..ac3dd422dd86286b46fcfa7421fd8d874edd715b 100644 --- a/sites/all/modules/views/tests/views_translatable.test +++ b/sites/all/modules/views/tests/views_translatable.test @@ -1,5 +1,4 @@ <?php -// $Id: views_translatable.test,v 1.1.4.2 2010/12/01 20:05:06 dereine Exp $ module_load_include('test', 'views', 'tests/views_query'); @@ -38,7 +37,7 @@ class viewsTranslatableTest extends ViewsSqlTest { variable_set('views_localization_plugin', 'test'); // Reset the plugin data. views_fetch_plugin_data(NULL, NULL, TRUE); - $this->strings = array('Defaults1', 'Apply1', 'Sort By1', 'Asc1', 'Desc1', 'more1', 'Reset1', 'Offset1', 'Defaults1', 'title1', 'Items per page1', 'fieldlabel1', 'filterlabel1'); + $this->strings = array('Master1', 'Apply1', 'Sort By1', 'Asc1', 'Desc1', 'more1', 'Reset1', 'Offset1', 'Master1', 'title1', 'Items per page1', 'fieldlabel1', 'filterlabel1'); $this->enableViewsUi(); } @@ -67,7 +66,7 @@ class viewsTranslatableTest extends ViewsSqlTest { $admin_user = $this->drupalCreateUser(array('administer views', 'administer site configuration')); $this->drupalLogin($admin_user); - $this->drupalGet("admin/structure/views/edit/$view->name"); + $this->drupalGet("admin/structure/views/view/$view->name/edit"); $this->assertNoText('-translated', 'Take sure that no strings get\'s translated in the ui.'); } @@ -96,8 +95,8 @@ class viewsTranslatableTest extends ViewsSqlTest { $view->api_version = '3.0-alpha1'; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults1', 'default'); + /* Display: Master */ + $handler = $view->new_display('default', 'Master1', 'default'); $handler->display->display_options['title'] = 'title1'; $handler->display->display_options['use_more_text'] = 'more1'; $handler->display->display_options['access']['type'] = 'none'; @@ -120,7 +119,7 @@ class viewsTranslatableTest extends ViewsSqlTest { $handler->display->display_options['pager']['options']['expose']['offset_label'] = 'Offset1'; $handler->display->display_options['style_plugin'] = 'default'; $handler->display->display_options['row_plugin'] = 'fields'; - /* Field: Node: Nid */ + /* Field: Content: Nid */ $handler->display->display_options['fields']['nid']['id'] = 'nid'; $handler->display->display_options['fields']['nid']['table'] = 'node'; $handler->display->display_options['fields']['nid']['field'] = 'nid'; @@ -135,15 +134,15 @@ class viewsTranslatableTest extends ViewsSqlTest { $handler->display->display_options['fields']['nid']['hide_empty'] = 0; $handler->display->display_options['fields']['nid']['empty_zero'] = 0; $handler->display->display_options['fields']['nid']['link_to_node'] = 0; - /* Filter: Node: Nid */ + /* Filter: Content: Nid */ $handler->display->display_options['filters']['nid']['id'] = 'nid'; $handler->display->display_options['filters']['nid']['table'] = 'node'; $handler->display->display_options['filters']['nid']['field'] = 'nid'; $handler->display->display_options['filters']['nid']['exposed'] = TRUE; - $handler->display->display_options['filters']['nid']['expose']['operator'] = 'nid_op'; + $handler->display->display_options['filters']['nid']['expose']['operator_id'] = 'nid_op'; $handler->display->display_options['filters']['nid']['expose']['label'] = 'filterlabel1'; $handler->display->display_options['filters']['nid']['expose']['identifier'] = 'nid'; - $handler->display->display_options['filters']['nid']['expose']['single'] = 0; + $handler->display->display_options['filters']['nid']['expose']['multiple'] = 1; $handler->display->display_options['filters']['nid']['expose']['reduce'] = 0; return $view; diff --git a/sites/all/modules/views/tests/views_ui.test b/sites/all/modules/views/tests/views_ui.test new file mode 100644 index 0000000000000000000000000000000000000000..f0f600fdd910dd5dff5d71fafea257f08ed76665 --- /dev/null +++ b/sites/all/modules/views/tests/views_ui.test @@ -0,0 +1,907 @@ +<?php +/** + * @file + * Tests views UI Wizard. + */ + +/** + * Views UI wizard tests. + */ +class ViewsUIWizardHelper extends DrupalWebTestCase { + function setUp() { + // Enable views_ui. + parent::setUp('views_ui'); + + // 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); + } +} + +class ViewsUIWizardBasicTestCase extends ViewsUIWizardHelper { + public static function getInfo() { + return array( + 'name' => 'Views UI wizard basic functionality', + 'description' => 'Test creating basic views with the wizard and viewing them on the listing page.', + 'group' => 'Views UI', + ); + } + + function testViewsWizardAndListing() { + // Check if we can access the main views admin page. + $this->drupalGet('admin/structure/views'); + $this->assertText(t('Add new view')); + + // Create a simple and not at all useful view. + $view1 = array(); + $view1['human_name'] = $this->randomName(16); + $view1['name'] = strtolower($this->randomName(16)); + $view1['description'] = $this->randomName(16); + $view1['page[create]'] = FALSE; + $this->drupalPost('admin/structure/views/add', $view1, t('Save & exit')); + $this->assertText(t('Your view was saved. You may edit it from the list below.')); + $this->assertText($view1['human_name']); + $this->assertText($view1['description']); + foreach(array('delete', 'clone', 'edit') as $operation) { + $this->assertLinkByHref(url('admin/structure/views/view/' . $view1['name'] . '/' . $operation)); + } + + // This view should not have a block. + $this->drupalGet('admin/structure/block'); + $this->assertNoText($view1['name'] . ': Block'); + + // Create two nodes. + $node1 = $this->drupalCreateNode(array('type' => 'page')); + $node2 = $this->drupalCreateNode(array('type' => 'article')); + + // Now create a page with simple node listing and an attached feed. + $view2 = array(); + $view2['human_name'] = $this->randomName(16); + $view2['name'] = strtolower($this->randomName(16)); + $view2['description'] = $this->randomName(16); + $view2['page[create]'] = 1; + $view2['page[title]'] = $this->randomName(16); + $view2['page[path]'] = $this->randomName(16); + $view2['page[feed]'] = 1; + $view2['page[feed_properties][path]'] = $this->randomName(16); + $this->drupalPost('admin/structure/views/add', $view2, t('Save & exit')); + + // Since the view has a page, we expect to be automatically redirected to + // it. + $this->assertUrl($view2['page[path]']); + $this->assertText($view2['page[title]']); + $this->assertText($node1->title); + $this->assertText($node2->title); + + // Check if we have the feed. + $this->assertLinkByHref(url($view2['page[feed_properties][path]'])); + $this->drupalGet($view2['page[feed_properties][path]']); + $this->assertRaw('<rss version="2.0"'); + // The feed should have the same title and nodes as the page. + $this->assertText($view2['page[title]']); + $this->assertRaw(url('node/' . $node1->nid, array('absolute' => TRUE))); + $this->assertText($node1->title); + $this->assertRaw(url('node/' . $node2->nid, array('absolute' => TRUE))); + $this->assertText($node2->title); + + // Go back to the views page and check if this view is there. + $this->drupalGet('admin/structure/views'); + $this->assertText($view2['human_name']); + $this->assertText($view2['description']); + $this->assertLinkByHref(url($view2['page[path]'])); + + // This view should not have a block. + $this->drupalGet('admin/structure/block'); + $this->assertNoText($view2['name'] . ': Block'); + + // Create a view with a page and a block, and filter the listing. + $view3 = array(); + $view3['human_name'] = $this->randomName(16); + $view3['name'] = strtolower($this->randomName(16)); + $view3['description'] = $this->randomName(16); + $view3['show[wizard_key]'] = 'node'; + $view3['show[type]'] = 'page'; + $view3['page[create]'] = 1; + $view3['page[title]'] = $this->randomName(16); + $view3['page[path]'] = $this->randomName(16); + $view3['block[create]'] = 1; + $view3['block[title]'] = $this->randomName(16); + $this->drupalPost('admin/structure/views/add', $view3, t('Save & exit')); + + // Make sure the view only displays the node we expect. + $this->assertUrl($view3['page[path]']); + $this->assertText($view3['page[title]']); + $this->assertText($node1->title); + $this->assertNoText($node2->title); + + // Go back to the views page and check if this view is there. + $this->drupalGet('admin/structure/views'); + $this->assertText($view3['human_name']); + $this->assertText($view3['description']); + $this->assertLinkByHref(url($view3['page[path]'])); + + // Put the block into the first sidebar region. + $this->drupalGet('admin/structure/block'); + $this->assertText($view3['name'] . ': Block'); + $edit = array(); + $edit["blocks[views_{$view3['name']}-block][region]"] = 'sidebar_first'; + $this->drupalPost('admin/structure/block', $edit, t('Save blocks')); + + // Visit a random page (not the one that displays the view itself) and look + // for the expected node title in the block. + $this->drupalGet('user'); + $this->assertText($node1->title); + $this->assertNoText($node2->title); + + // Check if the export screen works. + $this->drupalGet('admin/structure/views/view/' . $view3['name'] . '/export'); + $this->assertRaw('$view = new view;'); + $this->assertRaw($view3['human_name']); + $this->assertRaw($view3['description']); + + // Make sure the listing page doesn't show disabled default views. + $this->assertNoText('tracker', t('Default tracker view does not show on the listing page.')); + } +} + +class ViewsUIWizardDefaultViewsTestCase extends ViewsUIWizardHelper { + public static function getInfo() { + return array( + 'name' => 'Views UI default views functionality', + 'description' => 'Test enabling, disabling, and reverting default views via the listing page.', + 'group' => 'Views UI', + ); + } + + /** + * Test default views. + */ + function testDefaultViews() { + // Make sure the front page view starts off as disabled (does not appear on + // the listing page). + $edit_href = 'admin/structure/views/view/frontpage/edit'; + $this->drupalGet('admin/structure/views'); + // TODO: Disabled default views do now appear on the front page. Test this + // behavior with templates instead. + // $this->assertNoLinkByHref($edit_href); + + // Enable the front page view, and make sure it is now visible on the main + // listing page. + $this->drupalGet('admin/structure/views/templates'); + $this->clickViewsOperationLink(t('Enable'), '/frontpage/'); + $this->assertUrl('admin/structure/views'); + $this->assertLinkByHref($edit_href); + + // It should not be possible to revert the view yet. + $this->assertNoLink(t('Revert')); + $revert_href = 'admin/structure/views/view/frontpage/revert'; + $this->assertNoLinkByHref($revert_href); + + // Edit the view and change the title. Make sure that the new title is + // displayed. + $new_title = $this->randomName(16); + $edit = array('title' => $new_title); + $this->drupalPost('admin/structure/views/nojs/display/frontpage/page/title', $edit, t('Apply')); + $this->drupalPost('admin/structure/views/view/frontpage/edit/page', array(), t('Save')); + $this->drupalGet('frontpage'); + $this->assertText($new_title); + + // It should now be possible to revert the view. Do that, and make sure the + // view title we added above no longer is displayed. + $this->drupalGet('admin/structure/views'); + $this->assertLink(t('Revert')); + $this->assertLinkByHref($revert_href); + $this->drupalPost($revert_href, array(), t('Revert')); + $this->drupalGet('frontpage'); + $this->assertNoText($new_title); + + // Now disable the view, and make sure it stops appearing on the main view + // listing page but instead goes back to displaying on the disabled views + // listing page. + // TODO: Test this behavior with templates instead. + $this->drupalGet('admin/structure/views'); + $this->clickViewsOperationLink(t('Disable'), '/frontpage/'); + // $this->assertUrl('admin/structure/views'); + // $this->assertNoLinkByHref($edit_href); + // The easiest way to verify it appears on the disabled views listing page + // is to try to click the "enable" link from there again. + $this->drupalGet('admin/structure/views/templates'); + $this->clickViewsOperationLink(t('Enable'), '/frontpage/'); + $this->assertUrl('admin/structure/views'); + $this->assertLinkByHref($edit_href); + } + + /** + * Click a link to perform an operation on a view. + * + * In general, we expect lots of links titled "enable" or "disable" on the + * various views listing pages, and they might have tokens in them. So we + * need special code to find the correct one to click. + * + * @param $label + * Text between the anchor tags of the desired link. + * @param $unique_href_part + * A unique string that is expected to occur within the href of the desired + * link. For example, if the link URL is expected to look like + * "admin/structure/views/view/frontpage/...", then "/frontpage/" could be + * passed as the expected unique string. + * + * @return + * The page content that results from clicking on the link, or FALSE on + * failure. Failure also results in a failed assertion. + */ + function clickViewsOperationLink($label, $unique_href_part) { + $links = $this->xpath('//a[normalize-space(text())=:label]', array(':label' => $label)); + foreach ($links as $link_index => $link) { + $position = strpos($link['href'], $unique_href_part); + if ($position !== FALSE) { + $index = $link_index; + break; + } + } + $this->assertTrue(isset($index), t('Link to "@label" containing @part found.', array('@label' => $label, '@part' => $unique_href_part))); + if (isset($index)) { + return $this->clickLink($label, $index); + } + else { + return FALSE; + } + } +} + +class ViewsUIWizardTaggedWithTestCase extends ViewsUIWizardHelper { + protected $node_type_with_tags; + protected $node_type_without_tags; + protected $tag_vocabulary; + protected $tag_field; + protected $tag_instance; + + public static function getInfo() { + return array( + 'name' => 'Views UI wizard taxonomy functionality', + 'description' => 'Test the ability of the views wizard to create views filtered by taxonomy.', + 'group' => 'Views UI', + ); + } + + function setUp() { + parent::setUp(); + + // Create two content types. One will have an autocomplete tagging field, + // and one won't. + $this->node_type_with_tags = $this->drupalCreateContentType(); + $this->node_type_without_tags = $this->drupalCreateContentType(); + + // Create the vocabulary for the tag field. + $this->tag_vocabulary = new stdClass(); + $this->tag_vocabulary->name = 'Views testing tags'; + $this->tag_vocabulary->machine_name = 'views_testing_tags'; + taxonomy_vocabulary_save($this->tag_vocabulary); + + // Create the tag field itself. + $this->tag_field = array( + 'field_name' => 'field_views_testing_tags', + 'type' => 'taxonomy_term_reference', + 'cardinality' => FIELD_CARDINALITY_UNLIMITED, + 'settings' => array( + 'allowed_values' => array( + array( + 'vocabulary' => $this->tag_vocabulary->machine_name, + 'parent' => 0, + ), + ), + ), + ); + field_create_field($this->tag_field); + + // Create an instance of the tag field on one of the content types, and + // configure it to display an autocomplete widget. + $this->tag_instance = array( + 'field_name' => 'field_views_testing_tags', + 'entity_type' => 'node', + 'bundle' => $this->node_type_with_tags->type, + 'widget' => array( + 'type' => 'taxonomy_autocomplete', + ), + 'display' => array( + 'default' => array( + 'type' => 'taxonomy_term_reference_link', + 'weight' => 10, + ), + 'teaser' => array( + 'type' => 'taxonomy_term_reference_link', + 'weight' => 10, + ), + ), + ); + field_create_instance($this->tag_instance); + } + + /** + * Test the "tagged with" functionality. + */ + function testTaggedWith() { + // In this test we will only create nodes that have an instance of the tag + // field. + $node_add_path = 'node/add/' . $this->node_type_with_tags->type; + + // Create three nodes, with different tags. + $tag_field = $this->tag_field['field_name'] . '[' . LANGUAGE_NONE . ']'; + $edit = array(); + $edit['title'] = $node_tag1_title = $this->randomName(); + $edit[$tag_field] = 'tag1'; + $this->drupalPost($node_add_path, $edit, t('Save')); + $edit = array(); + $edit['title'] = $node_tag1_tag2_title = $this->randomName(); + $edit[$tag_field] = 'tag1, tag2'; + $this->drupalPost($node_add_path, $edit, t('Save')); + $edit = array(); + $edit['title'] = $node_no_tags_title = $this->randomName(); + $this->drupalPost($node_add_path, $edit, t('Save')); + + // Create a view that filters by taxonomy term "tag1". It should show only + // the two nodes from above that are tagged with "tag1". + $view1 = array(); + // First select the node type and update the form so the correct tag field + // is used. + $view1['show[type]'] = $this->node_type_with_tags->type; + $this->drupalPost('admin/structure/views/add', $view1, t('Update "of type" choice')); + // Now resubmit the entire form to the same URL. + $view1['human_name'] = $this->randomName(16); + $view1['name'] = strtolower($this->randomName(16)); + $view1['description'] = $this->randomName(16); + $view1['show[tagged_with]'] = 'tag1'; + $view1['page[create]'] = 1; + $view1['page[title]'] = $this->randomName(16); + $view1['page[path]'] = $this->randomName(16); + $this->drupalPost(NULL, $view1, t('Save & exit')); + // Visit the page and check that the nodes we expect are present and the + // ones we don't expect are absent. + $this->drupalGet($view1['page[path]']); + $this->assertText($node_tag1_title); + $this->assertText($node_tag1_tag2_title); + $this->assertNoText($node_no_tags_title); + + // Create a view that filters by taxonomy term "tag2". It should show only + // the one node from above that is tagged with "tag2". + $view2 = array(); + $view2['show[type]'] = $this->node_type_with_tags->type; + $this->drupalPost('admin/structure/views/add', $view2, t('Update "of type" choice')); + $view2['human_name'] = $this->randomName(16); + $view2['name'] = strtolower($this->randomName(16)); + $view2['description'] = $this->randomName(16); + $view2['show[tagged_with]'] = 'tag2'; + $view2['page[create]'] = 1; + $view2['page[title]'] = $this->randomName(16); + $view2['page[path]'] = $this->randomName(16); + $this->drupalPost(NULL, $view2, t('Save & exit')); + $this->drupalGet($view2['page[path]']); + $this->assertNoText($node_tag1_title); + $this->assertText($node_tag1_tag2_title); + $this->assertNoText($node_no_tags_title); + } + + /** + * Test that the "tagged with" form element only shows for node types that support it. + */ + function testTaggedWithByNodeType() { + // The tagging field is associated with one of our node types only. So the + // "tagged with" form element on the view wizard should appear on the form + // by default (when the wizard is configured to display all content) and + // also when the node type that has the tagging field is selected, but not + // when the node type that doesn't have the tagging field is selected. + $tags_xpath = '//input[@name="show[tagged_with]"]'; + $this->drupalGet('admin/structure/views/add'); + $this->assertFieldByXpath($tags_xpath); + $view['show[type]'] = $this->node_type_with_tags->type; + $this->drupalPost('admin/structure/views/add', $view, t('Update "of type" choice')); + $this->assertFieldByXpath($tags_xpath); + $view['show[type]'] = $this->node_type_without_tags->type; + $this->drupalPost(NULL, $view, t('Update "of type" choice')); + $this->assertNoFieldByXpath($tags_xpath); + + // If we add an instance of the tagging field to the second node type, the + // "tagged with" form element should not appear for it too. + $instance = $this->tag_instance; + $instance['bundle'] = $this->node_type_without_tags->type; + field_create_instance($instance); + $view['show[type]'] = $this->node_type_with_tags->type; + $this->drupalPost('admin/structure/views/add', $view, t('Update "of type" choice')); + $this->assertFieldByXpath($tags_xpath); + $view['show[type]'] = $this->node_type_without_tags->type; + $this->drupalPost(NULL, $view, t('Update "of type" choice')); + $this->assertFieldByXpath($tags_xpath); + } +} + +class ViewsUIWizardSortingTestCase extends ViewsUIWizardHelper { + public static function getInfo() { + return array( + 'name' => 'Views UI wizard sorting functionality', + 'description' => 'Test the ability of the views wizard to create views with sorts.', + 'group' => 'Views UI', + ); + } + + /** + * Test the sorting functionality. + */ + function testSorting() { + // Create nodes, each with a different creation time so that we can do a + // meaningful sort. + $node1 = $this->drupalCreateNode(array('created' => REQUEST_TIME)); + $node2 = $this->drupalCreateNode(array('created' => REQUEST_TIME + 1)); + $node3 = $this->drupalCreateNode(array('created' => REQUEST_TIME + 2)); + + // Create a view that sorts oldest first. + $view1 = array(); + $view1['human_name'] = $this->randomName(16); + $view1['name'] = strtolower($this->randomName(16)); + $view1['description'] = $this->randomName(16); + $view1['show[sort]'] = 'created:ASC'; + $view1['page[create]'] = 1; + $view1['page[title]'] = $this->randomName(16); + $view1['page[path]'] = $this->randomName(16); + $this->drupalPost('admin/structure/views/add', $view1, t('Save & exit')); + + // Make sure the view shows the nodes in the expected order. + $this->assertUrl($view1['page[path]']); + $this->assertText($view1['page[title]']); + $content = $this->drupalGetContent(); + $this->assertText($node1->title); + $this->assertText($node2->title); + $this->assertText($node3->title); + $pos1 = strpos($content, $node1->title); + $pos2 = strpos($content, $node2->title); + $pos3 = strpos($content, $node3->title); + $this->assertTrue($pos1 < $pos2 && $pos2 < $pos3, t('The nodes appear in the expected order in a view that sorts by oldest first.')); + + // Create a view that sorts newest first. + $view2 = array(); + $view2['human_name'] = $this->randomName(16); + $view2['name'] = strtolower($this->randomName(16)); + $view2['description'] = $this->randomName(16); + $view2['show[sort]'] = 'created:DESC'; + $view2['page[create]'] = 1; + $view2['page[title]'] = $this->randomName(16); + $view2['page[path]'] = $this->randomName(16); + $this->drupalPost('admin/structure/views/add', $view2, t('Save & exit')); + + // Make sure the view shows the nodes in the expected order. + $this->assertUrl($view2['page[path]']); + $this->assertText($view2['page[title]']); + $content = $this->drupalGetContent(); + $this->assertText($node3->title); + $this->assertText($node2->title); + $this->assertText($node1->title); + $pos3 = strpos($content, $node3->title); + $pos2 = strpos($content, $node2->title); + $pos1 = strpos($content, $node1->title); + $this->assertTrue($pos3 < $pos2 && $pos2 < $pos1, t('The nodes appear in the expected order in a view that sorts by newest first.')); + } +} + +class ViewsUIWizardItemsPerPageTestCase extends ViewsUIWizardHelper { + public static function getInfo() { + return array( + 'name' => 'Views UI wizard items per page functionality', + 'description' => 'Test the ability of the views wizard to specify the number of items per page.', + 'group' => 'Views UI', + ); + } + + /** + * Test the number of items per page. + */ + function testItemsPerPage() { + // Create articles, each with a different creation time so that we can do a + // meaningful sort. + $node1 = $this->drupalCreateNode(array('type' => 'article', 'created' => REQUEST_TIME)); + $node2 = $this->drupalCreateNode(array('type' => 'article', 'created' => REQUEST_TIME + 1)); + $node3 = $this->drupalCreateNode(array('type' => 'article', 'created' => REQUEST_TIME + 2)); + $node4 = $this->drupalCreateNode(array('type' => 'article', 'created' => REQUEST_TIME + 3)); + $node5 = $this->drupalCreateNode(array('type' => 'article', 'created' => REQUEST_TIME + 4)); + + // Create a page. This should never appear in the view created below. + $page_node = $this->drupalCreateNode(array('type' => 'page', 'created' => REQUEST_TIME + 2)); + + // Create a view that sorts newest first, and shows 4 items in the page and + // 3 in the block. + $view = array(); + $view['human_name'] = $this->randomName(16); + $view['name'] = strtolower($this->randomName(16)); + $view['description'] = $this->randomName(16); + $view['show[wizard_key]'] = 'node'; + $view['show[type]'] = 'article'; + $view['show[sort]'] = 'created:DESC'; + $view['page[create]'] = 1; + $view['page[title]'] = $this->randomName(16); + $view['page[path]'] = $this->randomName(16); + $view['page[items_per_page]'] = 4; + $view['block[create]'] = 1; + $view['block[title]'] = $this->randomName(16); + $view['block[items_per_page]'] = 3; + $this->drupalPost('admin/structure/views/add', $view, t('Save & exit')); + + // Make sure the page display shows the nodes we expect, and that they + // appear in the expected order. + $this->assertUrl($view['page[path]']); + $this->assertText($view['page[title]']); + $content = $this->drupalGetContent(); + $this->assertText($node5->title); + $this->assertText($node4->title); + $this->assertText($node3->title); + $this->assertText($node2->title); + $this->assertNoText($node1->title); + $this->assertNoText($page_node->title); + $pos5 = strpos($content, $node5->title); + $pos4 = strpos($content, $node4->title); + $pos3 = strpos($content, $node3->title); + $pos2 = strpos($content, $node2->title); + $this->assertTrue($pos5 < $pos4 && $pos4 < $pos3 && $pos3 < $pos2, t('The nodes appear in the expected order in the page display.')); + + // Put the block into the first sidebar region, visit a page that displays + // the block, and check that the nodes we expect appear in the correct + // order. + $this->drupalGet('admin/structure/block'); + $this->assertText($view['name'] . ': Block'); + $edit = array(); + $edit["blocks[views_{$view['name']}-block][region]"] = 'sidebar_first'; + $this->drupalPost('admin/structure/block', $edit, t('Save blocks')); + $this->drupalGet('user'); + $content = $this->drupalGetContent(); + $this->assertText($node5->title); + $this->assertText($node4->title); + $this->assertText($node3->title); + $this->assertNoText($node2->title); + $this->assertNoText($node1->title); + $this->assertNoText($page_node->title); + $pos5 = strpos($content, $node5->title); + $pos4 = strpos($content, $node4->title); + $pos3 = strpos($content, $node3->title); + $this->assertTrue($pos5 < $pos4 && $pos4 < $pos3, t('The nodes appear in the expected order in the block display.')); + } +} + +class ViewsUIWizardMenuTestCase extends ViewsUIWizardHelper { + public static function getInfo() { + return array( + 'name' => 'Views UI wizard menu functionality', + 'description' => 'Test the ability of the views wizard to put views in a menu.', + 'group' => 'Views UI', + ); + } + + /** + * Test the menu functionality. + */ + function testMenus() { + // Create a view with a page display and a menu link in the Main Menu. + $view = array(); + $view['human_name'] = $this->randomName(16); + $view['name'] = strtolower($this->randomName(16)); + $view['description'] = $this->randomName(16); + $view['page[create]'] = 1; + $view['page[title]'] = $this->randomName(16); + $view['page[path]'] = $this->randomName(16); + $view['page[link]'] = 1; + $view['page[link_properties][menu_name]'] = 'main-menu'; + $view['page[link_properties][title]'] = $this->randomName(16); + $this->drupalPost('admin/structure/views/add', $view, t('Save & exit')); + + // Make sure there is a link to the view from the front page (where we + // expect the main menu to display). + $this->drupalGet(''); + $this->assertLink($view['page[link_properties][title]']); + $this->assertLinkByHref(url($view['page[path]'])); + + // Make sure the link is associated with the main menu. + $links = menu_load_links('main-menu'); + $found = FALSE; + foreach ($links as $link) { + if ($link['link_path'] == $view['page[path]']) { + $found = TRUE; + break; + } + } + $this->assertTrue($found, t('Found a link to %path in the main menu', array('%path' => $view['page[path]']))); + } +} + +class ViewsUIWizardJumpMenuTestCase extends ViewsUIWizardHelper { + public static function getInfo() { + return array( + 'name' => 'Views UI wizard jump menu functionality', + 'description' => 'Test the ability of the views wizard to create views with a jump menu style plugin.', + 'group' => 'Views UI', + ); + } + + /** + * Test the jump menu style plugin. + */ + function testJumpMenus() { + // We'll run this test for several different base tables that appear in the + // wizard. + $base_table_methods = array( + 'node' => 'createNodeAndGetPath', + 'users' => 'createUserAndGetPath', + 'comment' => 'createCommentAndGetPath', + 'taxonomy_term' => 'createTaxonomyTermAndGetPath', + 'file_managed' => 'createFileAndGetPath', + 'node_revision' => 'createNodeRevisionAndGetPath', + ); + + foreach ($base_table_methods as $base_table => $method) { + // For each base table, find the path that we expect the jump menu to + // redirect us to. + $path_info = $this->{$method}(); + if (is_array($path_info)) { + $path = $path_info['path']; + $options = isset($path_info['options']) ? $path_info['options'] : array(); + } + else { + $path = $path_info; + $options = array(); + } + + // Create a page view for the specified base table that uses the jump + // menu style plugin. + $view = array(); + $view['human_name'] = $this->randomName(16); + $view['name'] = strtolower($this->randomName(16)); + $view['description'] = $this->randomName(16); + $view['show[wizard_key]'] = $base_table; + $view['page[create]'] = 1; + $view['page[title]'] = $this->randomName(16); + $view['page[path]'] = $this->randomName(16); + $view['page[style][style_plugin]'] = 'jump_menu'; + $view['page[style][row_plugin]'] = 'fields'; + $this->drupalPost('admin/structure/views/add', $view, t('Save & exit')); + + // Submit the jump menu form, and check that we are redirected to the + // expected URL. + $edit = array(); + $edit['jump'] = url($path, $options); + $this->drupalPost($view['page[path]'], $edit, t('Go')); + $this->assertResponse(200); + $this->assertUrl($path, $options); + } + } + + /** + * Helper function to create a node and return its expected path. + */ + function createNodeAndGetPath() { + $node = $this->drupalCreateNode(); + return entity_uri('node', $node); + } + + /** + * Helper function to create a user and return its expected path. + */ + function createUserAndGetPath() { + $account = $this->drupalCreateUser(); + return entity_uri('user', $account); + } + + /** + * Helper function to create a comment and return its expected path. + */ + function createCommentAndGetPath() { + $node = $this->drupalCreateNode(); + $comment = (object) array( + 'cid' => NULL, + 'nid' => $node->nid, + 'pid' => 0, + 'uid' => 0, + 'status' => COMMENT_PUBLISHED, + 'subject' => $this->randomName(), + 'language' => LANGUAGE_NONE, + 'comment_body' => array(LANGUAGE_NONE => array($this->randomName())), + ); + comment_save($comment); + return entity_uri('comment', $comment); + } + + /** + * Helper function to create a taxonomy term and return its expected path. + */ + function createTaxonomyTermAndGetPath() { + $vocabulary = new stdClass(); + $vocabulary->name = $this->randomName(); + $vocabulary->machine_name = drupal_strtolower($this->randomName()); + taxonomy_vocabulary_save($vocabulary); + + $term = new stdClass(); + $term->name = $this->randomName(); + $term->vid = $vocabulary->vid; + taxonomy_term_save($term); + + return entity_uri('taxonomy_term', $term); + } + + /** + * Helper function to create a file and return its expected path. + */ + function createFileAndGetPath() { + $file = (object) array( + 'uid' => 1, + 'filename' => 'views-ui-jump-menu-test.txt', + 'uri' => 'public://views-ui-jump-menu-test.txt', + 'filemime' => 'text/plain', + 'timestamp' => 1, + 'status' => FILE_STATUS_PERMANENT, + ); + file_put_contents($file->uri, 'test content'); + $file = file_save($file); + return file_create_url($file->uri); + } + + /** + * Helper function to create a node revision and return its expected path. + */ + function createNodeRevisionAndGetPath() { + // The node needs at least two revisions in order for Drupal to allow + // access to the revision path. + $settings = array('revision' => TRUE); + $node = $this->drupalCreateNode($settings); + $node->vid = NULL; + node_save($node); + return 'node/' . $node->nid . '/revisions/' . $node->vid . '/view'; + } +} + +class ViewsUIWizardOverrideDisplaysTestCase extends ViewsUIWizardHelper { + public static function getInfo() { + return array( + 'name' => 'Views UI overridden displays', + 'description' => 'Test that displays can be correctly overridden via the user interface.', + 'group' => 'Views UI', + ); + } + + /** + * Test that displays can be overridden via the UI. + */ + function testOverrideDisplays() { + // Create a basic view that shows all content, with a page and a block + // display. + $view['human_name'] = $this->randomName(16); + $view['name'] = strtolower($this->randomName(16)); + $view['page[create]'] = 1; + $view['page[path]'] = $this->randomName(16); + $view['block[create]'] = 1; + $view_path = $view['page[path]']; + $this->drupalPost('admin/structure/views/add', $view, t('Save & exit')); + + // Configure its title. Since the page and block both started off with the + // same (empty) title in the views wizard, we expect the wizard to have set + // things up so that they both inherit from the default display, and we + // therefore only need to change that to have it take effect for both. + $edit = array(); + $edit['title'] = $original_title = $this->randomName(16); + $edit['override[dropdown]'] = 'default'; + $this->drupalPost("admin/structure/views/nojs/display/{$view['name']}/page/title", $edit, t('Apply')); + $this->drupalPost("admin/structure/views/view/{$view['name']}/edit/page", array(), t('Save')); + + // Put the block into the first sidebar region, and make sure it will not + // display on the view's page display (since we will be searching for the + // presence/absence of the view's title in both the page and the block). + $this->drupalGet('admin/structure/block'); + $edit = array(); + $edit["blocks[views_{$view['name']}-block][region]"] = 'sidebar_first'; + $this->drupalPost('admin/structure/block', $edit, t('Save blocks')); + $edit = array(); + $edit['visibility'] = BLOCK_VISIBILITY_NOTLISTED; + $edit['pages'] = $view_path; + $this->drupalPost("admin/structure/block/manage/views/{$view['name']}-block/configure", $edit, t('Save block')); + + // Add a node that will appear in the view, so that the block will actually + // be displayed. + $this->drupalCreateNode(); + + // Make sure the title appears in both the page and the block. + $this->drupalGet($view_path); + $this->assertText($original_title); + $this->drupalGet(''); + $this->assertText($original_title); + + // Change the title for the page display only, and make sure that is the + // only one that is changed. + $edit = array(); + $edit['title'] = $new_title = $this->randomName(16); + $edit['override[dropdown]'] = 'page'; + $this->drupalPost("admin/structure/views/nojs/display/{$view['name']}/page/title", $edit, t('Apply')); + $this->drupalPost("admin/structure/views/view/{$view['name']}/edit/page", array(), t('Save')); + $this->drupalGet($view_path); + $this->assertText($new_title); + $this->assertNoText($original_title); + $this->drupalGet(''); + $this->assertText($original_title); + $this->assertNoText($new_title); + } + + /** + * Test that the wizard correctly sets up default and overridden displays. + */ + function testWizardMixedDefaultOverriddenDisplays() { + // Create a basic view with a page, block, and feed. Give the page and feed + // identical titles, but give the block a different one, so we expect the + // page and feed to inherit their titles from the default display, but the + // block to override it. + $view['human_name'] = $this->randomName(16); + $view['name'] = strtolower($this->randomName(16)); + $view['page[create]'] = 1; + $view['page[title]'] = $this->randomName(16); + $view['page[path]'] = $this->randomName(16); + $view['page[feed]'] = 1; + $view['page[feed_properties][path]'] = $this->randomName(16); + $view['block[create]'] = 1; + $view['block[title]'] = $this->randomName(16); + $this->drupalPost('admin/structure/views/add', $view, t('Save & exit')); + + // Put the block into the first sidebar region, and make sure it will not + // display on the view's page display (since we will be searching for the + // presence/absence of the view's title in both the page and the block). + $this->drupalGet('admin/structure/block'); + $edit = array(); + $edit["blocks[views_{$view['name']}-block][region]"] = 'sidebar_first'; + $this->drupalPost('admin/structure/block', $edit, t('Save blocks')); + $edit = array(); + $edit['visibility'] = BLOCK_VISIBILITY_NOTLISTED; + $edit['pages'] = $view['page[path]']; + $this->drupalPost("admin/structure/block/manage/views/{$view['name']}-block/configure", $edit, t('Save block')); + + // Add a node that will appear in the view, so that the block will actually + // be displayed. + $this->drupalCreateNode(); + + // Make sure that the feed, page and block all start off with the correct + // titles. + $this->drupalGet($view['page[path]']); + $this->assertText($view['page[title]']); + $this->assertNoText($view['block[title]']); + $this->drupalGet($view['page[feed_properties][path]']); + $this->assertText($view['page[title]']); + $this->assertNoText($view['block[title]']); + $this->drupalGet(''); + $this->assertText($view['block[title]']); + $this->assertNoText($view['page[title]']); + + // Edit the page and change the title. This should automatically change + // the feed's title also, but not the block. + $edit = array(); + $edit['title'] = $new_default_title = $this->randomName(16); + $this->drupalPost("admin/structure/views/nojs/display/{$view['name']}/page/title", $edit, t('Apply')); + $this->drupalPost("admin/structure/views/view/{$view['name']}/edit/page", array(), t('Save')); + $this->drupalGet($view['page[path]']); + $this->assertText($new_default_title); + $this->assertNoText($view['page[title]']); + $this->assertNoText($view['block[title]']); + $this->drupalGet($view['page[feed_properties][path]']); + $this->assertText($new_default_title); + $this->assertNoText($view['page[title]']); + $this->assertNoText($view['block[title]']); + $this->drupalGet(''); + $this->assertText($view['block[title]']); + $this->assertNoText($new_default_title); + $this->assertNoText($view['page[title]']); + + // Edit the block and change the title. This should automatically change + // the block title only, and leave the defaults alone. + $edit = array(); + $edit['title'] = $new_block_title = $this->randomName(16); + $this->drupalPost("admin/structure/views/nojs/display/{$view['name']}/block/title", $edit, t('Apply')); + $this->drupalPost("admin/structure/views/view/{$view['name']}/edit/block", array(), t('Save')); + $this->drupalGet($view['page[path]']); + $this->assertText($new_default_title); + $this->assertNoText($new_block_title); + $this->drupalGet($view['page[feed_properties][path]']); + $this->assertText($new_default_title); + $this->assertNoText($new_block_title); + $this->drupalGet(''); + $this->assertText($new_block_title); + $this->assertNoText($view['block[title]']); + } +} diff --git a/sites/all/modules/views/tests/views_upgrade.test b/sites/all/modules/views/tests/views_upgrade.test new file mode 100644 index 0000000000000000000000000000000000000000..102fb5f268cb7d9df509edad69213a6e9325c506 --- /dev/null +++ b/sites/all/modules/views/tests/views_upgrade.test @@ -0,0 +1,266 @@ +<?php +/** + * @file + * Try to test the upgrade path of all conversions. + * + * You can find all conversions by searching for "moved to". + */ +class viewsUpgradeTestCase extends ViewsSqlTest { + public static function getInfo() { + return array( + 'name' => 'Views Upgrade test', + 'description' => 'Try to test the upgrade path of modules which were changed.', + 'group' => 'Views', + ); + } + + 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); + } + + function viewsData() { + $data = parent::viewsData(); + $data['views_test']['old_field_1']['moved to'] = array('views_test', 'id'); + $data['views_test']['old_field_2']['field']['moved to'] = array('views_test', 'name'); + $data['views_test']['old_field_3']['filter']['moved to'] = array('views_test', 'age'); + + // @todo Test this scenario, too. + $data['views_old_table_2']['old_field']['moved to'] = array('views_test', 'job'); + + $data['views_old_table']['moved to'] = 'views_test'; + + return $data; + } + + function debugField($field) { + $keys = array('id', 'table', 'field', 'actual_field', 'original_field', 'real_field'); + $info = array(); + foreach ($keys as $key) { + $info[$key] = $field->{$key}; + } + debug($info, NULL, TRUE); + } + + /** + * Test the moved to parameter in general. + */ + public function testMovedTo() { + // Test moving on field lavel. + $view = $this->viewsMovedToField(); + $view->build(); + +// $this->assertEqual('old_field_1', $view->field['old_field_1']->options['id'], "Id shouldn't change during conversion"); +// $this->assertEqual('id', $view->field['old_field_1']->field, 'The field should change during conversion'); + $this->assertEqual('id', $view->field['old_field_1']->real_field); + $this->assertEqual('views_test', $view->field['old_field_1']->table); + $this->assertEqual('old_field_1', $view->field['old_field_1']->original_field, 'The field should have stored the original_field'); + + // Test moving on handler lavel. + $view = $this->viewsMovedToHandler(); + $view->build(); + +// $this->assertEqual('old_field_2', $view->field['old_field_2']->options['id']); + $this->assertEqual('name', $view->field['old_field_2']->real_field); + $this->assertEqual('views_test', $view->field['old_field_2']->table); + +// $this->assertEqual('old_field_3', $view->filter['old_field_3']->options['id']); + $this->assertEqual('age', $view->filter['old_field_3']->real_field); + $this->assertEqual('views_test', $view->filter['old_field_3']->table); + + // Test moving on table level. + $view = $this->viewsMovedToTable(); + $view->build(); + + $this->assertEqual('views_test', $view->base_table, 'Take sure that view->base_table gets automatically converted.'); +// $this->assertEqual('id', $view->field['id']->field, 'If we move a whole table fields of this table should work, too.'); + $this->assertEqual('id', $view->field['id']->real_field, 'To run the query right the real_field has to be set right.'); + $this->assertEqual('views_test', $view->field['id']->table); + } + + /** + * Test a import via ui. + * + * To ensure the general functionality the recent comments view from drupal6 is used. + */ + public function testUpgradeImport() { + $edit = array( + 'view' => $this->viewUpgradeImport(), + ); + $this->drupalPost('admin/structure/views/import', $edit, t('Import')); + + $this->assertText('Recent comments'); + } + + public function viewsMovedToField() { + $view = new view; + $view->name = 'test_views_move_to_field'; + $view->description = ''; + $view->tag = ''; + $view->view_php = ''; + $view->base_table = 'views_test'; + $view->is_cacheable = FALSE; + $view->api_version = 2; + $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['fields']['old_field_1']['id'] = 'old_field_1'; + $handler->display->display_options['fields']['old_field_1']['table'] = 'views_test'; + $handler->display->display_options['fields']['old_field_1']['field'] = 'old_field_1'; + + return $view; + } + + public function viewsMovedToHandler() { + $view = new view; + $view->name = 'test_views_move_to_handler'; + $view->description = ''; + $view->tag = ''; + $view->view_php = ''; + $view->base_table = 'views_test'; + $view->is_cacheable = FALSE; + $view->api_version = 2; + $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['fields']['old_field_2']['id'] = 'old_field_2'; + $handler->display->display_options['fields']['old_field_2']['table'] = 'views_test'; + $handler->display->display_options['fields']['old_field_2']['field'] = 'old_field_2'; + + $handler->display->display_options['filters']['old_field_3']['id'] = 'old_field_3'; + $handler->display->display_options['filters']['old_field_3']['table'] = 'views_test'; + $handler->display->display_options['filters']['old_field_3']['field'] = 'old_field_3'; + + return $view; + } + + public function viewsMovedToTable() { + $view = new view; + $view->name = 'test_views_move_to_table'; + $view->description = ''; + $view->tag = ''; + $view->view_php = ''; + $view->base_table = 'views_old_table'; + $view->is_cacheable = FALSE; + $view->api_version = 2; + $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['fields']['id']['id'] = 'id'; + $handler->display->display_options['fields']['id']['table'] = 'views_old_table'; + $handler->display->display_options['fields']['id']['field'] = 'id'; + + return $view; + } + + protected function viewUpgradeImport() { + $import = ' + $view = new view; + $view->name = "comments_recent"; + $view->description = "Contains a block and a page to list recent comments; the block will automatically link to the page, which displays the comment body as well as a link to the node."; + $view->tag = "default"; + $view->base_table = "comments"; + $view->human_name = ""; + $view->core = 0; + $view->api_version = "3.0-alpha1"; + $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ + + /* Display: Defaults */ + $handler = $view->new_display("default", "Defaults", "default"); + $handler->display->display_options["title"] = "Recent comments"; + $handler->display->display_options["use_more"] = TRUE; + $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["exposed_form"]["type"] = "basic"; + $handler->display->display_options["pager"]["type"] = "some"; + $handler->display->display_options["pager"]["options"]["items_per_page"] = 5; + $handler->display->display_options["style_plugin"] = "list"; + $handler->display->display_options["row_plugin"] = "fields"; + /* Relationship: Comment: Node */ + $handler->display->display_options["relationships"]["nid"]["id"] = "nid"; + $handler->display->display_options["relationships"]["nid"]["table"] = "comments"; + $handler->display->display_options["relationships"]["nid"]["field"] = "nid"; + /* Field: Comment: Title */ + $handler->display->display_options["fields"]["subject"]["id"] = "subject"; + $handler->display->display_options["fields"]["subject"]["table"] = "comments"; + $handler->display->display_options["fields"]["subject"]["field"] = "subject"; + $handler->display->display_options["fields"]["subject"]["label"] = ""; + $handler->display->display_options["fields"]["subject"]["link_to_comment"] = 1; + /* Field: Comment: Post date */ + $handler->display->display_options["fields"]["timestamp"]["id"] = "timestamp"; + $handler->display->display_options["fields"]["timestamp"]["table"] = "comments"; + $handler->display->display_options["fields"]["timestamp"]["field"] = "timestamp"; + $handler->display->display_options["fields"]["timestamp"]["label"] = ""; + $handler->display->display_options["fields"]["timestamp"]["date_format"] = "time ago"; + /* Sort criterion: Comment: Post date */ + $handler->display->display_options["sorts"]["timestamp"]["id"] = "timestamp"; + $handler->display->display_options["sorts"]["timestamp"]["table"] = "comments"; + $handler->display->display_options["sorts"]["timestamp"]["field"] = "timestamp"; + $handler->display->display_options["sorts"]["timestamp"]["order"] = "DESC"; + /* Filter: Node: Published or admin */ + $handler->display->display_options["filters"]["status_extra"]["id"] = "status_extra"; + $handler->display->display_options["filters"]["status_extra"]["table"] = "node"; + $handler->display->display_options["filters"]["status_extra"]["field"] = "status_extra"; + $handler->display->display_options["filters"]["status_extra"]["relationship"] = "nid"; + $handler->display->display_options["filters"]["status_extra"]["group"] = 0; + $handler->display->display_options["filters"]["status_extra"]["expose"]["operator"] = FALSE; + + /* Display: Page */ + $handler = $view->new_display("page", "Page", "page"); + $handler->display->display_options["defaults"]["items_per_page"] = FALSE; + $handler->display->display_options["defaults"]["style_plugin"] = FALSE; + $handler->display->display_options["style_plugin"] = "list"; + $handler->display->display_options["defaults"]["style_options"] = FALSE; + $handler->display->display_options["defaults"]["row_plugin"] = FALSE; + $handler->display->display_options["row_plugin"] = "fields"; + $handler->display->display_options["row_options"]["inline"] = array( + "title" => "title", + "timestamp" => "timestamp", + ); + $handler->display->display_options["row_options"]["separator"] = " "; + $handler->display->display_options["defaults"]["row_options"] = FALSE; + $handler->display->display_options["defaults"]["fields"] = FALSE; + /* Field: Node: Title */ + $handler->display->display_options["fields"]["title"]["id"] = "title"; + $handler->display->display_options["fields"]["title"]["table"] = "node"; + $handler->display->display_options["fields"]["title"]["field"] = "title"; + $handler->display->display_options["fields"]["title"]["relationship"] = "nid"; + $handler->display->display_options["fields"]["title"]["label"] = "Reply to"; + $handler->display->display_options["fields"]["title"]["link_to_node"] = 1; + /* Field: Comment: Post date */ + $handler->display->display_options["fields"]["timestamp"]["id"] = "timestamp"; + $handler->display->display_options["fields"]["timestamp"]["table"] = "comments"; + $handler->display->display_options["fields"]["timestamp"]["field"] = "timestamp"; + $handler->display->display_options["fields"]["timestamp"]["label"] = ""; + $handler->display->display_options["fields"]["timestamp"]["date_format"] = "time ago"; + /* Field: Comment: Title */ + $handler->display->display_options["fields"]["subject"]["id"] = "subject"; + $handler->display->display_options["fields"]["subject"]["table"] = "comments"; + $handler->display->display_options["fields"]["subject"]["field"] = "subject"; + $handler->display->display_options["fields"]["subject"]["label"] = ""; + $handler->display->display_options["fields"]["subject"]["link_to_comment"] = 1; + /* Field: Comment: Body */ + $handler->display->display_options["fields"]["comment"]["id"] = "comment"; + $handler->display->display_options["fields"]["comment"]["table"] = "comments"; + $handler->display->display_options["fields"]["comment"]["field"] = "comment"; + $handler->display->display_options["fields"]["comment"]["label"] = ""; + $handler->display->display_options["path"] = "comments/recent"; + + /* Display: Block */ + $handler = $view->new_display("block", "Block", "block"); + $handler->display->display_options["block_description"] = "Recent comments view" +;'; + + return $import; + } +} \ No newline at end of file diff --git a/sites/all/modules/views/tests/views_view.test b/sites/all/modules/views/tests/views_view.test new file mode 100644 index 0000000000000000000000000000000000000000..49234e31a0c9ab4ccc8c46079af3115c10f545f2 --- /dev/null +++ b/sites/all/modules/views/tests/views_view.test @@ -0,0 +1,267 @@ +<?php +/** + * Test the view class. + */ +class viewsViewTest extends ViewsSqlTest { + public static function getInfo() { + return array( + 'name' => 'Test the view class', + 'description' => 'Tests some functionality of the view class', + 'group' => 'Views', + ); + } + + /** + * Test the deconstructor to be sure that every kind of heavy objects are removed. + */ + function testDestroy() { + $view = $this->view_test_destroy(); + + $view->preview(); + $view->destroy(); + + $this->assertViewDestroy($view); + + // Manipulate the display variable to test a previous bug. + $view = $this->view_test_destroy(); + $view->preview(); + + $view->destroy(); + $this->assertViewDestroy($view); + } + + function assertViewDestroy($view) { + $this->assertFalse(isset($view->display['default']->handler), 'Take sure all displays are destroyed.'); + $this->assertFalse(isset($view->display['attachment_1']->handler), 'Take sure all displays are destroyed.'); + + $this->assertFalse(isset($view->filter), 'Take sure all handlers are destroyed'); + $this->assertFalse(isset($view->field), 'Take sure all handlers are destroyed'); + $this->assertFalse(isset($view->argument), 'Take sure all handlers are destroyed'); + $this->assertFalse(isset($view->relationship), 'Take sure all handlers are destroyed'); + $this->assertFalse(isset($view->sort), 'Take sure all handlers are destroyed'); + $this->assertFalse(isset($view->area), 'Take sure all handlers are destroyed'); + + $keys = array('current_display', 'display_handler', 'field', 'argument', 'filter', 'sort', 'relationship', 'header', 'footer', 'empty', 'query', 'result', 'inited', 'style_plugin', 'plugin_name', 'exposed_data', 'exposed_input', 'many_to_one_tables'); + foreach ($keys as $key) { + $this->assertFalse(isset($view->{$key}), $key); + } + $this->assertEqual($view->built, FALSE); + $this->assertEqual($view->executed, FALSE); + $this->assertEqual($view->build_info, array()); + $this->assertEqual($view->attachment_before, ''); + $this->assertEqual($view->attachment_after, ''); + } + + function testDelete() { + // Delete a database view + $view = $this->view_test_delete(); + $view->save(); + $view = views_get_view($view->name); + $view->delete(); + + $view = views_get_view($view->name); + $this->assertNotNull($view, 'Take sure that the old view is still in the static cache.'); + + $view = views_get_view($view->name, TRUE); + $this->assertNull($view, "Take sure that the old view get's cleared by the reset parameter."); + } + + /** + * This view provides some filters, fields, arguments, relationships, sorts, areas and attachments. + */ + function view_test_destroy() { + $view = new view; + $view->name = 'test_destroy'; + $view->description = ''; + $view->tag = ''; + $view->base_table = 'node'; + $view->human_name = ''; + $view->api_version = '3.0-alpha1'; + $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['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'; + /* Header: Global: Text area */ + $handler->display->display_options['header']['area']['id'] = 'area'; + $handler->display->display_options['header']['area']['table'] = 'views'; + $handler->display->display_options['header']['area']['field'] = 'area'; + $handler->display->display_options['header']['area']['empty'] = FALSE; + /* Header: Global: Text area */ + $handler->display->display_options['header']['area_1']['id'] = 'area_1'; + $handler->display->display_options['header']['area_1']['table'] = 'views'; + $handler->display->display_options['header']['area_1']['field'] = 'area'; + $handler->display->display_options['header']['area_1']['empty'] = FALSE; + /* Footer: Global: Text area */ + $handler->display->display_options['footer']['area']['id'] = 'area'; + $handler->display->display_options['footer']['area']['table'] = 'views'; + $handler->display->display_options['footer']['area']['field'] = 'area'; + $handler->display->display_options['footer']['area']['empty'] = FALSE; + /* Footer: Global: Text area */ + $handler->display->display_options['footer']['area_1']['id'] = 'area_1'; + $handler->display->display_options['footer']['area_1']['table'] = 'views'; + $handler->display->display_options['footer']['area_1']['field'] = 'area'; + $handler->display->display_options['footer']['area_1']['empty'] = FALSE; + /* Empty text: Global: Text area */ + $handler->display->display_options['empty']['area']['id'] = 'area'; + $handler->display->display_options['empty']['area']['table'] = 'views'; + $handler->display->display_options['empty']['area']['field'] = 'area'; + $handler->display->display_options['empty']['area']['empty'] = FALSE; + /* Empty text: Global: Text area */ + $handler->display->display_options['empty']['area_1']['id'] = 'area_1'; + $handler->display->display_options['empty']['area_1']['table'] = 'views'; + $handler->display->display_options['empty']['area_1']['field'] = 'area'; + $handler->display->display_options['empty']['area_1']['empty'] = FALSE; + /* Relationship: Comment: Node */ + $handler->display->display_options['relationships']['nid']['id'] = 'nid'; + $handler->display->display_options['relationships']['nid']['table'] = 'comments'; + $handler->display->display_options['relationships']['nid']['field'] = 'nid'; + /* Relationship: Comment: Parent comment */ + $handler->display->display_options['relationships']['pid']['id'] = 'pid'; + $handler->display->display_options['relationships']['pid']['table'] = 'comments'; + $handler->display->display_options['relationships']['pid']['field'] = 'pid'; + /* Relationship: Comment: User */ + $handler->display->display_options['relationships']['uid']['id'] = 'uid'; + $handler->display->display_options['relationships']['uid']['table'] = 'comments'; + $handler->display->display_options['relationships']['uid']['field'] = 'uid'; + /* Field: Content: Nid */ + $handler->display->display_options['fields']['nid']['id'] = 'nid'; + $handler->display->display_options['fields']['nid']['table'] = 'node'; + $handler->display->display_options['fields']['nid']['field'] = 'nid'; + /* Field: Content: Path */ + $handler->display->display_options['fields']['path']['id'] = 'path'; + $handler->display->display_options['fields']['path']['table'] = 'node'; + $handler->display->display_options['fields']['path']['field'] = 'path'; + /* Field: Content: Post date */ + $handler->display->display_options['fields']['created']['id'] = 'created'; + $handler->display->display_options['fields']['created']['table'] = 'node'; + $handler->display->display_options['fields']['created']['field'] = 'created'; + /* Sort criterion: Content: In moderation */ + $handler->display->display_options['sorts']['moderate']['id'] = 'moderate'; + $handler->display->display_options['sorts']['moderate']['table'] = 'node'; + $handler->display->display_options['sorts']['moderate']['field'] = 'moderate'; + /* Sort criterion: Content: Last comment author */ + $handler->display->display_options['sorts']['last_comment_name']['id'] = 'last_comment_name'; + $handler->display->display_options['sorts']['last_comment_name']['table'] = 'node_comment_statistics'; + $handler->display->display_options['sorts']['last_comment_name']['field'] = 'last_comment_name'; + /* Sort criterion: Content: Last comment time */ + $handler->display->display_options['sorts']['last_comment_timestamp']['id'] = 'last_comment_timestamp'; + $handler->display->display_options['sorts']['last_comment_timestamp']['table'] = 'node_comment_statistics'; + $handler->display->display_options['sorts']['last_comment_timestamp']['field'] = 'last_comment_timestamp'; + /* Argument: Content: Created date */ + $handler->display->display_options['arguments']['created_fulldate']['id'] = 'created_fulldate'; + $handler->display->display_options['arguments']['created_fulldate']['table'] = 'node'; + $handler->display->display_options['arguments']['created_fulldate']['field'] = 'created_fulldate'; + $handler->display->display_options['arguments']['created_fulldate']['style_plugin'] = 'default_summary'; + $handler->display->display_options['arguments']['created_fulldate']['default_argument_type'] = 'fixed'; + /* Argument: Content: Created day */ + $handler->display->display_options['arguments']['created_day']['id'] = 'created_day'; + $handler->display->display_options['arguments']['created_day']['table'] = 'node'; + $handler->display->display_options['arguments']['created_day']['field'] = 'created_day'; + $handler->display->display_options['arguments']['created_day']['style_plugin'] = 'default_summary'; + $handler->display->display_options['arguments']['created_day']['default_argument_type'] = 'fixed'; + /* Argument: Content: Created month */ + $handler->display->display_options['arguments']['created_month']['id'] = 'created_month'; + $handler->display->display_options['arguments']['created_month']['table'] = 'node'; + $handler->display->display_options['arguments']['created_month']['field'] = 'created_month'; + $handler->display->display_options['arguments']['created_month']['style_plugin'] = 'default_summary'; + $handler->display->display_options['arguments']['created_month']['default_argument_type'] = 'fixed'; + /* Filter: Content: Nid */ + $handler->display->display_options['filters']['nid']['id'] = 'nid'; + $handler->display->display_options['filters']['nid']['table'] = 'node'; + $handler->display->display_options['filters']['nid']['field'] = 'nid'; + /* Filter: Content: Published */ + $handler->display->display_options['filters']['status']['id'] = 'status'; + $handler->display->display_options['filters']['status']['table'] = 'node'; + $handler->display->display_options['filters']['status']['field'] = 'status'; + /* Filter: Content: Title */ + $handler->display->display_options['filters']['title']['id'] = 'title'; + $handler->display->display_options['filters']['title']['table'] = 'node'; + $handler->display->display_options['filters']['title']['field'] = 'title'; + + /* Display: Page */ + $handler = $view->new_display('page', 'Page', 'page_1'); + $handler->display->display_options['path'] = 'test_destroy'; + + /* Display: Attachment */ + $handler = $view->new_display('attachment', 'Attachment', 'attachment_1'); + $handler->display->display_options['pager']['type'] = 'some'; + $handler->display->display_options['displays'] = array( + 'default' => 'default', + 'page_1' => 'page_1', + ); + + /* Display: Attachment */ + $handler = $view->new_display('attachment', 'Attachment', 'attachment_2'); + $handler->display->display_options['pager']['type'] = 'some'; + $handler->display->display_options['displays'] = array( + 'default' => 'default', + 'page_1' => 'page_1', + ); + $translatables['test_destroy'] = array( + t('Master'), + t('more'), + t('Apply'), + t('Reset'), + t('Sort By'), + t('Asc'), + t('Desc'), + t('Items per page'), + t('- All -'), + t('Offset'), + t('Text area'), + t('Content'), + t('Parent comment'), + t('User'), + t('Nid'), + t('Path'), + t('Post date'), + t('All'), + t('Page'), + t('Attachment'), + ); + + return $view; + } + function view_test_delete() { + $view = new view; + $view->name = 'test_view_delete'; + $view->description = ''; + $view->tag = ''; + $view->base_table = 'node'; + $view->human_name = 'test_view_delete'; + $view->core = 7; + $view->api_version = '3.0-alpha1'; + $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ + + /* Display: Defaults */ + $handler = $view->new_display('default', 'Defaults', '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['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'; + $translatables['test_view_delete'] = array( + t('Defaults'), + t('more'), + t('Apply'), + t('Reset'), + t('Sort By'), + t('Asc'), + t('Desc'), + t('Items per page'), + t('- All -'), + t('Offset'), + ); + + return $view; + } +} \ No newline at end of file diff --git a/sites/all/modules/views/theme/theme.inc b/sites/all/modules/views/theme/theme.inc index a005c96d9f7f8ff7d9a2e94d30fe2a1b87508bfc..3ac182a6c94c5534e39fc144dbd507a30e253707 100644 --- a/sites/all/modules/views/theme/theme.inc +++ b/sites/all/modules/views/theme/theme.inc @@ -1,5 +1,4 @@ <?php -// $Id: theme.inc,v 1.84.4.43 2011/01/04 00:00:20 dereine Exp $ /** * @file theme.inc @@ -43,7 +42,7 @@ function template_preprocess_views_view(&$vars) { $view = $vars['view']; - $vars['rows'] = !empty($view->result) || !empty($view->style_plugin->definition['even empty']) ? $view->style_plugin->render($view->result) : ''; + $vars['rows'] = !empty($view->result) || $view->style_plugin->even_empty() ? $view->style_plugin->render($view->result) : ''; $vars['css_name'] = drupal_clean_css_identifier($view->name); $vars['name'] = $view->name; @@ -73,40 +72,36 @@ function template_preprocess_views_view(&$vars) { $vars['exposed'] = !empty($view->exposed_widgets) ? $view->exposed_widgets : ''; $vars['more'] = $view->display_handler->render_more_link(); $vars['feed_icon'] = !empty($view->feed_icon) ? $view->feed_icon : ''; - $vars['pager'] = $view->query->render_pager(); + + $vars['pager'] = ''; + + // @todo: Figure out whether this belongs into views_ui_preprocess_views_view. + // Render title for the admin preview. + $vars['title'] = !empty($view->views_ui_context) ? filter_xss_admin($view->get_title()) : ''; + + if ($view->display_handler->render_pager()) { + $exposed_input = isset($view->exposed_data_raw) ? $view->exposed_data_raw : NULL; + $vars['pager'] = $view->query->render_pager($exposed_input); + } $vars['attachment_before'] = !empty($view->attachment_before) ? $view->attachment_before : ''; $vars['attachment_after'] = !empty($view->attachment_after) ? $view->attachment_after : ''; - // if administrator, add some links. These used to be tabs, but this is better. - if (user_access('administer views') && module_exists('views_ui') && module_exists('contextual') && empty($view->hide_admin_links) && !variable_get('views_no_hover_links', FALSE)) { - $links = array( - 'views-edit' => array( - 'title' => t('Edit view'), - 'attributes' => array('title' => t("Edit this view")), - 'href' => "admin/structure/views/edit/$view->name", - 'fragment' => 'views-tab-' . $view->current_display, - 'query' => drupal_get_destination(), - ), - ); - drupal_alter('views_admin_links', $links, $view); - - $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')), - ), - ); - $vars['classes_array'][] = 'contextual-links-region'; - $vars['admin_links'] = drupal_render($build); - } - else { - $vars['admin_links'] = ''; - $vars['admin_links_raw'] = array(); + // Add contextual links to the view. We need to attach them to the dummy + // $view_array variable, since contextual_preprocess() requires that they be + // attached to an array (not an object) in order to process them. For our + // purposes, it doesn't matter what we attach them to, since once they are + // processed by contextual_preprocess() they will appear in the $title_suffix + // variable (which we will then render in views-view.tpl.php). + views_add_contextual_links($vars['view_array'], 'view', $view, $view->current_display); + // If a display handles where to put the contextual links for themselves let it + // does it but by default render the links in the view ouput. + $vars['admin_links'] = ''; + if (!empty($vars['view_array']['#views_contextual_links_info'])) { + $location = $vars['view_array']['#views_contextual_links_info']['views_ui']; + if ($location == 'view') { + $vars['admin_links'] = drupal_render($vars['view_array']['#contextual_links']['views_ui']); + } } // Attachments are always updated with the outer view, never by themselves, @@ -127,7 +122,7 @@ function template_preprocess_views_view(&$vars) { } // If using AJAX, send identifying data about this view. - if ($view->use_ajax && empty($view->is_attachment)) { + if ($view->use_ajax && empty($view->is_attachment) && empty($view->live_preview)) { $settings = array( 'views' => array( 'ajax_path' => url('views/ajax'), @@ -204,12 +199,13 @@ function template_preprocess_views_view_fields(&$vars) { $object->raw = NULL; // make sure it exists to reduce NOTICE } + $object->inline = !empty($vars['options']['inline'][$id]); + if (!empty($vars['options']['separator']) && $inline && $object->inline && $object->content) { $object->separator = filter_xss_admin($vars['options']['separator']); } $object->class = drupal_clean_css_identifier($id); - $object->inline = !empty($vars['options']['inline'][$id]); $inline = $object->inline; $object->inline_html = $object->handler->element_wrapper_type(TRUE, TRUE); @@ -231,7 +227,7 @@ function template_preprocess_views_view_fields(&$vars) { if ($class) { $class .= ' '; } - $class .= ' ' . $classes; + $class .= $classes; } $object->wrapper_prefix = '<' . $object->inline_html; @@ -307,14 +303,16 @@ function template_preprocess_views_view_field(&$vars) { function template_preprocess_views_view_summary(&$vars) { $view = $vars['view']; $argument = $view->argument[$view->build_info['summary_level']]; + $vars['row_classes'] = array(); $url_options = array(); if (!empty($view->exposed_raw_input)) { $url_options['query'] = $view->exposed_raw_input; } - $vars['classes'] = array(); foreach ($vars['rows'] as $id => $row) { + $vars['row_classes'][$id] = ''; + $vars['rows'][$id]->link = $argument->summary_name($row); $args = $view->args; $args[$argument->position] = $argument->summary_argument($row); @@ -326,7 +324,7 @@ function template_preprocess_views_view_summary(&$vars) { $vars['rows'][$id]->url = url($view->get_url($args, $base_path), $url_options); $vars['rows'][$id]->count = intval($row->{$argument->count_alias}); if ($vars['rows'][$id]->url == base_path() . $_GET['q'] || $vars['rows'][$id]->url == base_path() . drupal_get_path_alias($_GET['q'])) { - $vars['classes'][$id] = 'active'; + $vars['row_classes'][$id] = 'active'; } } } @@ -338,7 +336,7 @@ function template_preprocess_views_view_summary(&$vars) { function template_preprocess_views_view_summary_unformatted(&$vars) { $view = $vars['view']; $argument = $view->argument[$view->build_info['summary_level']]; - $vars['classes'] = array(); + $vars['row_classes'] = array(); $url_options = array(); @@ -363,7 +361,7 @@ function template_preprocess_views_view_summary_unformatted(&$vars) { $vars['rows'][$id]->url = url($view->get_url($args, $base_path), $url_options); $vars['rows'][$id]->count = intval($row->{$argument->count_alias}); if ($vars['rows'][$id]->url == base_path() . $_GET['q'] || $vars['rows'][$id]->url == base_path() . drupal_get_path_alias($_GET['q'])) { - $vars['classes'][$id] = 'active'; + $vars['row_classes'][$id] = 'active'; } } } @@ -478,6 +476,7 @@ function template_preprocess_views_view_table(&$vars) { $vars['field_classes'][$field][$num] .= $classes; } + $vars['field_attributes'][$field][$num] = array(); if (!empty($fields[$field]) && empty($fields[$field]->options['exclude'])) { $field_output = $renders[$num][$field]; @@ -518,11 +517,18 @@ function template_preprocess_views_view_table(&$vars) { $vars['row_classes'][count($vars['row_classes']) - 1][] = 'views-row-last'; $vars['classes_array'] = array('views-table'); + if (empty($vars['rows']) && !empty($options['empty_table'])) { + $vars['rows'][0][0] = $view->display_handler->render_area('empty'); + // Calculate the amounts of rows with output. + $vars['field_attributes'][0][0]['colspan'] = count($vars['header']); + } + + if (!empty($options['sticky'])) { drupal_add_js('misc/tableheader.js'); $vars['classes_array'][] = "sticky-enabled"; } - $vars['classes_array'][] = 'cols-'. count($vars['rows']); + $vars['classes_array'][] = 'cols-'. count($vars['header']); if (!empty($handler->options['summary'])) { $vars['attributes_array'] = array('summary' => $handler->options['summary']); @@ -626,7 +632,7 @@ function template_preprocess_views_view_grid(&$vars) { } } $vars['rows'] = $rows; - + $vars['class'] = 'views-view-grid cols-' . $columns; if (!empty($handler->options['summary'])) { $vars['attributes_array'] = array('summary' => $handler->options['summary']); } @@ -744,7 +750,11 @@ function template_preprocess_views_view_rss(&$vars) { $vars['items'] = $items; $vars['channel_elements'] = format_xml_elements($style->channel_elements); - drupal_add_http_header('Content-Type', 'application/rss+xml; charset=utf-8'); + // During live preview we don't want to output the header since the contents + // of the feed are being displayed inside a normal HTML page. + if (empty($vars['view']->live_preview)) { + drupal_add_http_header('Content-Type', 'application/rss+xml; charset=utf-8'); + } } /** @@ -890,6 +900,14 @@ function theme_views_mini_pager($vars) { } } +/** + * Generic <div> container function. + */ +function theme_views_container($variables) { + $element = $variables['element']; + return '<div' . drupal_attributes($element['#attributes']) . '>' . $element['#children'] . '</div>'; +} + /** * @defgroup views_templates Views' template files * @{ diff --git a/sites/all/modules/views/theme/views-exposed-form.tpl.php b/sites/all/modules/views/theme/views-exposed-form.tpl.php index 52f50c2e7856a3875c7470c1f81b6ff23cec4238..38c3bf033426bcd5b8b5488d687442737c77e757 100644 --- a/sites/all/modules/views/theme/views-exposed-form.tpl.php +++ b/sites/all/modules/views/theme/views-exposed-form.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-exposed-form.tpl.php,v 1.4.6.6 2010/08/13 21:45:25 merlinofchaos Exp $ /** * @file views-exposed-form.tpl.php * diff --git a/sites/all/modules/views/theme/views-more.tpl.php b/sites/all/modules/views/theme/views-more.tpl.php index d56ae178d6f84c4fb611ed2b48a33deeac9265b0..f0025144f6c003da823ad89806c7ae674b4793ff 100644 --- a/sites/all/modules/views/theme/views-more.tpl.php +++ b/sites/all/modules/views/theme/views-more.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-more.tpl.php,v 1.3.4.1 2009/11/02 22:01:27 merlinofchaos Exp $ /** * @file views-more.tpl.php * Theme the more link diff --git a/sites/all/modules/views/theme/views-ui-display-tab-bucket.tpl.php b/sites/all/modules/views/theme/views-ui-display-tab-bucket.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..6fa850ebc1eb577f7ed5c56322b08249f7e42351 --- /dev/null +++ b/sites/all/modules/views/theme/views-ui-display-tab-bucket.tpl.php @@ -0,0 +1,17 @@ +<?php + +/** + * @file views-ui-display-tab-bucket.tpl.php + * Template for each "box" on the display query edit screen. + */ +?> +<div class="<?php print $classes; ?>" <?php print $attributes; ?>> + <?php print $item_help_icon; ?> + <?php if(!empty($actions)) : ?> + <?php print $actions; ?> + <?php endif; ?> + <?php if (!empty($title)) : ?> + <h3><?php print $title; ?></h3> + <?php endif; ?> + <?php print $content; ?> +</div> diff --git a/sites/all/modules/views/theme/views-ui-display-tab-setting.tpl.php b/sites/all/modules/views/theme/views-ui-display-tab-setting.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..dd5c985b3328c1678162a193897b87ad6f047f13 --- /dev/null +++ b/sites/all/modules/views/theme/views-ui-display-tab-setting.tpl.php @@ -0,0 +1,15 @@ +<?php + +/** + * @file views-ui-display-tab-setting.tpl.php + * Template for each row inside the "boxes" on the display query edit screen. + */ +?> +<div class="views-display-setting <?php print $classes; ?> <?php print $zebra; ?> clearfix" <?php print $attributes; ?>> + <?php if ($description): ?> + <span class="label"><?php print $description; ?></span> + <?php endif; ?> + <?php if ($settings_links): ?> + <?php print $settings_links; ?> + <?php endif; ?> +</div> diff --git a/sites/all/modules/views/theme/views-ui-edit-item.tpl.php b/sites/all/modules/views/theme/views-ui-edit-item.tpl.php index e5ebcd675e75a69e02ea8a2a103c9240ab5cecfd..a82aca9baaecfcca2d2889e3734803575f3c43fb 100644 --- a/sites/all/modules/views/theme/views-ui-edit-item.tpl.php +++ b/sites/all/modules/views/theme/views-ui-edit-item.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-ui-edit-item.tpl.php,v 1.9 2008/08/08 16:57:44 merlinofchaos Exp $ /** * @file views-ui-edit-item.tpl.php * diff --git a/sites/all/modules/views/theme/views-ui-edit-tab.tpl.php b/sites/all/modules/views/theme/views-ui-edit-tab.tpl.php index c0e423c4048d8aeec652ca232c6dac2b84dcf205..dffaa9e1070cfcb04bb34f4e8d6893e28e867ffe 100644 --- a/sites/all/modules/views/theme/views-ui-edit-tab.tpl.php +++ b/sites/all/modules/views/theme/views-ui-edit-tab.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-ui-edit-tab.tpl.php,v 1.11.6.4 2010/12/24 08:25:02 dereine Exp $ /** * @file views-ui-edit-tab.tpl.php * Template for the primary view editing window. diff --git a/sites/all/modules/views/theme/views-ui-edit-view.tpl.php b/sites/all/modules/views/theme/views-ui-edit-view.tpl.php index 5c515ab0ba5c2d85ab37ec3d887403172bdc10bb..592ce581368af9ac8019f8e3fe4f9fec47eea146 100644 --- a/sites/all/modules/views/theme/views-ui-edit-view.tpl.php +++ b/sites/all/modules/views/theme/views-ui-edit-view.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-ui-edit-view.tpl.php,v 1.10.6.2 2010/10/16 14:55:13 dereine Exp $ /** * @file views-ui-edit-view.tpl.php * Template for the primary view editing window. @@ -11,7 +10,7 @@ <?php print t('This view is being edited by user !user, and is therefore locked from editing by others. This lock is !age old. Click here to <a href="!break">break this lock</a>.', array('!user' => $locked, '!age' => $lock_age, '!break' => $break)); ?> </div> <?php endif; ?> - <div class="views-basic-info contextual-links-region clearfix<?php if (!empty($view->changed)) { print " changed"; }?>"> + <div class="views-basic-info clearfix<?php if (!empty($view->changed)) { print " changed"; }?>"> <?php if (!is_numeric($view->vid)): ?> <div class="view-changed view-new"><?php print t('New view'); ?></div> <?php else: ?> diff --git a/sites/all/modules/views/theme/views-view-field.tpl.php b/sites/all/modules/views/theme/views-view-field.tpl.php index 6053d1d645f5655b3129c57fcf2477d15cea1847..6aebd27f6e6c12260982be2029dd0c532144d632 100644 --- a/sites/all/modules/views/theme/views-view-field.tpl.php +++ b/sites/all/modules/views/theme/views-view-field.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view-field.tpl.php,v 1.1 2008/05/16 22:22:32 merlinofchaos Exp $ /** * This template is used to print a single field in a view. It is not * actually used in default Views, as this is registered as a theme diff --git a/sites/all/modules/views/theme/views-view-fields.tpl.php b/sites/all/modules/views/theme/views-view-fields.tpl.php index 22d8c7e97f40dee5682daade40c89401c1f09058..6d431b4b5617829f39c658fe6e8f520fa002c37e 100644 --- a/sites/all/modules/views/theme/views-view-fields.tpl.php +++ b/sites/all/modules/views/theme/views-view-fields.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view-fields.tpl.php,v 1.6.6.1 2010/12/04 07:39:35 dereine Exp $ /** * @file views-view-fields.tpl.php * Default simple view template to all the fields as a row. diff --git a/sites/all/modules/views/theme/views-view-grid.tpl.php b/sites/all/modules/views/theme/views-view-grid.tpl.php index 4c831e4ba5ef0e1a85c3fcb131e45b6f5610de32..b5dbfac8a5b593aac5c6800f3d11c2fc6412bf41 100644 --- a/sites/all/modules/views/theme/views-view-grid.tpl.php +++ b/sites/all/modules/views/theme/views-view-grid.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view-grid.tpl.php,v 1.3.6.3 2010/12/10 08:19:15 dereine Exp $ /** * @file views-view-grid.tpl.php * Default simple view template to display a rows in a grid. @@ -13,7 +12,7 @@ <?php if (!empty($title)) : ?> <h3><?php print $title; ?></h3> <?php endif; ?> -<table class="views-view-grid"<?php print $attributes; ?>> +<table class="<?php print $class; ?>"<?php print $attributes; ?>> <tbody> <?php foreach ($rows as $row_number => $columns): ?> <tr class="<?php print $row_classes[$row_number]; ?>"> diff --git a/sites/all/modules/views/theme/views-view-list.tpl.php b/sites/all/modules/views/theme/views-view-list.tpl.php index 167f728d844670afb58225dc3b665f5266810478..b1d66f4b6b3338a19f1294eb0f14fc59a131b5ec 100644 --- a/sites/all/modules/views/theme/views-view-list.tpl.php +++ b/sites/all/modules/views/theme/views-view-list.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view-list.tpl.php,v 1.3.6.3 2010/12/07 17:19:09 dereine Exp $ /** * @file views-view-list.tpl.php * Default simple view template to display a list of rows. diff --git a/sites/all/modules/views/theme/views-view-row-comment.tpl.php b/sites/all/modules/views/theme/views-view-row-comment.tpl.php index 44b1b4360cf34552177b1a33b79934a0b5d4c464..b6fa85c2985a2bfcf3486165894f924490e16245 100644 --- a/sites/all/modules/views/theme/views-view-row-comment.tpl.php +++ b/sites/all/modules/views/theme/views-view-row-comment.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view-row-comment.tpl.php,v 1.1 2008/05/15 22:55:18 merlinofchaos Exp $ /** * @file views-view-row-comment.tpl.php * Default simple view template to display a single comment. diff --git a/sites/all/modules/views/theme/views-view-row-node.tpl.php b/sites/all/modules/views/theme/views-view-row-node.tpl.php index c0a35d3c58a3272cfc5aa4ee16317aea007c5aef..d40bb4dd3f9cebca0898e753654fef6ab1eaa94c 100644 --- a/sites/all/modules/views/theme/views-view-row-node.tpl.php +++ b/sites/all/modules/views/theme/views-view-row-node.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view-row-node.tpl.php,v 1.3.6.1 2010/09/15 09:01:01 dereine Exp $ /** * @file views-view-row-node.tpl.php * Default simple view template to display a single node. diff --git a/sites/all/modules/views/theme/views-view-row-rss.tpl.php b/sites/all/modules/views/theme/views-view-row-rss.tpl.php index 0a975018ba2315657eef3e7ac8641b6280ae63f1..03c6acf5e2afcdcd6d77515a33b873841433f7e4 100644 --- a/sites/all/modules/views/theme/views-view-row-rss.tpl.php +++ b/sites/all/modules/views/theme/views-view-row-rss.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view-row-rss.tpl.php,v 1.1 2008/12/02 22:17:42 merlinofchaos Exp $ /** * @file views-view-row-rss.tpl.php * Default view template to display a item in an RSS feed. diff --git a/sites/all/modules/views/theme/views-view-rss.tpl.php b/sites/all/modules/views/theme/views-view-rss.tpl.php index 36e6ab95146853b17840292eb5fd06dcc1f0e71d..54e4dc9b4fe82a92b7cb9e4c3711345d2fc221c9 100644 --- a/sites/all/modules/views/theme/views-view-rss.tpl.php +++ b/sites/all/modules/views/theme/views-view-rss.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view-rss.tpl.php,v 1.3 2008/12/02 00:02:06 merlinofchaos Exp $ /** * @file views-view-rss.tpl.php * Default template for feed displays that use the RSS style. diff --git a/sites/all/modules/views/theme/views-view-summary-unformatted.tpl.php b/sites/all/modules/views/theme/views-view-summary-unformatted.tpl.php index 9498feb5822155631a6188b4951263361fbb8d60..632d33463eae656761024be5cbcc018057e8454f 100644 --- a/sites/all/modules/views/theme/views-view-summary-unformatted.tpl.php +++ b/sites/all/modules/views/theme/views-view-summary-unformatted.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view-summary-unformatted.tpl.php,v 1.2.6.1 2010/03/16 23:12:25 merlinofchaos Exp $ /** * @file views-view-summary-unformatted.tpl.php * Default simple view template to display a group of summary lines @@ -12,7 +11,7 @@ <?php foreach ($rows as $id => $row): ?> <?php print (!empty($options['inline']) ? '<span' : '<div') . ' class="views-summary views-summary-unformatted">'; ?> <?php if (!empty($row->separator)) { print $row->separator; } ?> - <a href="<?php print $row->url; ?>"<?php print !empty($classes[$id]) ? ' class="'. $classes[$id] .'"' : ''; ?>><?php print $row->link; ?></a> + <a href="<?php print $row->url; ?>"<?php print !empty($row_classes[$id]) ? ' class="' . $row_classes[$id] . '"' : ''; ?>><?php print $row->link; ?></a> <?php if (!empty($options['count'])): ?> (<?php print $row->count; ?>) <?php endif; ?> diff --git a/sites/all/modules/views/theme/views-view-summary.tpl.php b/sites/all/modules/views/theme/views-view-summary.tpl.php index c07d7382d2712badcd4b2b292fc9f21192a95ab3..3ee25bba8f0d95eadc49388525fea7ff71378f0a 100644 --- a/sites/all/modules/views/theme/views-view-summary.tpl.php +++ b/sites/all/modules/views/theme/views-view-summary.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view-summary.tpl.php,v 1.6.6.1 2010/03/16 23:12:25 merlinofchaos Exp $ /** * @file views-view-summary.tpl.php * Default simple view template to display a list of summary lines @@ -10,7 +9,7 @@ <div class="item-list"> <ul class="views-summary"> <?php foreach ($rows as $id => $row): ?> - <li><a href="<?php print $row->url; ?>"<?php print !empty($classes[$id]) ? ' class="'. $classes[$id] .'"' : ''; ?>><?php print $row->link; ?></a> + <li><a href="<?php print $row->url; ?>"<?php print !empty($row_classes[$id]) ? ' class="'. $row_classes[$id] .'"' : ''; ?>><?php print $row->link; ?></a> <?php if (!empty($options['count'])): ?> (<?php print $row->count?>) <?php endif; ?> 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 89866f0ae602d4f4bb5fd45f2d1abc20ee3be5e1..b728b4121a3c60383103a36bfb7f2bec1c4e4826 100644 --- a/sites/all/modules/views/theme/views-view-table.tpl.php +++ b/sites/all/modules/views/theme/views-view-table.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view-table.tpl.php,v 1.8.6.3 2010/12/10 08:19:15 dereine Exp $ /** * @file views-view-table.tpl.php * Template to display a view as a table. @@ -35,7 +34,7 @@ <?php foreach ($rows as $count => $row): ?> <tr class="<?php print implode(' ', $row_classes[$count]); ?>"> <?php foreach ($row as $field => $content): ?> - <td class="<?php print $field_classes[$field][$count]; ?>"> + <td class="<?php print $field_classes[$field][$count]; ?>" <?php print drupal_attributes($field_attributes[$field][$count]); ?>> <?php print $content; ?> </td> <?php endforeach; ?> diff --git a/sites/all/modules/views/theme/views-view-unformatted.tpl.php b/sites/all/modules/views/theme/views-view-unformatted.tpl.php index 6bf5a336df90c172d71f7125833fc246e500d94f..89b35aae975e5b26c72e3f08c695987688e81bf5 100644 --- a/sites/all/modules/views/theme/views-view-unformatted.tpl.php +++ b/sites/all/modules/views/theme/views-view-unformatted.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view-unformatted.tpl.php,v 1.6.6.1 2010/03/29 20:05:38 dereine Exp $ /** * @file views-view-unformatted.tpl.php * Default simple view template to display a list of rows. diff --git a/sites/all/modules/views/theme/views-view.tpl.php b/sites/all/modules/views/theme/views-view.tpl.php index a202ec961083cc2e217d8d4318383c5f5026ebc6..755f8ab87e58223dd3217f2f86ae92fdab1ee177 100644 --- a/sites/all/modules/views/theme/views-view.tpl.php +++ b/sites/all/modules/views/theme/views-view.tpl.php @@ -1,5 +1,4 @@ <?php -// $Id: views-view.tpl.php,v 1.13.4.4 2010/07/04 10:04:51 dereine Exp $ /** * @file views-view.tpl.php * Main view template @@ -33,6 +32,11 @@ <?php if ($admin_links): ?> <?php print $admin_links; ?> <?php endif; ?> + <?php print render($title_prefix); ?> + <?php if ($title): ?> + <?php print $title; ?> + <?php endif; ?> + <?php print render($title_suffix); ?> <?php if ($header): ?> <div class="view-header"> <?php print $header; ?> diff --git a/sites/all/modules/views/views.info b/sites/all/modules/views/views.info index 5ff9437224a03d07fd53a8664f8f447887476496..90a983a5ae0c867c73ac36e5dbd0137a30435f91 100644 --- a/sites/all/modules/views/views.info +++ b/sites/all/modules/views/views.info @@ -1,14 +1,17 @@ -; $Id: views.info,v 1.7.6.60 2011/01/05 21:34:52 dereine Exp $ name = Views description = Create customized lists and queries from your database. package = Views core = 7.x php = 5.2 -files[] = views.module + +; Always available CSS +stylesheets[all][] = css/views.css + dependencies[] = ctools ; Handlers files[] = handlers/views_handler_area.inc files[] = handlers/views_handler_area_text.inc +files[] = handlers/views_handler_area_view.inc files[] = handlers/views_handler_argument.inc files[] = handlers/views_handler_argument_date.inc files[] = handlers/views_handler_argument_formula.inc @@ -27,6 +30,8 @@ files[] = handlers/views_handler_field_markup.inc files[] = handlers/views_handler_field_math.inc 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_url.inc files[] = handlers/views_handler_filter.inc files[] = handlers/views_handler_filter_group_by_numeric.inc @@ -49,7 +54,6 @@ files[] = handlers/views_handler_sort_random.inc files[] = includes/base.inc files[] = includes/handlers.inc files[] = includes/plugins.inc -files[] = includes/tabs.inc files[] = includes/view.inc ; Modules files[] = modules/aggregator/views_handler_argument_aggregator_fid.inc @@ -150,6 +154,7 @@ files[] = modules/taxonomy/views_handler_relationship_node_term_data.inc files[] = modules/taxonomy/views_plugin_argument_validate_taxonomy_term.inc files[] = modules/taxonomy/views_plugin_argument_default_taxonomy_tid.inc ;files[] = modules/translation/views_handler_argument_node_language.inc +files[] = modules/system/views_handler_filter_system_type.inc files[] = modules/translation/views_handler_argument_node_tnid.inc files[] = modules/translation/views_handler_field_node_language.inc files[] = modules/translation/views_handler_field_node_link_translate.inc @@ -166,7 +171,7 @@ files[] = modules/user/views_handler_argument_users_roles_rid.inc files[] = modules/user/views_handler_field_user.inc files[] = modules/user/views_handler_field_user_language.inc files[] = modules/user/views_handler_field_user_link.inc -files[] = modules/user/views_handler_field_user_link_delete.inc +files[] = modules/user/views_handler_field_user_link_cancel.inc files[] = modules/user/views_handler_field_user_link_edit.inc files[] = modules/user/views_handler_field_user_mail.inc files[] = modules/user/views_handler_field_user_name.inc @@ -259,14 +264,17 @@ files[] = tests/views_pager.test files[] = tests/views_plugin_localization_test.inc files[] = tests/views_translatable.test files[] = tests/views_query.test +files[] = tests/views_upgrade.test files[] = tests/views_test.views_default.inc files[] = tests/user/views_user_argument_default.test files[] = tests/user/views_user_argument_validate.test files[] = tests/views_cache.test +files[] = tests/views_view.test +files[] = tests/views_ui.test -; Information added by drupal.org packaging script on 2011-01-06 -version = "7.x-3.0-alpha1" +; Information added by drupal.org packaging script on 2011-03-28 +version = "7.x-3.0-beta3" core = "7.x" project = "views" -datestamp = "1294276880" +datestamp = "1301301970" diff --git a/sites/all/modules/views/views.install b/sites/all/modules/views/views.install index aad5092e861b2d8de71d0ec1cbeea5f9fcde9b00..a999c7309e44c72df9e137a3306b76d96d47abfb 100644 --- a/sites/all/modules/views/views.install +++ b/sites/all/modules/views/views.install @@ -1,5 +1,4 @@ <?php -// $Id: views.install,v 1.50.4.12 2011/01/01 23:51:28 dereine Exp $ /** * @file views.install * Contains install and update functions for Views. @@ -89,6 +88,30 @@ function views_schema($caller_function = FALSE) { function views_schema_6000() { $schema['views_view'] = array( 'description' => 'Stores the general data for a view.', + 'export' => array( + 'identifier' => 'view', + 'bulk export' => TRUE, + 'primary key' => 'vid', + 'default hook' => 'views_default_views', + 'admin_title' => 'human_name', + 'admin_description' => 'description', + 'api' => array( + 'owner' => 'views', + 'api' => 'views_default', + 'minimum_version' => '2', + 'current_version' => '3.0', + ), + 'object' => 'view', + // the callback to load the displays + 'subrecords callback' => 'views_load_display_records', + // the variable that holds enabled/disabled status + 'status' => 'views_defaults', + // CRUD callbacks + 'create callback' => 'views_new_view', + 'save callback' => 'views_save_view', + 'delete callback' => 'views_delete_view', + 'export callback' => 'views_export_view', + ), 'fields' => array( 'vid' => array( 'type' => 'serial', @@ -500,7 +523,7 @@ function views_update_6012() { ->condition('module', 'views') ->condition('delta', db_like('-exp-') . '%', 'LIKE') ->fields(array('cache' => DRUPAL_NO_CACHE)); - + return $ret; } @@ -560,3 +583,30 @@ function views_update_6014() { return $ret; } +/** + * Rename some system variables. + */ +function views_update_7000() { + // Views now lets users turn off query details on live preview. + $query_on_top = variable_get('views_ui_query_on_top'); + if (isset($query_on_top)) { + variable_set('views_ui_show_sql_query', TRUE); + if ($query_on_top) { + variable_set('views_ui_show_sql_query_where', 'above'); + } + else { + variable_set('views_ui_show_sql_query_where', 'below'); + } + variable_del('views_ui_query_on_top'); + } + + // Rename the views_hide_help_message variable from negative to positive. + $hide_help = variable_get('views_hide_help_message'); + if (isset($hide_help)) { + variable_set('views_ui_show_advanced_help_warning', !$hide_help); + variable_del('views_hide_help_message'); + } + + // Rename the unused views_no_hover_links variable. + variable_del('views_no_hover_links'); +} diff --git a/sites/all/modules/views/views.module b/sites/all/modules/views/views.module index c943a3f7197e8d21fa262dc45a2ceecadfbc6682..5b283f3fe72e43a5aeeca37c4ccfd77bbac4c0c9 100644 --- a/sites/all/modules/views/views.module +++ b/sites/all/modules/views/views.module @@ -1,5 +1,4 @@ <?php -// $Id: views.module,v 1.341.4.53 2011/01/06 00:37:05 dereine Exp $ /** * @file * Primarily Drupal hooks and global API functions to manipulate views. @@ -23,13 +22,6 @@ function views_api_minimum_version() { return '2'; } -/** - * Implement hook_init(). - */ -function views_init() { - drupal_add_css(drupal_get_path('module', 'views') .'/css/views.css'); -} - /** * Implement hook_theme(). Register views theming functions. */ @@ -50,7 +42,10 @@ function views_theme($existing, $type, $theme, $path) { ); $arguments = array( - 'display' => array('view' => NULL), + // For displays, we pass in a dummy array as the first parameter, since + // $view is an object but the core contextual_preprocess() function only + // attaches contextual links when the primary theme argument is an array. + 'display' => array('view_array' => array(), 'view' => NULL), 'style' => array('view' => NULL, 'options' => NULL, 'rows' => NULL, 'title' => NULL), 'row' => array('view' => NULL, 'options' => NULL, 'row' => NULL, 'field_alias' => NULL), ); @@ -239,7 +234,7 @@ function views_permission() { 'description' => t('Access the views administration pages.'), ), 'access all views' => array( - 'title' => t('Access all views'), + 'title' => t('Bypass views access control'), 'description' => t('Bypass access control when accessing views.'), ), ); @@ -406,7 +401,7 @@ function views_page() { $name = array_shift($args); $display_id = array_shift($args); - // Load the view + // Load the view and render it. if ($view = views_get_view($name)) { return $view->execute_display($display_id, $args); } @@ -415,6 +410,58 @@ function views_page() { return drupal_not_found(); } +/** + * Implements hook_page_alter(). + */ +function views_page_alter(&$page) { + // If the main content of this page contains a view, attach its contextual + // links to the overall page array. This allows them to be rendered directly + // next to the page title. + $view = views_get_page_view(); + if (!empty($view)) { + views_add_contextual_links($page, 'page', $view, $view->current_display); + } +} + +/** + * Implements MODULE_preprocess_HOOK(). + */ +function views_preprocess_html(&$variables) { + // If the page contains a view as its main content, contextual links may have + // been attached to the page as a whole; for example, by views_page_alter(). + // This allows them to be associated with the page and rendered by default + // next to the page title (which we want). However, it also causes the + // Contextual Links module to treat the wrapper for the entire page (i.e., + // the <body> tag) as the HTML element that these contextual links are + // associated with. This we don't want; for better visual highlighting, we + // prefer a smaller region to be chosen. The region we prefer differs from + // theme to theme and depends on the details of the theme's markup in + // page.tpl.php, so we can only find it using JavaScript. We therefore remove + // the "contextual-links-region" class from the <body> tag here and add + // JavaScript that will insert it back in the correct place. + if (!empty($variables['page']['#views_contextual_links_info'])) { + $key = array_search('contextual-links-region', $variables['classes_array']); + if ($key !== FALSE) { + unset($variables['classes_array'][$key]); + // Add the JavaScript, with a group and weight such that it will run + // before modules/contextual/contextual.js. + drupal_add_js(drupal_get_path('module', 'views') . '/js/views-contextual.js', array('group' => JS_LIBRARY, 'weight' => -1)); + } + } +} + +/** + * Implements hook_contextual_links_view_alter(). + */ +function views_contextual_links_view_alter(&$element, $items) { + // If we are rendering views-related contextual links attached to the overall + // page array, add a class to the list of contextual links. This will be used + // by the JavaScript added in views_preprocess_html(). + if (!empty($element['#element']['#views_contextual_links_info']) && !empty($element['#element']['#type']) && $element['#element']['#type'] == 'page') { + $element['#attributes']['class'][] = 'views-contextual-links-page'; + } +} + /** * Implement hook_block_info(). */ @@ -508,6 +555,9 @@ function views_block_view($delta) { $view->set_display($display_id); if (isset($view->display_handler)) { $output = $view->display_handler->view_special_blocks($type); + // Before returning the block output, convert it to a renderable + // array with contextual links. + views_add_block_contextual_links($output, $view, $display_id); $view->destroy(); return $output; } @@ -521,6 +571,9 @@ function views_block_view($delta) { if ($view = views_get_view($name)) { if ($view->access($display_id)) { $output = $view->execute_display($display_id); + // Before returning the block output, convert it to a renderable array + // with contextual links. + views_add_block_contextual_links($output, $view, $display_id); $view->destroy(); return $output; } @@ -528,6 +581,145 @@ function views_block_view($delta) { } } +/** + * Converts Views block content to a renderable array with contextual links. + * + * @param $block + * An array representing the block, with the same structure as the return + * value of hook_block_view(). This will be modified so as to force + * $block['content'] to be a renderable array, containing the optional + * '#contextual_links' property (if there are any contextual links associated + * with the block). + * @param $view + * The view that was used to generate the block content. + * @param $display_id + * The ID of the display within the view that was used to generate the block + * content. + */ +function views_add_block_contextual_links(&$block, $view, $display_id) { + // Do not add contextual links to an empty block. + if (!empty($block['content'])) { + // Contextual links only work on blocks whose content is a renderable + // array, so if the block contains a string of already-rendered markup, + // convert it to an array. + if (is_string($block['content'])) { + $block['content'] = array('#markup' => $block['content']); + } + // Add the contextual links. + views_add_contextual_links($block['content'], 'block', $view, $display_id); + } +} + +/** + * Adds contextual links associated with a view display to a renderable array. + * + * This function should be called when a view is being rendered in a particular + * location and you want to attach the appropriate contextual links (e.g., + * links for editing the view) to it. + * + * The function operates by checking the view's display plugin to see if it has + * defined any contextual links that are intended to be displayed in the + * requested location; if so, it attaches them. The contextual links intended + * for a particular location are defined by the 'contextual links' and + * 'contextual links locations' properties in hook_views_plugins() and + * hook_views_plugins_alter(); as a result, these hook implementations have + * full control over where and how contextual links are rendered for each + * display. + * + * In addition to attaching the contextual links to the passed-in array (via + * the standard #contextual_links property), this function also attaches + * additional information via the #views_contextual_links_info property. This + * stores an array whose keys are the names of each module that provided + * views-related contextual links (same as the keys of the #contextual_links + * array itself) and whose values are themselves arrays whose keys ('location', + * 'view_name', and 'view_display_id') store the location, name of the view, + * and display ID that were passed in to this function. This allows you to + * access information about the contextual links and how they were generated in + * a variety of contexts where you might be manipulating the renderable array + * later on (for example, alter hooks which run later during the same page + * request). + * + * @param $render_element + * The renderable array to which contextual links will be added. This array + * should be suitable for passing in to drupal_render() and will normally + * contain a representation of the view display whose contextual links are + * being requested. + * @param $location + * The location in which the calling function intends to render the view and + * its contextual links. The core system supports three options for this + * parameter: + * - 'block': Used when rendering a block which contains a view. This + * retrieves any contextual links intended to be attached to the block + * itself. + * - 'page': Used when rendering the main content of a page which contains a + * view. This retrieves any contextual links intended to be attached to the + * page itself (for example, links which are displayed directly next to the + * page title). + * - 'view': Used when rendering the view itself, in any context. This + * retrieves any contextual links intended to be attached directly to the + * view. + * If you are rendering a view and its contextual links in another location, + * you can pass in a different value for this parameter. However, you will + * also need to use hook_views_plugins() or hook_views_plugins_alter() to + * declare, via the 'contextual links locations' array key, which view + * displays support having their contextual links rendered in the location + * you have defined. + * @param $view + * The view whose contextual links will be added. + * @param $display_id + * The ID of the display within $view whose contextual links will be added. + * + * @see hook_views_plugins() + * @see views_block_view() + * @see views_page_alter() + * @see template_preprocess_views_view() + */ +function views_add_contextual_links(&$render_element, $location, $view, $display_id) { + // Do not do anything if the view is configured to hide its administrative + // links. + if (empty($view->hide_admin_links)) { + // Also do not do anything if the display plugin has not defined any + // contextual links that are intended to be displayed in the requested + // location. + $plugin = views_fetch_plugin_data('display', $view->display[$display_id]->display_plugin); + // If contextual links locations are empty provide a sane default. + if (empty($plugin['contextual links locations'])) { + $plugin['contextual links locations'] = array('view'); + } + $has_links = !empty($plugin['contextual links']) && !empty($plugin['contextual links locations']); + if ($has_links && in_array($location, $plugin['contextual links locations'])) { + foreach ($plugin['contextual links'] as $module => $link) { + $args = array(); + $valid = TRUE; + if (!empty($link['argument properties'])) { + foreach ($link['argument properties'] as $property) { + // If the plugin is trying to create an invalid contextual link + // (for example, "path/to/{$view->property}", where $view->property + // does not exist), we cannot construct the link, so we skip it. + if (!property_exists($view, $property)) { + $valid = FALSE; + break; + } + else { + $args[] = $view->{$property}; + } + } + } + // If the link was valid, attach information about it to the renderable + // array. + if ($valid) { + $render_element['#contextual_links'][$module] = array($link['parent path'], $args); + $render_element['#views_contextual_links_info'][$module] = array( + 'location' => $location, + 'view_name' => $view->name, + 'view_display_id' => $display_id, + ); + } + } + } + } +} + /** * Implements hook_flush_caches(). */ @@ -697,34 +889,29 @@ function views_include($file) { /** * Load views files on behalf of modules. */ -function views_module_include($file, $reset = FALSE) { - foreach (views_get_module_apis($reset) as $module => $info) { - if (file_exists(DRUPAL_ROOT . "/$info[path]/$module.$file")) { - require_once DRUPAL_ROOT . "/$info[path]/$module.$file"; +function views_module_include($api, $reset = FALSE) { + if ($reset) { + $cache = &drupal_static('ctools_plugin_api_info'); + if (isset($cache['views']['views'])) { + unset($cache['views']['views']); } } + ctools_include('plugins'); + return ctools_plugin_api_include('views', $api, views_api_minimum_version(), views_api_version()); } /** * Get a list of modules that support the current views API. */ -function views_get_module_apis($reset = FALSE) { - static $cache = NULL; - if (!isset($cache) || $reset) { - $cache = array(); - foreach (module_implements('views_api') as $module) { - $info = module_invoke($module, 'views_api'); - if (version_compare($info['api'], views_api_minimum_version(), '>=') && - version_compare($info['api'], views_api_version(), '<=')) { - if (!isset($info['path'])) { - $info['path'] = drupal_get_path('module', $module); - } - $cache[$module] = $info; - } +function views_get_module_apis($api = 'views', $reset = FALSE) { + if ($reset) { + $cache = &drupal_static('ctools_plugin_api_info'); + if (isset($cache['views']['views'])) { + unset($cache['views']['views']); } } - - return $cache; + ctools_include('plugins'); + return ctools_plugin_api_info('views', $api, views_api_minimum_version(), views_api_version()); } /** @@ -773,26 +960,7 @@ function views_include_handlers($reset = FALSE) { views_include('handlers'); views_include('cache'); views_include('plugins'); - _views_include_handlers(); - $finished = TRUE; -} - -/** - * Load default views files on behalf of modules. - */ -function views_include_default_views($reset = FALSE) { - static $finished = FALSE; - // Ensure this only gets run once. - if ($finished && !$reset) { - return; - } - - // Default views hooks may be in the normal handler file, - // or in a separate views_default file at the discretion of - // the module author. - views_include_handlers($reset); - - _views_include_default_views($reset); + views_module_include('views', $reset); $finished = TRUE; } @@ -817,10 +985,49 @@ function views_include_default_views($reset = FALSE) { * An instance of a handler object. May be views_handler_broken. */ function views_get_handler($table, $field, $key, $override = NULL) { - $data = views_fetch_data($table); + static $recursion_protection = array(); + + $data = views_fetch_data($table, FALSE); $handler = NULL; - if (isset($data[$field][$key])) { + // Support old views_data entries conversion. + + // Support conversion on table level. + if (isset($data['moved to'])) { + $moved = array($data['moved to'], $field); + } + // Support conversion on datafield level. + if (isset($data[$field]['moved to'])) { + $moved = $data[$field]['moved to']; + } + // Support conversion on handler level. + if (isset($data[$field][$key]['moved to'])) { + $moved = $data[$field][$key]['moved to']; + } + + if (isset($data[$field][$key]) || !empty($moved)) { + if (!empty($moved)) { + list($moved_table, $moved_field) = $moved; + if (!empty($recursion_protection[$moved_table][$moved_field])) { + // recursion detected! + return NULL; + } + + $recursion_protection[$moved_table][$moved_field] = TRUE; + $handler = views_get_handler($moved_table, $moved_field, $key, $override); + $recursion_protection = array(); + if ($handler) { + // store these values so we know what we were originally called. + $handler->original_table = $table; + $handler->original_field = $field; + if (empty($handler->actual_table)) { + $handler->actual_table = $moved_table; + $handler->actual_field = $moved_field; + } + } + return $handler; + } + // Set up a default handler: if (empty($data[$field][$key]['handler'])) { $data[$field][$key]['handler'] = 'views_handler_' . $key; @@ -830,7 +1037,7 @@ function views_get_handler($table, $field, $key, $override = NULL) { $data[$field][$key]['override handler'] = $override; } - $handler = _views_prepare_handler($data[$field][$key], $data, $field); + $handler = _views_prepare_handler($data[$field][$key], $data, $field, $key); } if ($handler) { @@ -838,22 +1045,22 @@ function views_get_handler($table, $field, $key, $override = NULL) { } // DEBUG -- identify missing handlers - debug("Missing handler: $table $field $key"); + vpr("Missing handler: $table $field $key"); $broken = array( 'title' => t('Broken handler @table.@field', array('@table' => $table, '@field' => $field)), 'handler' => 'views_handler_' . $key . '_broken', 'table' => $table, 'field' => $field, ); - return _views_create_handler($broken); + return _views_create_handler($broken, 'handler', $key); } /** * Fetch Views' data from the cache */ -function views_fetch_data($table = NULL, $reset = FALSE) { +function views_fetch_data($table = NULL, $move = TRUE, $reset = FALSE) { views_include('cache'); - return _views_fetch_data($table, $reset); + return _views_fetch_data($table, $move, $reset); } // ----------------------------------------------------------------------- @@ -867,6 +1074,43 @@ function views_fetch_plugin_data($type = NULL, $plugin = NULL, $reset = FALSE) { return _views_fetch_plugin_data($type, $plugin, $reset); } +/** + * Fetch a list of all base tables available + * + * @param $type + * Either 'display', 'style' or 'row' + * @param $key + * For style plugins, this is an optional type to restrict to. May be 'normal', + * 'summary', 'feed' or others based on the neds of the display. + * @param $base + * An array of possible base tables. + * + * @return + * A keyed array of in the form of 'base_table' => 'Description'. + */ +function views_fetch_plugin_names($type, $key = NULL, $base = array()) { + $data = views_fetch_plugin_data(); + + $plugins[$type] = array(); + + foreach ($data[$type] as $id => $plugin) { + // Skip plugins that don't conform to our key. + if ($key && (empty($plugin['type']) || $plugin['type'] != $key)) { + continue; + } + if (empty($plugin['no ui']) && (empty($base) || empty($plugin['base']) || array_intersect($base, $plugin['base']))) { + $plugins[$type][$id] = $plugin['title']; + } + } + + if (!empty($plugins[$type])) { + asort($plugins[$type]); + return $plugins[$type]; + } + // fall-through + return array(); +} + /** * Get a handler for a plugin */ @@ -882,34 +1126,26 @@ function views_get_plugin($type, $plugin, $reset = FALSE) { // Views database functions /** - * Get a view from the default views defined by modules. + * Get all view templates. * - * Default views are cached per-language. This function will rescan the - * default_views hook if necessary. - * - * @param $view_name - * The name of the view to load. - * @return - * A view object or NULL if it is not available. + * Templates are special in-code views that are never active, but exist only + * to be cloned into real views as though they were templates. */ -function &views_get_default_view($view_name, $reset = FALSE) { - $null = NULL; - - // Attempt to load individually cached view from cache. - views_include('cache'); - if (!$reset) { - $data = views_cache_get("views_default:{$view_name}", TRUE); - if (isset($data->data) && is_object($data->data)) { - return $data->data; +function views_get_all_templates() { + $templates = array(); + $modules = views_module_include('views_template'); + + foreach ($modules as $module => $info) { + $function = $module . '_views_templates'; + if (function_exists($function)) { + $new = $function(); + if ($new && is_array($new)) { + $templates = array_merge($new, $templates); + } } } - // Otherwise, allow entire cache to be rebuilt. - $cache = views_discover_default_views($reset); - if (isset($cache[$view_name])) { - return $cache[$view_name]; - } - return $null; + return $templates; } /** @@ -928,21 +1164,6 @@ function views_new_view() { return $view; } -/** - * Scan all modules for default views and rebuild the default views cache. - * - * @return An associative array of all known default views. - */ -function views_discover_default_views($reset = FALSE) { - static $cache = array(); - - if (empty($cache) || $reset) { - views_include('cache'); - $cache = _views_discover_default_views($reset); - } - return $cache; -} - /** * Return a list of all views and display IDs that have a particular * setting in their display's plugin settings. @@ -981,7 +1202,7 @@ function views_get_applicable_views($type) { // This view uses hook menu. Clone it so that different handlers // don't trip over each other, and add it to the list. $v = $view->clone_view(); - if ($v->set_display($id)) { + if ($v->set_display($id) && $v->display_handler->get_option('enabled')) { $result[] = array($v, $id); } // In PHP 4.4.7 and presumably earlier, if we do not unset $v @@ -1001,36 +1222,38 @@ function views_get_applicable_views($type) { * If TRUE, reset the static cache forcing views to be reloaded. */ function views_get_all_views($reset = FALSE) { - static $views = array(); - - if (empty($views) || $reset) { - $views = array(); - - // First, get all applicable views. - views_include('view'); - $views = view::load_views(); + ctools_include('export'); + return ctools_export_crud_load_all('views_view', $reset); +} - // Get all default views. - $status = variable_get('views_defaults', array()); +/** + * Returns an array of all enabled views, as fully loaded $view objects. + */ +function views_get_enabled_views() { + $views = views_get_all_views(); + return array_filter($views, 'views_view_is_enabled'); +} - foreach (views_discover_default_views($reset) as $view) { - // Determine if default view is enabled or disabled. - if (isset($status[$view->name])) { - $view->disabled = $status[$view->name]; - } +/** + * Returns an array of all disabled views, as fully loaded $view objects. + */ +function views_get_disabled_views() { + $views = views_get_all_views(); + return array_filter($views, 'views_view_is_disabled'); +} - // If overridden, also say so. - if (!empty($views[$view->name])) { - $views[$view->name]->type = t('Overridden'); - } - else { - $view->type = t('Default'); - $views[$view->name] = $view; - } - } +/** + * Returns TRUE if a view is enabled, FALSE otherwise. + */ +function views_view_is_enabled($view) { + return empty($view->disabled); +} - } - return $views; +/** + * Returns TRUE if a view is disabled, FALSE otherwise. + */ +function views_view_is_disabled($view) { + return !empty($view->disabled); } /** @@ -1049,29 +1272,86 @@ function views_get_all_views($reset = FALSE) { * a fresh one. */ function views_get_view($name, $reset = FALSE) { - views_include('view'); - $view = view::load($name, $reset); - $default_view = views_get_default_view($name, $reset); + if ($reset) { + $cache = &drupal_static('ctools_export_load_object'); + if (isset($cache['views_view'][$name])) { + unset($cache['views_view'][$name]); + } + } - // The view does not exist. - if (empty($view) && empty($default_view)) { - return; + ctools_include('export'); + $view = ctools_export_crud_load('views_view', $name); + if ($view) { + // When views are converted automatically the base_table should be renamed + // to have a working query. + $data = views_fetch_data($view->base_table, FALSE); + if (isset($data['moved to'])) { + $view->base_table = $data['moved to']; + } + return $view->clone_view(); } - // The view is defined in code. - elseif (empty($view) && !empty($default_view)) { - $status = variable_get('views_defaults', array()); - if (isset($status[$default_view->name])) { - $default_view->disabled = $status[$default_view->name]; +} + +/** + * Export callback to load the view subrecords, which are the displays. + */ +function views_load_display_records(&$views) { + // Get vids from the views. + $names = array(); + foreach ($views as $view) { + if (empty($view->display)) { + $names[$view->vid] = $view->name; } - $default_view->type = t('Default'); - return $default_view->clone_view(); } - // The view is overriden/defined in the database. - elseif (!empty($view) && !empty($default_view)) { - $view->type = t('Overridden'); + + if (empty($names)) { + return; } - return $view->clone_view(); + foreach (view::db_objects() as $key) { + $object_name = "views_$key"; + $result = db_query("SELECT * FROM {{$object_name}} WHERE vid IN (:vids) ORDER BY vid, position", + array(':vids' => array_keys($names))); + + 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 = &$views[$names[$object->vid]]->$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; + } + } + } +} + +/** + * Export CRUD callback to save a view. + */ +function views_save_view(&$view) { + return $view->save(); +} + +/** + * Export CRUD callback to delete a view. + */ +function views_delete_view(&$view) { + return $view->delete(TRUE); +} + +/** + * Export CRUD callback to export a view. + */ +function views_export_view(&$view, $indent = '') { + return $view->export($indent); } // ------------------------------------------------------------------ @@ -1089,12 +1369,15 @@ function views_debug($message) { $output = var_export($message, TRUE); } if (variable_get('views_devel_region', 'footer') != 'watchdog') { - drupal_set_content(variable_get('views_devel_region', 'footer'), '<pre>' . $output . '</pre>'); + drupal_add_region_content(variable_get('views_devel_region', 'footer'), '<pre>' . $output . '</pre>'); } else { watchdog('views_logging', '<pre>' . $output . '</pre>'); } } + elseif (isset($GLOBALS['drupal_test_info'])) { + debug($message); + } } /** @@ -1211,6 +1494,18 @@ function views_exposed_form($form, &$form_state) { return $form; } +/** + * Implement hook_form_alter for the exposed form. + * + * Since the exposed form is a GET form, we don't want it to send a wide + * variety of information. + */ +function views_form_views_exposed_form_alter(&$form, &$form_state) { + $form['form_build_id']['#access'] = FALSE; + $form['form_token']['#access'] = FALSE; + $form['form_id']['#access'] = FALSE; +} + /** * Validate handler for exposed filters */ @@ -1392,7 +1687,7 @@ function views_embed_view($name, $display_id = 'default') { * The name of the view to retrieve the data from. * @param string $display_id * The display id. On the edit page for the view in question, you'll find -* a list of displays at the left side of the control area. "Defaults" +* a list of displays at the left side of the control area. "Master" * will be at the top of that list. Hover your cursor over the name of the * display you want to use. An URL will appear in the status bar of your * browser. This is usually at the bottom of the window, in the chrome. @@ -1568,3 +1863,93 @@ function views_trim_text($alter, $value) { return $value; } + +/** + * Report to CTools that we use hook_views_api instead of hook_ctools_plugin_api() + */ +function views_ctools_plugin_api_hook_name() { + return 'views_api'; +} + +// Declare API compatibility on behalf of core modules: + +/** + * Implements hook_views_api(). + * + * This one is used as the base to reduce errors when updating. + */ +function views_views_api() { + return array( + // in your modules do *not* use views_api_version()!!! + 'api' => views_api_version(), + 'path' => drupal_get_path('module', 'views') . '/modules', + ); +} + +if (!function_exists('aggregator_views_api')) { + function aggregator_views_api() { return views_views_api(); } +} + +if (!function_exists('book_views_api')) { + function book_views_api() { return views_views_api(); } +} + +if (!function_exists('comment_views_api')) { + function comment_views_api() { return views_views_api(); } +} + +if (!function_exists('locale_views_api')) { + function locale_views_api() { return views_views_api(); } +} + +if (!function_exists('field_views_api')) { + function field_views_api() { return views_views_api(); } +} + +if (!function_exists('filter_views_api')) { + function filter_views_api() { return views_views_api(); } +} + +if (!function_exists('node_views_api')) { + function node_views_api() { return views_views_api(); } +} + +if (!function_exists('poll_views_api')) { + function poll_views_api() { return views_views_api(); } +} + +if (!function_exists('profile_views_api')) { + function profile_views_api() { return views_views_api(); } +} + +if (!function_exists('search_views_api')) { + function search_views_api() { return views_views_api(); } +} + +if (!function_exists('statistics_views_api')) { + function statistics_views_api() { return views_views_api(); } +} + +if (!function_exists('system_views_api')) { + function system_views_api() { return views_views_api(); } +} + +if (!function_exists('taxonomy_views_api')) { + function taxonomy_views_api() { return views_views_api(); } +} + +if (!function_exists('translation_views_api')) { + function translation_views_api() { return views_views_api(); } +} + +if (!function_exists('upload_views_api')) { + function upload_views_api() { return views_views_api(); } +} + +if (!function_exists('user_views_api')) { + function user_views_api() { return views_views_api(); } +} + +if (!function_exists('contact_views_api')) { + function contact_views_api() { return views_views_api(); } +} diff --git a/sites/all/modules/views/views_export/views_export.css b/sites/all/modules/views/views_export/views_export.css index 87178e4cfc9d6548b58b0922f4714378de875a51..4887ad36e2a3b77a34cc554ccdb1bec4e1c447f1 100644 --- a/sites/all/modules/views/views_export/views_export.css +++ b/sites/all/modules/views/views_export/views_export.css @@ -1,4 +1,3 @@ -/* $Id: views_export.css,v 1.1 2008/06/12 16:17:25 merlinofchaos Exp $ */ div.export-container table input, div.export-container table th, diff --git a/sites/all/modules/views/views_export/views_export.info b/sites/all/modules/views/views_export/views_export.info index d1cc4934dfd84be005c4b1e9c379cf7e9d2d8051..34175876331e8a4aba8f94ae8b9fb1c74c7cd5a8 100644 --- a/sites/all/modules/views/views_export/views_export.info +++ b/sites/all/modules/views/views_export/views_export.info @@ -1,4 +1,3 @@ -; $Id: views_export.info,v 1.1.6.2 2010/12/23 17:52:53 dereine Exp $ name = Views exporter description = Allows exporting multiple views at once. @@ -6,9 +5,9 @@ package = "Views" dependencies[] = views core = 7.x -; Information added by drupal.org packaging script on 2011-01-06 -version = "7.x-3.0-alpha1" +; Information added by drupal.org packaging script on 2011-03-28 +version = "7.x-3.0-beta3" core = "7.x" project = "views" -datestamp = "1294276880" +datestamp = "1301301970" diff --git a/sites/all/modules/views/views_export/views_export.module b/sites/all/modules/views/views_export/views_export.module index e5ce65e8c1c9fe23f3a0736b388729f55a6046d7..fa1769398bfceefbd156dde48ea9c5f6c1fb95f8 100644 --- a/sites/all/modules/views/views_export/views_export.module +++ b/sites/all/modules/views/views_export/views_export.module @@ -1,5 +1,4 @@ <?php -// $Id: views_export.module,v 1.9.4.5 2010/12/01 20:29:24 dereine Exp $ /** * @file views_export.module @@ -209,9 +208,7 @@ function views_export_export_form_submit(&$form, &$form_state) { $types = system_element_info(); - $info = '; $Id: views_export.module,v 1.9.4.5 2010/12/01 20:29:24 dereine Exp $'."\n"; - $info .= "\n"; - $info .= strtr("name = @module Export Module\n", array('@module' => $form_state['values']['name'])); + $info = strtr("name = @module Export Module\n", array('@module' => $form_state['values']['name'])); $info .= strtr("description = Exports some views of @module\n", array('@module' => $form_state['values']['name'])); $info .= "dependencies[] = views\n"; $info .= "core = 6.x\n"; diff --git a/sites/all/modules/views/views_ui.info b/sites/all/modules/views/views_ui.info index c57b35bebe07e19c82dcc2d1d382438ba22466db..ff1b49c2d0db8bff11018f318bbbfd88b2b2fcda 100644 --- a/sites/all/modules/views/views_ui.info +++ b/sites/all/modules/views/views_ui.info @@ -1,4 +1,3 @@ -; $Id: views_ui.info,v 1.10.6.2 2010/12/24 08:29:52 dereine Exp $ name = Views UI description = Administrative interface to views. Without this module, you cannot create or edit your views. package = Views @@ -6,9 +5,11 @@ core = 7.x configure = admin/structure/views dependencies[] = views files[] = views_ui.module -; Information added by drupal.org packaging script on 2011-01-06 -version = "7.x-3.0-alpha1" +files[] = plugins/views_wizard/views_ui_base_views_wizard.class.php + +; Information added by drupal.org packaging script on 2011-03-28 +version = "7.x-3.0-beta3" core = "7.x" project = "views" -datestamp = "1294276880" +datestamp = "1301301970" diff --git a/sites/all/modules/views/views_ui.module b/sites/all/modules/views/views_ui.module index beb3a50dc1e1567bae2df2d4b7e35a426a69c8f0..41b6d0488c2230209a48d2adea314f5d5ff28c4f 100644 --- a/sites/all/modules/views/views_ui.module +++ b/sites/all/modules/views/views_ui.module @@ -1,211 +1,201 @@ <?php -// $Id: views_ui.module,v 1.109.6.18 2010/12/24 13:42:00 dereine Exp $ /** * @file views_ui.module * Provide structure for the administrative interface to Views. */ -/* +/** * Implements hook_menu(). */ function views_ui_menu() { $items = array(); - // Minor code reduction technique + //module_load_include('inc', 'views_ui', 'includes/admin'); + + // Drupal core loads the module file when uninstall a module. So views.module is not loaded. + // There is a core bug filled, remove it once the bug is fixed. + // @see http://drupal.org/node/1029606 + if (!module_exists('views')) { + return; + } + + // Minor code reduction technique. $base = array( 'access callback' => 'user_access', 'access arguments' => array('administer views'), 'file' => 'includes/admin.inc', ); - $callback = $base + array('type' => MENU_CALLBACK); - - $convert = array('file' => 'includes/convert.inc') + $base; - - $items['admin/structure/views'] = $base + array( - 'title' => 'Views', - 'page callback' => 'views_ui_list_views', - 'description' => 'Views are customized lists of content on your system; they are highly configurable and give you control over how lists of content are presented.', - 'type' => MENU_NORMAL_ITEM - ); - $items['admin/structure/views/list'] = $base + array( - 'title' => 'List', - 'page callback' => 'views_ui_list_views', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => '-1' - ); - $items['admin/structure/views/add'] = $base + array( + // Top-level Views module pages (not tied to a particular View). + $items['admin/structure/views/add'] = array( 'title' => 'Add new view', 'page callback' => 'views_ui_add_page', 'type' => MENU_LOCAL_ACTION, - ); + ) + $base; + + // Top-level Views module pages (not tied to a particular View). + $items['admin/structure/views/add-template'] = array( + 'title' => 'Add view from template', + 'page callback' => 'views_ui_add_template_page', + // Don't show a local action link if there aren't any templates. + 'type' => views_get_all_templates() ? MENU_LOCAL_ACTION : MENU_VISIBLE_IN_BREADCRUMB, + ) + $base; + $items['admin/structure/views/import'] = array( - 'title' => 'Import view from code', + 'title' => 'Import', 'page callback' => 'drupal_get_form', 'page arguments' => array('views_ui_import_page'), 'access callback' => 'views_import_access', 'type' => MENU_LOCAL_ACTION, ) + $base; - $items['admin/structure/views/tools'] = $base + array( - 'title' => 'Tools', + + $items['admin/structure/views/settings'] = array( + 'title' => 'Settings', 'page callback' => 'drupal_get_form', - 'page arguments' => array('views_ui_admin_tools'), - 'type' => MENU_LOCAL_TASK - ); - $items['admin/structure/views/tools/basic'] = $base + array( + 'page arguments' => array('views_ui_admin_settings_basic'), + 'type' => MENU_LOCAL_TASK, + ) + $base; + $items['admin/structure/views/settings/basic'] = array( 'title' => 'Basic', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('views_ui_admin_tools'), - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - - $items['admin/structure/views/tools/convert'] = $convert + array( - 'title' => 'Convert', - 'description' => 'Convert stored Views 1 views.', - 'page callback' => 'views_ui_admin_convert', + 'page arguments' => array('views_ui_admin_settings_basic'), + 'type' => MENU_LOCAL_TASK, + ) + $base; + $items['admin/structure/views/settings/advanced'] = array( + 'title' => 'Advanced', + 'page arguments' => array('views_ui_admin_settings_advanced'), 'type' => MENU_LOCAL_TASK, 'weight' => 1, - ); - $items['admin/structure/views1/delete'] = $convert + array( - 'title' => 'Delete view', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('views_ui_delete1_confirm', 4), - 'type' => MENU_CALLBACK, - ); - $items['admin/structure/views1/convert'] = $convert + array( - 'title' => 'Convert view', - 'page callback' => 'views_ui_convert1', + ) + $base; + + // The primary Edit View page. Secondary tabs for each Display are added in + // views_ui_menu_local_tasks_alter(). + $items['admin/structure/views/view/%views_ui_cache'] = array( + 'title callback' => 'views_ui_edit_page_title', + 'title arguments' => array(4), + 'page callback' => 'views_ui_edit_page', 'page arguments' => array(4), + ) + $base; + $items['admin/structure/views/view/%views_ui_cache/edit'] = array( + 'title' => 'Edit view', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, + 'weight' => -10, + ) + $base; + $items['admin/structure/views/view/%views_ui_cache/edit/%/ajax'] = array( + 'page callback' => 'views_ui_ajax_get_form', + 'page arguments' => array('views_ui_edit_form', 4, 6), + 'delivery callback' => 'ajax_deliver', + 'theme callback' => 'ajax_base_page_theme', 'type' => MENU_CALLBACK, - ); + ) + $base; - $items['admin/structure/views/delete/%views_ui_cache'] = $callback + array( - 'title' => 'Delete view', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('views_ui_delete_confirm', 4), - ); - $items['admin/structure/views/break-lock/%views_ui_cache'] = $callback + array( - 'title' => 'Delete view', + // Additional pages for acting on a View. + $items['admin/structure/views/view/%views_ui_cache/analyze'] = array( + 'title' => 'Analyze', + 'page callback' => 'views_ui_analyze_view', + 'page arguments' => array(FALSE, 4), + 'type' => MENU_VISIBLE_IN_BREADCRUMB, + ) + $base; + + $items['admin/structure/views/view/%views_ui_cache/break-lock'] = array( + 'title' => 'Break lock', 'page callback' => 'drupal_get_form', 'page arguments' => array('views_ui_break_lock_confirm', 4), - ); - $items['admin/structure/views/export/%views_ui_cache'] = $callback + array( - 'page callback' => 'drupal_get_form', - 'page arguments' => array('views_ui_export_page', 4), - 'type' => MENU_LOCAL_TASK - ); - $items['admin/structure/views/clone/%views_ui_cache'] = $callback + array( - 'page callback' => 'views_ui_clone_page', - 'page arguments' => array(4), - 'type' => MENU_LOCAL_TASK - ); - $items['admin/structure/views/enable/%views_ui_default'] = $callback + array( - 'page callback' => 'views_ui_enable_page', - 'page arguments' => array(4), - ); - $items['admin/structure/views/disable/%views_ui_default'] = $callback + array( - 'page callback' => 'views_ui_disable_page', - 'page arguments' => array(4), - ); + 'type' => MENU_VISIBLE_IN_BREADCRUMB, + ) + $base; - // Many line items for editing a view. - $items['admin/structure/views/edit/%views_ui_cache'] = $base + array( - 'title' => 'Edit', - 'page callback' => 'views_ui_edit_page', - 'page arguments' => array(4), - 'type' => MENU_LOCAL_TASK - ); + // NoJS/AJAX callbacks that can use the default Views AJAX form system. + $items['admin/structure/views/nojs/%/%views_ui_cache'] = array( + 'page callback' => 'views_ui_ajax_form', + 'page arguments' => array(FALSE, 4, 5), + 'type' => MENU_CALLBACK, + ) + $base; + $items['admin/structure/views/ajax/%/%views_ui_cache'] = array( + 'page callback' => 'views_ui_ajax_form', + 'page arguments' => array(TRUE, 4, 5), + 'delivery callback' => 'ajax_deliver', + 'type' => MENU_CALLBACK, + ) + $base; + + // NoJS/AJAX callbacks that require custom page callbacks. $ajax_callbacks = array( - 'analyze' => 'views_ui_analyze_view', - 'add-display' => 'views_ui_add_display', + //'analyze' => 'views_ui_analyze_view', 'preview' => 'views_ui_preview', - 'reorder-displays' => 'views_ui_reorder_view', ); - foreach ($ajax_callbacks as $menu => $menu_callback) { - $items['admin/structure/views/nojs/' . $menu . '/%views_ui_cache'] = $callback + array( + $items['admin/structure/views/nojs/' . $menu . '/%views_ui_cache/%'] = array( 'page callback' => $menu_callback, - 'page arguments' => array(FALSE, 5), - ); - $items['admin/structure/views/ajax/' . $menu . '/%views_ui_cache'] = $callback + array( + 'page arguments' => array(5, 6), + ) + $base; + $items['admin/structure/views/ajax/' . $menu . '/%views_ui_cache/%'] = array( 'page callback' => $menu_callback, - 'page arguments' => array(TRUE, 5), - 'delivery callback' => 'views_ui_ajax_deliver', - ); + 'page arguments' => array(5, 6), + 'delivery callback' => 'ajax_deliver', + ) + $base; } - $items['admin/structure/views/nojs/human_name/%views_ui_cache'] = $callback + array( - 'page callback' => 'views_ui_edit_details', - 'page arguments' => array('human_name', FALSE, 5), - ); - $items['admin/structure/views/ajax/human_name/%views_ui_cache'] = $callback + array( - 'page callback' => 'views_ui_edit_details', - 'page arguments' => array('human_name', TRUE, 5), - 'delivery callback' => 'views_ui_ajax_deliver', - ); - $items['admin/structure/views/nojs/tag/%views_ui_cache'] = $callback + array( - 'page callback' => 'views_ui_edit_details', - 'page arguments' => array('tag', FALSE, 5), - ); - $items['admin/structure/views/ajax/tag/%views_ui_cache'] = $callback + array( - 'page callback' => 'views_ui_edit_details', - 'page arguments' => array('tag', TRUE, 5), - 'delivery callback' => 'views_ui_ajax_deliver', - ); - $items['admin/structure/views/nojs/description/%views_ui_cache'] = $callback + array( - 'page callback' => 'views_ui_edit_details', - 'page arguments' => array('description', FALSE, 5), - ); - $items['admin/structure/views/ajax/description/%views_ui_cache'] = $callback + array( - 'page callback' => 'views_ui_edit_details', - 'page arguments' => array('description', TRUE, 5), - 'delivery callback' => 'views_ui_ajax_deliver', - ); - - $items['admin/build/views/nojs/clone-display/%views_ui_cache'] = $callback + array( - 'page callback' => 'views_ui_clone_display', - 'page arguments' => array(FALSE, 5, 6), - ); - - $items['admin/build/views/ajax/clone-display/%views_ui_cache'] = $callback + array( - 'page callback' => 'views_ui_clone_display', - 'page arguments' => array(TRUE, 5, 6), - 'delivery callback' => 'views_ui_ajax_deliver', - ); - - $items['admin/structure/views/nojs/%/%views_ui_cache'] = $callback + array( - 'page callback' => 'views_ui_ajax_form', - 'page arguments' => array(FALSE, 4, 5), - ); - $items['admin/structure/views/ajax/%/%views_ui_cache'] = $callback + array( - 'page callback' => 'views_ui_ajax_form', - 'page arguments' => array(TRUE, 4, 5), - 'delivery callback' => 'views_ui_ajax_deliver', - ); - - // autocompletes for handlers and such - $items['admin/views/ajax/autocomplete/tag'] = $callback + array( + // Autocomplete callback for tagging a View. + // Views module uses admin/views/... instead of admin/structure/views/... for + // autocomplete paths, so be consistent with that. + // @todo Change to admin/structure/views/... when the change can be made to + // Views module as well. + $items['admin/views/ajax/autocomplete/tag'] = array( 'page callback' => 'views_ui_autocomplete_tag', - 'access arguments' => array('administer views'), 'type' => MENU_CALLBACK, - 'file' => 'includes/admin.inc', - ); + ) + $base; return $items; } -/* +/** + * Implements hook_menu_local_tasks_alter(). + * + * Adds secondary tabs for navigating across Displays when editing a View. Since + * each view contains its own set of displays, doing this here instead of in + * hook_menu() reduces bloat in the {menu_links} table, and avoids requiring a + * menu rebuild every time a display is added or removed. + */ +function views_ui_menu_local_tasks_alter(&$data, $router_item, $root_path) { + // @todo This is commented out until theming of secondary local tasks is + // fixed (see http://drupal.org/node/599706#comment-3620912). In the + // meantime, we add the tabs within views_ui_edit_form(). + /* + if ($root_path == 'admin/structure/views/view/%') { + module_load_include('inc', 'views_ui', 'includes/admin'); + $view = $router_item['page_arguments'][0]; + $tabs = views_ui_edit_page_display_tabs($view); + if ($active_display = arg(6) && isset($tabs[$active_display])) { + $tabs[$active_display]['#active'] = TRUE; + } + else { + // Set the first one to active. + foreach ($tabs as $id => $tab) { + if (!isset($tab['#access']) || $tab['#access']) { + $tabs[$id]['#active'] = TRUE; + break; + } + } + } + if (!isset($data['tabs'][1]['output'])) { + $data['tabs'][1]['output'] = array(); + } + $data['tabs'][1]['output'] = array_merge($data['tabs'][1]['output'], $tabs); + $data['tabs'][1]['count'] = count($data['tabs'][1]['output']); + } + */ +} + +/** * Implements hook_help(). */ function views_ui_help($path, $arg = '') { switch ($path) { - case 'admin/structure/views/tools/convert': - return '<p>' . t('The converter will make a best-effort attempt to convert a Views 1 view to Views 2. This conversion is not reliable; you will very likely have to make adjustments to your view to get it to match. You can import Views 1 views through the normal Import tab.') . '</p>'; + } + // return '<pre>'.print_r(views_ui_get_wizards(),1); } -/* +/** * Implements hook_theme(). */ function views_ui_theme() { @@ -214,14 +204,14 @@ function views_ui_theme() { return array( // edit a view - 'views_ui_edit_view' => array( - 'variables' => array('view' => NULL), - 'template' => 'views-ui-edit-view', + 'views_ui_display_tab_setting' => array( + 'variables' => array('description' => '', 'link' => '', 'settings_links' => array(), 'overridden' => FALSE, 'defaulted' => FALSE, 'description_separator' => TRUE, 'class' => array()), + 'template' => 'views-ui-display-tab-setting', 'path' => "$path/theme", ), - 'views_ui_edit_tab' => array( - 'variables' => array('view' => NULL, 'display' => NULL), - 'template' => 'views-ui-edit-tab', + 'views_ui_display_tab_bucket' => array( + 'render element' => 'element', + 'template' => 'views-ui-display-tab-bucket', 'path' => "$path/theme", ), 'views_ui_edit_item' => array( @@ -236,17 +226,18 @@ function views_ui_theme() { 'render element' => 'form', 'file' => 'includes/admin.inc', ), + 'views_ui_item_delete_form' => array( + 'render element' => 'form', + ), + 'views_ui_expose_filter_form' => array( + 'render element' => 'form', + 'file' => 'includes/admin.inc', + ), // list views - 'views_ui_list_views' => array( - 'variables' => array( - 'views' => array(), - 'help' => '', - 'widgets' => '', - 'help_type_icon' => '', - ), - 'template' => 'views-ui-list-views', - 'path' => "$path/theme", + 'views_ui_view_info' => array( + 'variables' => array('view' => NULL, 'base' => NULL), + 'file' => "includes/admin.inc", ), // tab themes @@ -266,12 +257,44 @@ function views_ui_theme() { 'views_ui_style_plugin_table' => array( 'render element' => 'form', ), + + // When previewing a view. + 'views_ui_view_preview_section' => array( + 'variables' => array('view' => NULL, 'section' => NULL, 'content' => NULL, 'links' => ''), + ), + + // Generic container wrapper, to use instead of theme_container when an id + // is not desired. + 'views_container' => array( + 'render element' => 'element', + 'file' => 'theme/theme.inc', + ), ); } /** - * Specialized menu callback to load a view either out of the cache or just - * load it. + * Page title callback for the Edit View page. + */ +function views_ui_edit_page_title($view) { + module_load_include('inc', 'views_ui', 'includes/admin'); + $bases = views_fetch_base_tables(); + $name = $view->get_human_name(); + if (isset($bases[$view->base_table])) { + $name .= ' (' . $bases[$view->base_table]['title'] . ')'; + } + + return $name; +} + +/** + * Specialized menu callback to load a view and check its locked status. + * + * @param $name + * The machine name of the view. + * + * @return + * The view object, with a "locked" property indicating whether or not + * someone else is already editing the view. */ function views_ui_cache_load($name) { ctools_include('object-cache'); @@ -312,9 +335,14 @@ function views_ui_cache_set(&$view) { ctools_include('object-cache'); $view->changed = TRUE; // let any future object know that this view has changed. + if (isset($view->current_display)) { + // Add the knowledge of the changed display, too. + $view->changed_display[$view->current_display] = TRUE; + unset($view->current_display); + } + // Unset handlers; we don't want to write these into the cache unset($view->display_handler); - unset($view->current_display); unset($view->default_display); $view->query = NULL; foreach (array_keys($view->display) as $id) { @@ -339,84 +367,487 @@ function views_ui_default_load($name) { } /** - * Package and send the result of a page callback to the browser as an AJAX - * response, and add the HTML. + * Theme preprocess for views-view.tpl.php. + */ +function views_ui_preprocess_views_view(&$vars) { + $view = $vars['view']; + if (!empty($view->views_ui_context) && module_exists('contextual')) { + $view->hide_admin_links = TRUE; + foreach (array('title', 'header', 'exposed', 'rows', 'pager', 'more', 'footer', 'empty', 'attachment_after', 'attachment_before') as $section) { + if (!empty($vars[$section])) { + $vars[$section] = array( + '#theme' => 'views_ui_view_preview_section', + '#view' => $view, + '#section' => $section, + '#content' => $vars[$section], + '#theme_wrappers' => array('views_container'), + '#attributes' => array('class' => 'contextual-links-region'), + ); + $vars[$section] = drupal_render($vars[$section]); + } + } + } +} + +/** + * Theme preprocess for theme_views_ui_view_preview_section(). + * + * @TODO + * Perhaps move this to includes/admin.inc or theme/theme.inc + */ +function template_preprocess_views_ui_view_preview_section(&$vars) { + switch ($vars['section']) { + case 'title': + $vars['title'] = t('Title'); + $links = views_ui_view_preview_section_display_category_links($vars['view'], 'title', $vars['title']); + break; + case 'header': + $vars['title'] = t('Header'); + $links = views_ui_view_preview_section_handler_links($vars['view'], $vars['section']); + break; + case 'empty': + $vars['title'] = t('No results behavior'); + $links = views_ui_view_preview_section_handler_links($vars['view'], $vars['section']); + break; + case 'exposed': + // @todo Sorts can be exposed too, so we may need a better title. + $vars['title'] = t('Exposed Filters'); + $links = views_ui_view_preview_section_display_category_links($vars['view'], 'exposed_form_options', $vars['title']); + break; + case 'rows': + // @todo The title needs to depend on what is being viewed. + $vars['title'] = t('Content'); + $links = views_ui_view_preview_section_rows_links($vars['view']); + break; + case 'pager': + $vars['title'] = t('Pager'); + $links = views_ui_view_preview_section_display_category_links($vars['view'], 'pager_options', $vars['title']); + break; + case 'more': + $vars['title'] = t('More'); + $links = views_ui_view_preview_section_display_category_links($vars['view'], 'use_more', $vars['title']); + break; + case 'footer': + $vars['title'] = t('Footer'); + $links = views_ui_view_preview_section_handler_links($vars['view'], $vars['section']); + break; + case 'attachment_before': + // @todo: Add links to the attachment configuration page. + $vars['title'] = t('Attachment before'); + break; + case 'attachment_after': + // @todo: Add links to the attachment configuration page. + $vars['title'] = t('Attachment after'); + break; + } + + if (isset($links)) { + $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')), + ), + ); + $vars['links'] = drupal_render($build); + } + $vars['theme_hook_suggestions'][] = 'views_ui_view_preview_section__' . $vars['section']; +} + +/** + * Returns the HTML for a section of a View being previewed within the Views UI. + */ +function theme_views_ui_view_preview_section($vars) { + return '<h1 class="section-title">' . $vars['title'] . '</h1>' + . $vars['links'] + . '<div class="preview-section">'. $vars['content'] . '</div>'; +} + +/** + * Returns contextual links for each handler of a certain section. + * + * @TODO + * Bring in relationships + * Refactor this function to use much stuff of views_ui_edit_form_get_bucket. * - * @param $page_callback_result - * The result of a page callback. Can be one of: - * - NULL: to indicate no content. - * - An integer menu status constant: to indicate an error condition. - * - A string of HTML content. - * - A renderable array of content. + * @param $title + * Add a bolded title of this section. */ -function views_ui_ajax_deliver($page_callback_result) { - $commands = array(); - $header = TRUE; - - if (!isset($page_callback_result)) { - // Simply delivering an empty commands array is sufficient. This results - // in the AJAX request being completed, but nothing being done to the page. - } - elseif (is_int($page_callback_result)) { - switch ($page_callback_result) { - case MENU_NOT_FOUND: - $commands[] = ajax_command_alert(t('The requested page could not be found.')); - break; - - case MENU_ACCESS_DENIED: - $commands[] = ajax_command_alert(t('You are not authorized to access this page.')); - break; - - case MENU_SITE_OFFLINE: - $commands[] = ajax_command_alert(filter_xss_admin(variable_get('maintenance_mode_message', - t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal')))))); - break; +function views_ui_view_preview_section_handler_links($view, $type, $title = FALSE) { + $display = $view->display_handler->display; + $handlers = $view->display_handler->get_handlers($type); + $links = array(); + + $types = views_object_types(); + if ($title) { + $links[$type . '-title'] = array( + 'title' => $types[$type]['title'], + 'attributes' => array('class' => array('views-ajax-link')), + ); + } + + foreach ($handlers as $id => $handler) { + $field_name = $handler->ui_name(TRUE); + $links[$type . '-edit-' . $id] = array( + 'title' => t('Edit @section', array('@section' => $field_name)), + 'href' => "admin/structure/views/nojs/config-item/$view->name/$display->id/$type/$id", + 'attributes' => array('class' => array('views-ajax-link')), + ); + } + $links[$type . '-add'] = array( + 'title' => t('Add new'), + 'href' => "admin/structure/views/nojs/add-item/$view->name/$display->id/$type", + 'attributes' => array('class' => array('views-ajax-link')), + ); + + return $links; +} + +/** + * Returns a link to editing a certain display setting. + */ +function views_ui_view_preview_section_display_category_links($view, $type, $title) { + $display = $view->display_handler->display; + $links = array( + $type . '-edit' => array( + 'title' => t('Edit @section', array('@section' => $title)), + 'href' => "admin/structure/views/nojs/display/$view->name/$display->id/$type", + 'attributes' => array('class' => array('views-ajax-link')), + ), + ); + + return $links; +} + +/** + * Returns all contextual links for the main content part of the view. + */ +function views_ui_view_preview_section_rows_links($view) { + $display = $view->display_handler->display; + $links = array(); + $links = array_merge($links, views_ui_view_preview_section_handler_links($view, 'filter', TRUE)); + $links = array_merge($links, views_ui_view_preview_section_handler_links($view, 'field', TRUE)); + $links = array_merge($links, views_ui_view_preview_section_handler_links($view, 'sort', TRUE)); + $links = array_merge($links, views_ui_view_preview_section_handler_links($view, 'argument', TRUE)); + $links = array_merge($links, views_ui_view_preview_section_handler_links($view, 'relationship', TRUE)); + + return $links; +} + + +/** + * Implments hook_ctools_plugin_directory(). + * + * Views UI provides wizard plugins on behalf of core base tables. + */ +function views_ui_ctools_plugin_directory($module, $plugin) { + if ($module == 'views_ui' || ($module == 'ctools' && $plugin == 'export_ui')) { + return 'plugins/' . $plugin; + } +} + +/** + * Fetch metadata on a specific views ui wizard plugin. + * + * @param $wizard_type + * Name of a wizard, or name of a base table. + * + * @return + * An array with information about the requested wizard type. + */ +function views_ui_get_wizard($wizard_type) { + ctools_include('plugins'); + $w = ctools_get_plugins('views_ui', 'views_wizard', $wizard_type); + // @todo - handle this via an alter hook instead. + if (!$w) { + // Must be a base table using the default wizard plugin. + $base_tables = views_fetch_base_tables(); + if (!empty($base_tables[$wizard_type])) { + $w = views_ui_views_wizard_defaults(); + $w['base_table'] = $wizard_type; + $w['title'] = $base_tables[$wizard_type]['title']; } } - elseif (is_array($page_callback_result) && isset($page_callback_result['#type']) && ($page_callback_result['#type'] == 'ajax')) { - // Complex AJAX callbacks can return a result that contains an error message - // or a specific set of commands to send to the browser. - $page_callback_result += element_info('ajax'); - $header = $page_callback_result['#header']; - $error = $page_callback_result['#error']; - if (isset($error) && $error !== FALSE) { - if ((empty($error) || $error === TRUE)) { - $error = t('An error occurred while handling the request: The server received invalid input.'); + return $w; +} + +/** + * Fetch metadata for all content_type plugins. + * + * @return + * An array of arrays with information about all available views wizards. + */ +function views_ui_get_wizards() { + ctools_include('plugins'); + $wizard_plugins = ctools_get_plugins('views_ui', 'views_wizard'); + $wizard_tables = array(); + foreach ($wizard_plugins as $name => $info) { + $wizard_tables[$info['base_table']] = TRUE; + } + $base_tables = views_fetch_base_tables(); + $default_wizard = views_ui_views_wizard_defaults(); + // Find base tables with no wizard. + // @todo - handle this via an alter hook for plugins? + foreach ($base_tables as $table => $info) { + if (!isset($wizard_tables[$table])) { + $wizard = $default_wizard; + $wizard['title'] = $info['title']; + $wizard['base_table'] = $table; + $wizard_plugins[$table] = $wizard; + } + } + return $wizard_plugins; +} + +/** + * Helper function to define the default values for a Views wizard plugin. + * + * @return + * An array of defaults for a views wizard. + */ +function views_ui_views_wizard_defaults() { + return array( + // The children may, for example, be a different variant for each node type. + 'get children' => NULL, + 'get child' => NULL, + // title and base table must be populated. They are empty here just + // so they are documented. + 'title' => '', + 'base_table' => NULL, + // This is a callback that takes the wizard as argument and returns + // an instantiazed Views UI form wizard object. + 'get_instance' => 'views_ui_get_form_wizard_instance', + 'form_wizard_class' => array( + 'file' => 'views_ui_base_views_wizard', + 'class' => 'ViewsUiBaseViewsWizard', + ), + ); +} + +/** + * Inform CTools that the Views wizard plugin can have child plugins. + */ +function views_ui_ctools_plugin_type() { + return array( + 'views_wizard' => array( + 'child plugins' => TRUE, + 'classes' => array( + 'form_wizard_class', + ), + 'defaults' => views_ui_views_wizard_defaults(), + ), + ); +} + +function views_ui_get_form_wizard_instance($wizard) { + if (isset($wizard['form_wizard_class']['class'])) { + $class = $wizard['form_wizard_class']['class']; + return new $class($wizard); + } + else { + return new ViewsUiBaseViewsWizard($wizard); + } +} + +/** + * Implements hook_views_plugins_alter(). + */ +function views_ui_views_plugins_alter(&$plugins) { + // Attach contextual links to each display plugin. The links will point to + // paths underneath "admin/structure/views/view/{$view->name}" (i.e., paths + // for editing and performing other contextual actions on the view). + foreach ($plugins['display'] as &$display) { + $display['contextual links']['views_ui'] = array( + 'parent path' => 'admin/structure/views/view', + 'argument properties' => array('name'), + ); + } +} + +/** + * Implements hook_contextual_links_view_alter(). + */ +function views_ui_contextual_links_view_alter(&$element, $items) { + // Remove contextual links from being rendered, when so desired, such as + // within a View preview. + if (views_ui_contextual_links_suppress()) { + $element['#links'] = array(); + } + // Append the display ID to the Views UI edit links, so that clicking on the + // contextual link takes you directly to the correct display tab on the edit + // screen. + elseif (!empty($element['#links']['views-ui-edit']) && !empty($element['#element']['#views_contextual_links_info']['views_ui']['view_display_id'])) { + $display_id = $element['#element']['#views_contextual_links_info']['views_ui']['view_display_id']; + $element['#links']['views-ui-edit']['href'] .= '/' . $display_id; + } +} + +/** + * Sets a static variable for controlling whether contextual links are rendered. + * + * @see views_ui_contextual_links_view_alter() + */ +function views_ui_contextual_links_suppress($set = NULL) { + $suppress = &drupal_static(__FUNCTION__); + if (isset($set)) { + $suppress = $set; + } + return $suppress; +} + +/** + * Increments the views_ui_contextual_links_suppress() static variable. + * + * When this function is added to the #pre_render of an element, and + * 'views_ui_contextual_links_suppress_pop' is added to the #post_render of the + * same element, then all contextual links within the element and its + * descendants are suppressed from being rendered. This is used, for example, + * during a View preview, when it is not desired for nodes in the Views result + * to have contextual links. + * + * @see views_ui_contextual_links_suppress_pop() + */ +function views_ui_contextual_links_suppress_push() { + views_ui_contextual_links_suppress(((int) views_ui_contextual_links_suppress())+1); +} + +/** + * Decrements the views_ui_contextual_links_suppress() static variable. + * + * @see views_ui_contextual_links_suppress_push() + */ +function views_ui_contextual_links_suppress_pop() { + views_ui_contextual_links_suppress(((int) views_ui_contextual_links_suppress())-1); +} + +/** + * Menu callback; handles AJAX form submissions similar to ajax_form_callback(), but can be used for uncached forms. + * + * ajax_form_callback(), the menu callback for the system/ajax path, requires + * the form to be retrievable from the form cache, because it lacks a trusted + * $form_id argument with which to call drupal_retrieve_form(). When AJAX is + * wanted on a non-cacheable form, #ajax['path'] can be set to a path whose + * menu router item's 'page callback' is this function, and whose + * 'page arguments' is the form id, optionally followed by additional build + * arguments, as expected by drupal_get_form(). + * + * The same caution must be used when defining a hook_menu() entry with this + * page callback as is used when defining a hook_menu() entry with the + * 'drupal_get_form' page callback: a 'page arguments' must be specified with a + * literal value as the first argument, because $form_id determines which form + * builder function gets called, so must be safe from user tampering. + * + * @see drupal_get_form() + * @see ajax_form_callback() + * @see http://drupal.org/node/774876 + */ +function views_ui_ajax_get_form($form_id) { + // @see ajax_get_form() + $form_state = array( + 'no_redirect' => TRUE, + ); + $form_state['rebuild_info']['copy']['#build_id'] = TRUE; + $form_state['rebuild_info']['copy']['#action'] = TRUE; + + // @see drupal_get_form() + $args = func_get_args(); + array_shift($args); + $form_state['build_info']['args'] = $args; + $form = drupal_build_form($form_id, $form_state); + + // @see ajax_form_callback() + if (!empty($form_state['triggering_element'])) { + $callback = $form_state['triggering_element']['#ajax']['callback']; + } + if (!empty($callback) && function_exists($callback)) { + return $callback($form, $form_state); + } +} +// @todo move these when we can + + +/** + * Helper function to get a list of paths assigned to a view. + * + * @param $view + * The view. + * + * @return + * An array of links to this view's display paths. + */ +function _views_ui_get_paths($view) { + $all_paths = array(); + if (empty($view->display)) { + $all_paths[] = t('Edit this view to add a display.'); + } + else { + $view->init_display(); // Make sure all the handlers are set up + foreach ($view->display as $display) { + if (!empty($display->handler) && $display->handler->has_path()) { + $one_path = $display->handler->get_option('path'); + if (empty($path_sort)) { + $path_sort = strtolower($one_path); + } + if (empty($view->disabled) && strpos($one_path, '%') === FALSE) { + $all_paths[] = l($one_path, $one_path); + } + else { + $all_paths[] = check_plain($one_path); + } } - $commands[] = ajax_command_alert($error); } - else { - $commands = $page_callback_result['#commands']; + } + + return array_unique($all_paths); +} + +/** + * Helper function to get a list of displays included in a view. + * + * @param $view + * The view. + * + * @return + * An array of display types that this view includes. + */ +function _views_ui_get_displays_list($view) { + $displays = array(); + foreach ($view->display as $display) { + if (!empty($display->handler->definition['admin'])) { + $displays[$display->handler->definition['admin']] = TRUE; + } + } + + if ($displays) { + ksort($displays); + $displays = array_keys($displays); + } + return $displays; +} + +/** + * This is part of a patch to address a jQueryUI bug. The bug is responsible + * for the inability to scroll a page when a modal dialog is active. If the content + * of the dialog extends beyond the bottom of the viewport, the user is only able + * to scroll with a mousewheel or up/down keyboard keys. + * + * @see http://bugs.jqueryui.com/ticket/4671 + * @see https://bugs.webkit.org/show_bug.cgi?id=19033 + * @see /js/jquery.ui.dialog.patch.js + * @see /js/jquery.ui.dialog.min.js + * + * The javascript patch overwrites the $.ui.dialog.overlay.events object to remove + * the mousedown, mouseup and click events from the list of events that are bound + * in $.ui.dialog.overlay.create. + */ + +function views_ui_library_alter(&$libraries, $module) { + if ($module == 'system' && isset($libraries['ui.dialog'])) { + if (version_compare($libraries['ui.dialog']['version'], '1.7.2', '>=')) { + drupal_add_js(drupal_get_path('module', 'views') . '/js/jquery.ui.dialog.patch.js', array('group' => JS_THEME)); } } - else { - // Like normal page callbacks, simple AJAX callbacks can return html - // content, as a string or renderable array, to replace what was previously - // there in the wrapper. In this case, in addition to the content, we want - // to add the status messages, but inside the new wrapper, so that they get - // replaced on subsequent AJAX calls for the same wrapper. - $html = is_string($page_callback_result) ? $page_callback_result : drupal_render($page_callback_result); - $commands[] = ajax_command_replace(NULL, $html); - $commands[] = ajax_command_prepend(NULL, theme('status_messages')); - } - - // This function needs to do the same thing that drupal_deliver_html_page() - // does: add any needed http headers, print rendered output, and perform - // end-of-request tasks. By default, $header=TRUE, and we add a - // 'text/javascript' header. The page callback can override $header by - // returning an 'ajax' element with a #header property. This can be set to - // FALSE to prevent the 'text/javascript' header from being output, necessary - // when outputting to an IFRAME. This can also be set to 'multipart', in which - // case, we don't output JSON, but JSON content wrapped in a textarea, making - // a 'text/javascript' header incorrect. - if ($header && $header !== 'multipart') { - drupal_add_http_header('Content-Type', 'text/javascript; charset=utf-8'); - } - $output = ajax_render($commands); - if ($header === 'multipart') { - // jQuery file uploads: http://malsup.com/jquery/form/#code-samples - $output = '<textarea>' . $output . '</textarea>'; - } - print $output; - ajax_footer(); }