Issue #731662 by dagmar, dawehner, tim.plunkett, bojanz, SuperXren, BWPanda: Added Hybrid Exposed Filters.
parent
a369a0e3dd
commit
40d5f16f55
|
|
@ -380,6 +380,7 @@ td.group-title {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.grouped-description,
|
||||||
.exposed-description {
|
.exposed-description {
|
||||||
float: left;
|
float: left;
|
||||||
padding-top: 3px;
|
padding-top: 3px;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,21 @@ When you click the Rearrange Icon you can first rearrange your filters, easily d
|
||||||
|
|
||||||
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>.
|
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>.
|
||||||
|
|
||||||
|
For exposed filters, you can create a grouped filter. When filters are in a group, each item of the group represents a set of operators and values. The following table illustrates how this feature works. The values of the first column of the table are displayed as options of a single select box:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>What the user see</th><th>What views does</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>Is lower than 10</td><td><strong>Operator:</strong> Is Lower than. <strong>Value:</strong> 10</td></tr>
|
||||||
|
<tr><td>Is between 10 and 20</td><td><strong>Operator:</strong> Is between. <strong>Value:</strong> 10 and 20</td></tr>
|
||||||
|
<tr><td>Is greater than 20</td><td><strong>Operator:</strong> Is Greater. <strong>Value:</strong> 20</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<strong>Please note:</strong> When using grouped filters with the option: 'Enable to allow users to select multiple items' checked, you probably may want to to place the filter in a separated group and define the operator of the group as 'OR'. This may be neccesary because in order to use multiple times the same filter, all options have to be applied using the OR operator, if not, probably you will get nothing listed since usually items in a group are mutually exclusive.
|
||||||
|
|
||||||
Taxonomy filters have been significantly altered in Views 7.x-3.x. D7 significantly re-organized taxonomy, there was a lot of duplicate taxonomy related fields and filters. Some of them were removed to try and reduce confusion between them. Implicit relationships to taxonomy have been removed, in favor of explicit relationships. If the filters you can find don't do what you need, try adding either the related taxonomy terms relationship, or a relationship on the specific taxonomy field. That will give you the term specific filters.
|
Taxonomy filters have been significantly altered in Views 7.x-3.x. D7 significantly re-organized taxonomy, there was a lot of duplicate taxonomy related fields and filters. Some of them were removed to try and reduce confusion between them. Implicit relationships to taxonomy have been removed, in favor of explicit relationships. If the filters you can find don't do what you need, try adding either the related taxonomy terms relationship, or a relationship on the specific taxonomy field. That will give you the term specific filters.
|
||||||
|
|
||||||
You can override the complete filter section - see <a href="topic:views/overrides">here</a> for more information.
|
You can override the complete filter section - see <a href="topic:views/overrides">here</a> for more information.
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,6 @@ function views_ui_get_admin_css() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return $list;
|
return $list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,7 +151,6 @@ function views_ui_preview($view, $display_id, $args = array()) {
|
||||||
|
|
||||||
$view->set_exposed_input($exposed_input);
|
$view->set_exposed_input($exposed_input);
|
||||||
|
|
||||||
|
|
||||||
if (!$view->set_display($display_id)) {
|
if (!$view->set_display($display_id)) {
|
||||||
return t('Invalid display id @display', array('@display' => $display_id));
|
return t('Invalid display id @display', array('@display' => $display_id));
|
||||||
}
|
}
|
||||||
|
|
@ -2716,7 +2714,6 @@ function views_ui_get_form_progress($view) {
|
||||||
return $progress;
|
return $progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// Various subforms for editing the pieces of a view.
|
// Various subforms for editing the pieces of a view.
|
||||||
|
|
||||||
|
|
@ -3506,6 +3503,7 @@ function theme_views_ui_expose_filter_form($variables) {
|
||||||
|
|
||||||
$output = drupal_render($form['form_description']);
|
$output = drupal_render($form['form_description']);
|
||||||
$output .= drupal_render($form['expose_button']);
|
$output .= drupal_render($form['expose_button']);
|
||||||
|
$output .= drupal_render($form['group_button']);
|
||||||
if (isset($form['required'])) {
|
if (isset($form['required'])) {
|
||||||
$output .= drupal_render($form['required']);
|
$output .= drupal_render($form['required']);
|
||||||
}
|
}
|
||||||
|
|
@ -3536,7 +3534,76 @@ function theme_views_ui_expose_filter_form($variables) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit handler for rearranging form
|
* Theme the build group filter form.
|
||||||
|
*/
|
||||||
|
function theme_views_ui_build_group_filter_form($variables) {
|
||||||
|
$form = $variables['form'];
|
||||||
|
$more = drupal_render($form['more']);
|
||||||
|
|
||||||
|
$output = drupal_render($form['form_description']);
|
||||||
|
$output .= drupal_render($form['expose_button']);
|
||||||
|
$output .= drupal_render($form['group_button']);
|
||||||
|
if (isset($form['required'])) {
|
||||||
|
$output .= drupal_render($form['required']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$output .= drupal_render($form['operator']);
|
||||||
|
$output .= drupal_render($form['value']);
|
||||||
|
|
||||||
|
$output .= '<div class="views-left-40">';
|
||||||
|
$output .= drupal_render($form['optional']);
|
||||||
|
$output .= drupal_render($form['remember']);
|
||||||
|
$output .= '</div>';
|
||||||
|
|
||||||
|
$output .= '<div class="views-right-60">';
|
||||||
|
$output .= drupal_render($form['widget']);
|
||||||
|
$output .= drupal_render($form['label']);
|
||||||
|
$output .= '</div>';
|
||||||
|
|
||||||
|
$header = array(
|
||||||
|
t('Default'),
|
||||||
|
t('Weight'),
|
||||||
|
t('Label'),
|
||||||
|
t('Operator'),
|
||||||
|
t('Value'),
|
||||||
|
t('Operations'),
|
||||||
|
);
|
||||||
|
|
||||||
|
$form['default_group'] = form_process_radios($form['default_group']);
|
||||||
|
$form['default_group_multiple'] = form_process_checkboxes($form['default_group_multiple']);
|
||||||
|
$form['default_group']['All']['#title'] = '';
|
||||||
|
|
||||||
|
hide($form['default_group_multiple']['All']);
|
||||||
|
$rows[] = array(
|
||||||
|
drupal_render($form['default_group']['All']),
|
||||||
|
'',
|
||||||
|
array(
|
||||||
|
'data' => variable_get('views_exposed_filter_any_label', 'new_any') == 'old_any' ? t('<Any>') : t('- Any -'),
|
||||||
|
'colspan' => 4,
|
||||||
|
'class' => array('class' => 'any-default-radios-row'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach (element_children($form['group_items']) as $group_id) {
|
||||||
|
$form['group_items'][$group_id]['value']['#title'] = '';
|
||||||
|
$data = array(
|
||||||
|
'default' => drupal_render($form['default_group'][$group_id]) . drupal_render($form['default_group_multiple'][$group_id]),
|
||||||
|
'weight' => drupal_render($form['group_items'][$group_id]['weight']),
|
||||||
|
'title' => drupal_render($form['group_items'][$group_id]['title']),
|
||||||
|
'operator' => drupal_render($form['group_items'][$group_id]['operator']),
|
||||||
|
'value' => drupal_render($form['group_items'][$group_id]['value']),
|
||||||
|
'remove' => drupal_render($form['group_items'][$group_id]['remove']) . l('<span>' . t('Remove') . '</span>', 'javascript:void()', array('attributes' => array('id' => 'views-remove-link-' . $group_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)),
|
||||||
|
);
|
||||||
|
$rows[] = array('data' => $data, 'id' => 'views-row-' . $group_id, 'class' => array('draggable'));
|
||||||
|
}
|
||||||
|
$table = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('class' => array('views-filter-groups'), 'id' => 'views-filter-groups'))) . drupal_render($form['add_group']);
|
||||||
|
drupal_add_tabledrag('views-filter-groups', 'order', 'sibling', 'weight');
|
||||||
|
$render_form = drupal_render_children($form);
|
||||||
|
return $output . $render_form . $table . $more;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit handler for rearranging form.
|
||||||
*/
|
*/
|
||||||
function views_ui_rearrange_form_submit($form, &$form_state) {
|
function views_ui_rearrange_form_submit($form, &$form_state) {
|
||||||
$types = View::views_object_types();
|
$types = View::views_object_types();
|
||||||
|
|
@ -3977,7 +4044,6 @@ function views_ui_add_item_form($form, &$form_state) {
|
||||||
$form['#title'] = t('Add @type', array('@type' => $ltitle));
|
$form['#title'] = t('Add @type', array('@type' => $ltitle));
|
||||||
$form['#section'] = $display_id . 'add-item';
|
$form['#section'] = $display_id . 'add-item';
|
||||||
|
|
||||||
|
|
||||||
// Add the display override dropdown.
|
// Add the display override dropdown.
|
||||||
views_ui_standard_display_dropdown($form, $form_state, $section);
|
views_ui_standard_display_dropdown($form, $form_state, $section);
|
||||||
|
|
||||||
|
|
@ -4144,6 +4210,45 @@ function views_ui_add_item_form_submit($form, &$form_state) {
|
||||||
views_ui_cache_set($form_state['view']);
|
views_ui_cache_set($form_state['view']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override handler for views_ui_edit_display_form
|
||||||
|
*/
|
||||||
|
function views_ui_config_item_form_build_group($form, &$form_state) {
|
||||||
|
$item = &$form_state['handler']->options;
|
||||||
|
// flip. If the filter was a group, set back to a standard filter.
|
||||||
|
$item['is_grouped'] = empty($item['is_grouped']);
|
||||||
|
|
||||||
|
// If necessary, set new defaults:
|
||||||
|
if ($item['is_grouped']) {
|
||||||
|
$form_state['handler']->build_group_options();
|
||||||
|
}
|
||||||
|
|
||||||
|
$form_state['view']->set_item($form_state['display_id'], $form_state['type'], $form_state['id'], $item);
|
||||||
|
|
||||||
|
views_ui_add_form_to_stack($form_state['form_key'], $form_state['view'], $form_state['display_id'], array($form_state['type'], $form_state['id']), TRUE, TRUE);
|
||||||
|
|
||||||
|
views_ui_cache_set($form_state['view']);
|
||||||
|
$form_state['rerender'] = TRUE;
|
||||||
|
$form_state['rebuild'] = TRUE;
|
||||||
|
$form_state['force_build_group_options'] = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new group to the exposed filter groups.
|
||||||
|
*/
|
||||||
|
function views_ui_config_item_form_add_group($form, &$form_state) {
|
||||||
|
$item =& $form_state['handler']->options;
|
||||||
|
|
||||||
|
// Add a new row.
|
||||||
|
$item['group_info']['group_items'][] = array();
|
||||||
|
|
||||||
|
$form_state['view']->set_item($form_state['display_id'], $form_state['type'], $form_state['id'], $item);
|
||||||
|
|
||||||
|
views_ui_cache_set($form_state['view']);
|
||||||
|
$form_state['rerender'] = TRUE;
|
||||||
|
$form_state['rebuild'] = TRUE;
|
||||||
|
$form_state['force_build_group_options'] = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Form to config_item items in the views UI.
|
* Form to config_item items in the views UI.
|
||||||
|
|
@ -4317,7 +4422,6 @@ function views_ui_config_item_form_submit_temporary($form, &$form_state) {
|
||||||
$handler = views_get_handler($item['table'], $item['field'], $handler_type, $override);
|
$handler = views_get_handler($item['table'], $item['field'], $handler_type, $override);
|
||||||
$handler->init($form_state['view'], $item);
|
$handler->init($form_state['view'], $item);
|
||||||
|
|
||||||
|
|
||||||
// Add the incoming options to existing options because items using
|
// Add the incoming options to existing options because items using
|
||||||
// the extra form may not have everything in the form here.
|
// the extra form may not have everything in the form here.
|
||||||
$options = $form_state['values']['options'] + $form_state['handler']->options;
|
$options = $form_state['values']['options'] + $form_state['handler']->options;
|
||||||
|
|
@ -4372,7 +4476,6 @@ function views_ui_config_item_form_submit($form, &$form_state) {
|
||||||
$handler = views_get_handler($item['table'], $item['field'], $handler_type, $override);
|
$handler = views_get_handler($item['table'], $item['field'], $handler_type, $override);
|
||||||
$handler->init($form_state['view'], $item);
|
$handler->init($form_state['view'], $item);
|
||||||
|
|
||||||
|
|
||||||
// Add the incoming options to existing options because items using
|
// Add the incoming options to existing options because items using
|
||||||
// the extra form may not have everything in the form here.
|
// the extra form may not have everything in the form here.
|
||||||
$options = $form_state['values']['options'] + $form_state['handler']->options;
|
$options = $form_state['values']['options'] + $form_state['handler']->options;
|
||||||
|
|
@ -4901,7 +5004,6 @@ function views_ui_admin_settings_advanced() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$form['actions']['#type'] = 'actions';
|
$form['actions']['#type'] = 'actions';
|
||||||
$form['actions']['submit'] = array(
|
$form['actions']['submit'] = array(
|
||||||
'#type' => 'submit',
|
'#type' => 'submit',
|
||||||
|
|
@ -5164,7 +5266,6 @@ function views_fetch_fields($base, $type, $grouping = FALSE) {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Theme the form for the table style plugin
|
* Theme the form for the table style plugin
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -827,7 +827,7 @@ Drupal.behaviors.viewsRemoveIconClass.attach = function (context, settings) {
|
||||||
$('.icon', $this).removeClass('icon');
|
$('.icon', $this).removeClass('icon');
|
||||||
$('.horizontal', $this).removeClass('horizontal');
|
$('.horizontal', $this).removeClass('horizontal');
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change "Expose filter" buttons into checkboxes.
|
* Change "Expose filter" buttons into checkboxes.
|
||||||
|
|
@ -835,7 +835,7 @@ Drupal.behaviors.viewsRemoveIconClass.attach = function (context, settings) {
|
||||||
Drupal.behaviors.viewsUiCheckboxify = {};
|
Drupal.behaviors.viewsUiCheckboxify = {};
|
||||||
Drupal.behaviors.viewsUiCheckboxify.attach = function (context, settings) {
|
Drupal.behaviors.viewsUiCheckboxify.attach = function (context, settings) {
|
||||||
var $ = jQuery;
|
var $ = jQuery;
|
||||||
var $buttons = $('#edit-options-expose-button-button').once('views-ui-checkboxify');
|
var $buttons = $('#edit-options-expose-button-button, #edit-options-group-button-button').once('views-ui-checkboxify');
|
||||||
var length = $buttons.length;
|
var length = $buttons.length;
|
||||||
var i;
|
var i;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
|
|
@ -843,6 +843,33 @@ Drupal.behaviors.viewsUiCheckboxify.attach = function (context, settings) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the default widget to select the default group according to the
|
||||||
|
* selected widget for the exposed group.
|
||||||
|
*/
|
||||||
|
Drupal.behaviors.viewsUiChangeDefaultWidget = {};
|
||||||
|
Drupal.behaviors.viewsUiChangeDefaultWidget.attach = function (context, settings) {
|
||||||
|
var $ = jQuery;
|
||||||
|
function change_default_widget(multiple) {
|
||||||
|
if (multiple) {
|
||||||
|
$('input.default-radios').hide();
|
||||||
|
$('td.any-default-radios-row').parent().hide();
|
||||||
|
$('input.default-checkboxes').show();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('input.default-checkboxes').hide();
|
||||||
|
$('td.any-default-radios-row').parent().show();
|
||||||
|
$('input.default-radios').show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Update on widget change.
|
||||||
|
$('input[name="options[group_info][multiple]"]').change(function() {
|
||||||
|
change_default_widget($(this).attr("checked"));
|
||||||
|
});
|
||||||
|
// Update the first time the form is rendered.
|
||||||
|
$('input[name="options[group_info][multiple]"]').trigger('change');
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches an expose filter button to a checkbox that triggers its click event.
|
* Attaches an expose filter button to a checkbox that triggers its click event.
|
||||||
*
|
*
|
||||||
|
|
@ -852,13 +879,14 @@ Drupal.behaviors.viewsUiCheckboxify.attach = function (context, settings) {
|
||||||
Drupal.viewsUi.Checkboxifier = function (button) {
|
Drupal.viewsUi.Checkboxifier = function (button) {
|
||||||
var $ = jQuery;
|
var $ = jQuery;
|
||||||
this.$button = $(button);
|
this.$button = $(button);
|
||||||
this.$parent = this.$button.parent('div.views-expose');
|
this.$parent = this.$button.parent('div.views-expose, div.views-grouped');
|
||||||
this.$checkbox = this.$parent.find('input:checkbox');
|
this.$input = this.$parent.find('input:checkbox, input:radio');
|
||||||
// Hide the button and its description.
|
// Hide the button and its description.
|
||||||
this.$button.hide();
|
this.$button.hide();
|
||||||
this.$parent.find('.exposed-description').hide();
|
this.$parent.find('.exposed-description, .grouped-description').hide();
|
||||||
|
|
||||||
|
this.$input.click($.proxy(this, 'clickHandler'));
|
||||||
|
|
||||||
this.$checkbox.click($.proxy(this, 'clickHandler'));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -554,6 +554,18 @@ abstract class Handler extends Plugin {
|
||||||
return !empty($this->options['exposed']);
|
return !empty($this->options['exposed']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if the exposed filter works like a grouped filter.
|
||||||
|
*/
|
||||||
|
function is_a_group() { return FALSE; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define if the exposed input has to be submitted multiple times.
|
||||||
|
* This is TRUE when exposed filters grouped are using checkboxes as
|
||||||
|
* widgets.
|
||||||
|
*/
|
||||||
|
function multiple_exposed_input() { return FALSE; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take input from exposed handlers and assign to this handler, if necessary.
|
* Take input from exposed handlers and assign to this handler, if necessary.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -2789,8 +2789,15 @@ abstract class DisplayPluginBase extends Plugin {
|
||||||
foreach (View::views_object_types() as $type => $info) {
|
foreach (View::views_object_types() as $type => $info) {
|
||||||
foreach ($this->get_handlers($type) as $key => $handler) {
|
foreach ($this->get_handlers($type) as $key => $handler) {
|
||||||
if ($handler->can_expose() && $handler->is_exposed()) {
|
if ($handler->can_expose() && $handler->is_exposed()) {
|
||||||
if ($id != $key && $identifier == $handler->options['expose']['identifier']) {
|
if ($handler->is_a_group()) {
|
||||||
return FALSE;
|
if ($id != $key && $identifier == $handler->options['group_info']['identifier']) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($id != $key && $identifier == $handler->options['expose']['identifier']) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,9 @@ class BooleanOperator extends FilterPluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
function admin_summary() {
|
function admin_summary() {
|
||||||
|
if ($this->is_a_group()) {
|
||||||
|
return t('grouped');
|
||||||
|
}
|
||||||
if (!empty($this->options['exposed'])) {
|
if (!empty($this->options['exposed'])) {
|
||||||
return t('exposed');
|
return t('exposed');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,34 @@ class Date extends Numeric {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the build group options form.
|
||||||
|
*/
|
||||||
|
function build_group_validate($form, &$form_state) {
|
||||||
|
// Special case to validate grouped date filters, this is because the
|
||||||
|
// $group['value'] array contains the type of filter (date or offset)
|
||||||
|
// and therefore the number of items the comparission has to be done
|
||||||
|
// against 'one' instead of 'zero'.
|
||||||
|
foreach ($form_state['values']['options']['group_info']['group_items'] as $id => $group) {
|
||||||
|
if (empty($group['remove'])) {
|
||||||
|
// Check if the title is defined but value wasn't defined.
|
||||||
|
if (!empty($group['title'])) {
|
||||||
|
if ((!is_array($group['value']) && empty($group['value'])) || (is_array($group['value']) && count(array_filter($group['value'])) == 1)) {
|
||||||
|
form_error($form['group_info']['group_items'][$id]['value'], t('The value is required if title for this item is defined.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the value is defined but title wasn't defined.
|
||||||
|
if ((!is_array($group['value']) && !empty($group['value'])) || (is_array($group['value']) && count(array_filter($group['value'])) > 1)) {
|
||||||
|
if (empty($group['title'])) {
|
||||||
|
form_error($form['group_info']['group_items'][$id]['title'], t('The title is required if value for this item is defined.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function accept_exposed_input($input) {
|
function accept_exposed_input($input) {
|
||||||
if (empty($this->options['exposed'])) {
|
if (empty($this->options['exposed'])) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,11 @@ abstract class FilterPluginBase extends Handler {
|
||||||
*/
|
*/
|
||||||
var $operator = '=';
|
var $operator = '=';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the information of the selected item in a gruped filter.
|
||||||
|
*/
|
||||||
|
var $group_info = NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool
|
* @var bool
|
||||||
* Disable the possibility to force a single value.
|
* Disable the possibility to force a single value.
|
||||||
|
|
@ -78,6 +83,7 @@ abstract class FilterPluginBase extends Handler {
|
||||||
|
|
||||||
$this->operator = $this->options['operator'];
|
$this->operator = $this->options['operator'];
|
||||||
$this->value = $this->options['value'];
|
$this->value = $this->options['value'];
|
||||||
|
$this->group_info = $this->options['group_info']['default_group'];
|
||||||
|
|
||||||
// Compatibility: The new UI changed several settings.
|
// Compatibility: The new UI changed several settings.
|
||||||
if (!empty($options['exposed']) && !empty($options['expose']['optional']) && !isset($options['expose']['required'])) {
|
if (!empty($options['exposed']) && !empty($options['expose']['optional']) && !isset($options['expose']['required'])) {
|
||||||
|
|
@ -90,6 +96,11 @@ abstract class FilterPluginBase extends Handler {
|
||||||
$this->options['expose']['operator_id'] = $options['expose']['operator_id'] = $options['expose']['operator'];
|
$this->options['expose']['operator_id'] = $options['expose']['operator_id'] = $options['expose']['operator'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->multiple_exposed_input()) {
|
||||||
|
$this->group_info = array_filter($options['group_info']['default_group_multiple']);
|
||||||
|
$this->options['expose']['multiple'] = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// If there are relationships in the view, allow empty should be true
|
// If there are relationships in the view, allow empty should be true
|
||||||
// so that we can do IS NULL checks on items. Not all filters respect
|
// so that we can do IS NULL checks on items. Not all filters respect
|
||||||
// allow empty, but string and numeric do and that covers enough.
|
// allow empty, but string and numeric do and that covers enough.
|
||||||
|
|
@ -121,6 +132,29 @@ abstract class FilterPluginBase extends Handler {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// A group is a combination of a filter, an operator and a value
|
||||||
|
// operating like a single filter.
|
||||||
|
// Users can choose from a select box which group they want to apply.
|
||||||
|
// Views will filter the view according to the defined values.
|
||||||
|
// Because it acts as a standard filter, we have to define
|
||||||
|
// an identifier and other settings like the widget and the label.
|
||||||
|
// This settings are saved in another array to allow users to switch
|
||||||
|
// between a normal filter and a group of filters with a single click.
|
||||||
|
$options['is_grouped'] = array('default' => FALSE, 'bool' => TRUE);
|
||||||
|
$options['group_info'] = array(
|
||||||
|
'contains' => array(
|
||||||
|
'label' => array('default' => '', 'translatable' => TRUE),
|
||||||
|
'identifier' => array('default' => ''),
|
||||||
|
'optional' => array('default' => TRUE, 'bool' => TRUE),
|
||||||
|
'widget' => array('default' => 'select'),
|
||||||
|
'multiple' => array('default' => FALSE, 'bool' => TRUE),
|
||||||
|
'remember' => array('default' => 0),
|
||||||
|
'default_group' => array('default' => 'All'),
|
||||||
|
'default_group_multiple' => array('default' => array()),
|
||||||
|
'group_items' => array('default' => array()),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return $options;
|
return $options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,6 +170,21 @@ abstract class FilterPluginBase extends Handler {
|
||||||
*/
|
*/
|
||||||
function can_expose() { return TRUE; }
|
function can_expose() { return TRUE; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if a filter can be converted into a group.
|
||||||
|
* Only exposed filters with operators available can be converted into groups.
|
||||||
|
*/
|
||||||
|
function can_build_group() {
|
||||||
|
return $this->is_exposed() && (count($this->operator_options()) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if the exposed filter works like a grouped filter.
|
||||||
|
*/
|
||||||
|
function is_a_group() {
|
||||||
|
return !empty($this->options['is_grouped']);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide the basic form which calls through to subforms.
|
* Provide the basic form which calls through to subforms.
|
||||||
* If overridden, it is best to call through to the parent,
|
* If overridden, it is best to call through to the parent,
|
||||||
|
|
@ -147,19 +196,36 @@ abstract class FilterPluginBase extends Handler {
|
||||||
if ($this->can_expose()) {
|
if ($this->can_expose()) {
|
||||||
$this->show_expose_button($form, $form_state);
|
$this->show_expose_button($form, $form_state);
|
||||||
}
|
}
|
||||||
|
if ($this->can_build_group()) {
|
||||||
|
$this->show_build_group_button($form, $form_state);
|
||||||
|
}
|
||||||
$form['clear_markup_start'] = array(
|
$form['clear_markup_start'] = array(
|
||||||
'#markup' => '<div class="clearfix">',
|
'#markup' => '<div class="clearfix">',
|
||||||
);
|
);
|
||||||
// Add the subform from operator_form().
|
if ($this->is_a_group()) {
|
||||||
$this->show_operator_form($form, $form_state);
|
if ($this->can_build_group()) {
|
||||||
// Add the subform from value_form().
|
$form['clear_markup_start'] = array(
|
||||||
$this->show_value_form($form, $form_state);
|
'#markup' => '<div class="clearfix">',
|
||||||
$form['clear_markup_end'] = array(
|
);
|
||||||
'#markup' => '</div>',
|
// Render the build group form.
|
||||||
);
|
$this->show_build_group_form($form, $form_state);
|
||||||
if ($this->can_expose()) {
|
$form['clear_markup_end'] = array(
|
||||||
// Add the subform from expose_form().
|
'#markup' => '</div>',
|
||||||
$this->show_expose_form($form, $form_state);
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Add the subform from operator_form().
|
||||||
|
$this->show_operator_form($form, $form_state);
|
||||||
|
// Add the subform from value_form().
|
||||||
|
$this->show_value_form($form, $form_state);
|
||||||
|
$form['clear_markup_end'] = array(
|
||||||
|
'#markup' => '</div>',
|
||||||
|
);
|
||||||
|
if ($this->can_expose()) {
|
||||||
|
// Add the subform from expose_form().
|
||||||
|
$this->show_expose_form($form, $form_state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,9 +235,12 @@ abstract class FilterPluginBase extends Handler {
|
||||||
function options_validate(&$form, &$form_state) {
|
function options_validate(&$form, &$form_state) {
|
||||||
$this->operator_validate($form, $form_state);
|
$this->operator_validate($form, $form_state);
|
||||||
$this->value_validate($form, $form_state);
|
$this->value_validate($form, $form_state);
|
||||||
if (!empty($this->options['exposed'])) {
|
if (!empty($this->options['exposed']) && !$this->is_a_group()) {
|
||||||
$this->expose_validate($form, $form_state);
|
$this->expose_validate($form, $form_state);
|
||||||
}
|
}
|
||||||
|
if ($this->is_a_group()) {
|
||||||
|
$this->build_group_validate($form, $form_state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -179,11 +248,17 @@ abstract class FilterPluginBase extends Handler {
|
||||||
*/
|
*/
|
||||||
function options_submit(&$form, &$form_state) {
|
function options_submit(&$form, &$form_state) {
|
||||||
unset($form_state['values']['expose_button']); // don't store this.
|
unset($form_state['values']['expose_button']); // don't store this.
|
||||||
$this->operator_submit($form, $form_state);
|
unset($form_state['values']['group_button']); // don't store this.
|
||||||
$this->value_submit($form, $form_state);
|
if (!$this->is_a_group()) {
|
||||||
|
$this->operator_submit($form, $form_state);
|
||||||
|
$this->value_submit($form, $form_state);
|
||||||
|
}
|
||||||
if (!empty($this->options['exposed'])) {
|
if (!empty($this->options['exposed'])) {
|
||||||
$this->expose_submit($form, $form_state);
|
$this->expose_submit($form, $form_state);
|
||||||
}
|
}
|
||||||
|
if ($this->is_a_group()) {
|
||||||
|
$this->build_group_submit($form, $form_state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -264,6 +339,78 @@ abstract class FilterPluginBase extends Handler {
|
||||||
*/
|
*/
|
||||||
function value_submit($form, &$form_state) { }
|
function value_submit($form, &$form_state) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut to display the exposed options form.
|
||||||
|
*/
|
||||||
|
function show_build_group_form(&$form, &$form_state) {
|
||||||
|
if (empty($this->options['is_grouped'])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->build_group_form($form, $form_state);
|
||||||
|
|
||||||
|
// When we click the expose button, we add new gadgets to the form but they
|
||||||
|
// have no data in $_POST so their defaults get wiped out. This prevents
|
||||||
|
// these defaults from getting wiped out. This setting will only be TRUE
|
||||||
|
// during a 2nd pass rerender.
|
||||||
|
if (!empty($form_state['force_build_group_options'])) {
|
||||||
|
foreach (element_children($form['group_info']) as $id) {
|
||||||
|
if (isset($form['group_info'][$id]['#default_value']) && !isset($form['group_info'][$id]['#value'])) {
|
||||||
|
$form['group_info'][$id]['#value'] = $form['group_info'][$id]['#default_value'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut to display the build_group/hide button.
|
||||||
|
*/
|
||||||
|
function show_build_group_button(&$form, &$form_state) {
|
||||||
|
|
||||||
|
$form['group_button'] = array(
|
||||||
|
'#prefix' => '<div class="views-grouped clearfix">',
|
||||||
|
'#suffix' => '</div>',
|
||||||
|
// Should always come after the description and the relationship.
|
||||||
|
'#weight' => -190,
|
||||||
|
);
|
||||||
|
|
||||||
|
$grouped_description = t('Grouped filters allow a choice between predefined operator|value pairs.');
|
||||||
|
$form['group_button']['radios'] = array(
|
||||||
|
'#theme_wrappers' => array('container'),
|
||||||
|
'#attributes' => array('class' => array('js-only')),
|
||||||
|
);
|
||||||
|
$form['group_button']['radios']['radios'] = array(
|
||||||
|
'#title' => t('Filter type to expose'),
|
||||||
|
'#description' => $grouped_description,
|
||||||
|
'#type' => 'radios',
|
||||||
|
'#options' => array(
|
||||||
|
t('Single filter'),
|
||||||
|
t('Grouped filters'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (empty($this->options['is_grouped'])) {
|
||||||
|
$form['group_button']['markup'] = array(
|
||||||
|
'#markup' => '<div class="description grouped-description">' . $grouped_description . '</div>',
|
||||||
|
);
|
||||||
|
$form['group_button']['button'] = array(
|
||||||
|
'#limit_validation_errors' => array(),
|
||||||
|
'#type' => 'submit',
|
||||||
|
'#value' => t('Grouped filters'),
|
||||||
|
'#submit' => array('views_ui_config_item_form_build_group'),
|
||||||
|
);
|
||||||
|
$form['group_button']['radios']['radios']['#default_value'] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$form['group_button']['button'] = array(
|
||||||
|
'#limit_validation_errors' => array(),
|
||||||
|
'#type' => 'submit',
|
||||||
|
'#value' => t('Single filter'),
|
||||||
|
'#submit' => array('views_ui_config_item_form_build_group'),
|
||||||
|
);
|
||||||
|
$form['group_button']['radios']['radios']['#default_value'] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Shortcut to display the expose/hide button.
|
* Shortcut to display the expose/hide button.
|
||||||
*/
|
*/
|
||||||
|
|
@ -437,6 +584,81 @@ abstract class FilterPluginBase extends Handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the build group options form.
|
||||||
|
*/
|
||||||
|
function build_group_validate($form, &$form_state) {
|
||||||
|
if (empty($form_state['values']['options']['group_info']['identifier'])) {
|
||||||
|
form_error($form['group_info']['identifier'], t('The identifier is required if the filter is exposed.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($form_state['values']['options']['group_info']['identifier']) && $form_state['values']['options']['group_info']['identifier'] == 'value') {
|
||||||
|
form_error($form['group_info']['identifier'], t('This identifier is not allowed.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->view->display_handler->is_identifier_unique($form_state['id'], $form_state['values']['options']['group_info']['identifier'])) {
|
||||||
|
form_error($form['group_info']['identifier'], t('This identifier is used by another handler.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($form_state['values']['options']['group_info']['group_items'])) {
|
||||||
|
foreach ($form_state['values']['options']['group_info']['group_items'] as $id => $group) {
|
||||||
|
if (empty($group['remove'])) {
|
||||||
|
|
||||||
|
// Check if the title is defined but value wasn't defined.
|
||||||
|
if (!empty($group['title'])) {
|
||||||
|
if ((!is_array($group['value']) && trim($group['value']) == "") ||
|
||||||
|
(is_array($group['value']) && count(array_filter($group['value'], '_views_array_filter_zero')) == 0)) {
|
||||||
|
form_error($form['group_info']['group_items'][$id]['value'],
|
||||||
|
t('The value is required if title for this item is defined.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the value is defined but title wasn't defined.
|
||||||
|
if ((!is_array($group['value']) && trim($group['value']) != "") ||
|
||||||
|
(is_array($group['value']) && count(array_filter($group['value'], '_views_array_filter_zero')) > 0)) {
|
||||||
|
if (empty($group['title'])) {
|
||||||
|
form_error($form['group_info']['group_items'][$id]['title'],
|
||||||
|
t('The title is required if value for this item is defined.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save new group items, re-enumerates and remove groups marked to delete.
|
||||||
|
*/
|
||||||
|
function build_group_submit($form, &$form_state) {
|
||||||
|
$groups = array();
|
||||||
|
uasort($form_state['values']['options']['group_info']['group_items'], 'drupal_sort_weight');
|
||||||
|
// Filter out removed items.
|
||||||
|
|
||||||
|
// Start from 1 to avoid problems with #default_value in the widget.
|
||||||
|
$new_id = 1;
|
||||||
|
$new_default = 'All';
|
||||||
|
foreach ($form_state['values']['options']['group_info']['group_items'] as $id => $group) {
|
||||||
|
if (empty($group['remove'])) {
|
||||||
|
// Don't store this.
|
||||||
|
unset($group['remove']);
|
||||||
|
unset($group['weight']);
|
||||||
|
$groups[$new_id] = $group;
|
||||||
|
|
||||||
|
if ($form_state['values']['options']['group_info']['default_group'] === $id) {
|
||||||
|
$new_default = $new_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$new_id++;
|
||||||
|
}
|
||||||
|
if ($new_default != 'All') {
|
||||||
|
$form_state['values']['options']['group_info']['default_group'] = $new_default;
|
||||||
|
}
|
||||||
|
$filter_default_multiple = array_filter($form_state['values']['options']['group_info']['default_group_multiple']);
|
||||||
|
$form_state['values']['options']['group_info']['default_group_multiple'] = $filter_default_multiple;
|
||||||
|
|
||||||
|
$form_state['values']['options']['group_info']['group_items'] = $groups;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide default options for exposed filters.
|
* Provide default options for exposed filters.
|
||||||
*/
|
*/
|
||||||
|
|
@ -452,6 +674,68 @@ abstract class FilterPluginBase extends Handler {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide default options for exposed filters.
|
||||||
|
*/
|
||||||
|
function build_group_options() {
|
||||||
|
$this->options['group_info'] = array(
|
||||||
|
'label' => $this->definition['title'],
|
||||||
|
'identifier' => $this->options['id'],
|
||||||
|
'optional' => TRUE,
|
||||||
|
'widget' => 'select',
|
||||||
|
'multiple' => FALSE,
|
||||||
|
'remember' => FALSE,
|
||||||
|
'default_group' => 'All',
|
||||||
|
'default_group_multiple' => array(),
|
||||||
|
'group_items' => array(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a form containing a group of operator | values to apply as a
|
||||||
|
* single filter.
|
||||||
|
*/
|
||||||
|
function group_form(&$form, &$form_state) {
|
||||||
|
if (!empty($this->options['group_info']['optional']) && !$this->multiple_exposed_input()) {
|
||||||
|
|
||||||
|
$old_any = $this->options['group_info']['widget'] == 'select' ? '<Any>' : '<Any>';
|
||||||
|
$any_label = variable_get('views_exposed_filter_any_label', 'new_any') == 'old_any' ? $old_any : t('- Any -');
|
||||||
|
$groups = array('All' => $any_label);
|
||||||
|
}
|
||||||
|
foreach ($this->options['group_info']['group_items'] as $id => $group) {
|
||||||
|
if (!empty($group['title'])) {
|
||||||
|
$groups[$id] = $id != 'All' ? t($group['title']) : $group['title'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($groups)) {
|
||||||
|
$value = $this->options['group_info']['identifier'];
|
||||||
|
|
||||||
|
$form[$value] = array(
|
||||||
|
'#type' => $this->options['group_info']['widget'],
|
||||||
|
'#default_value' => $this->group_info,
|
||||||
|
'#options' => $groups,
|
||||||
|
);
|
||||||
|
if (!empty($this->options['group_info']['multiple'])) {
|
||||||
|
if (count($groups) < 5) {
|
||||||
|
$form[$value]['#type'] = 'checkboxes';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$form[$value]['#type'] = 'select';
|
||||||
|
$form[$value]['#size'] = 5;
|
||||||
|
$form[$value]['#multiple'] = TRUE;
|
||||||
|
}
|
||||||
|
unset($form[$value]['#default_value']);
|
||||||
|
if (empty($form_state['input'])) {
|
||||||
|
$form_state['input'][$value] = $this->group_info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->options['expose']['label'] = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render our chunk of the exposed filter form when selecting
|
* Render our chunk of the exposed filter form when selecting
|
||||||
*
|
*
|
||||||
|
|
@ -503,6 +787,247 @@ abstract class FilterPluginBase extends Handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the form to let users create the group of exposed filters.
|
||||||
|
* This form is displayed when users click on button 'Build group'
|
||||||
|
*/
|
||||||
|
function build_group_form(&$form, &$form_state) {
|
||||||
|
if (empty($this->options['exposed']) || empty($this->options['is_grouped'])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$form['#theme'] = 'views_ui_build_group_filter_form';
|
||||||
|
|
||||||
|
// #flatten will move everything from $form['group_info'][$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['group_info']['#flatten'] = TRUE;
|
||||||
|
|
||||||
|
if (!empty($this->options['group_info']['identifier'])) {
|
||||||
|
$identifier = $this->options['group_info']['identifier'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$identifier = 'group_' . $this->options['expose']['identifier'];
|
||||||
|
}
|
||||||
|
$form['group_info']['identifier'] = array(
|
||||||
|
'#type' => 'textfield',
|
||||||
|
'#default_value' => $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',
|
||||||
|
);
|
||||||
|
$form['group_info']['label'] = array(
|
||||||
|
'#type' => 'textfield',
|
||||||
|
'#default_value' => $this->options['group_info']['label'],
|
||||||
|
'#title' => t('Label'),
|
||||||
|
'#size' => 40,
|
||||||
|
);
|
||||||
|
$form['group_info']['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['group_info']['optional'],
|
||||||
|
);
|
||||||
|
$form['group_info']['multiple'] = array(
|
||||||
|
'#type' => 'checkbox',
|
||||||
|
'#title' => t('Allow multiple selections'),
|
||||||
|
'#description' => t('Enable to allow users to select multiple items.'),
|
||||||
|
'#default_value' => $this->options['group_info']['multiple'],
|
||||||
|
);
|
||||||
|
$form['group_info']['widget'] = array(
|
||||||
|
'#type' => 'radios',
|
||||||
|
'#default_value' => $this->options['group_info']['widget'],
|
||||||
|
'#title' => t('Widget type'),
|
||||||
|
'#options' => array(
|
||||||
|
'radios' => t('Radios'),
|
||||||
|
'select' => t('Select'),
|
||||||
|
),
|
||||||
|
'#description' => t('Select which kind of widget will be used to render the group of filters'),
|
||||||
|
);
|
||||||
|
$form['group_info']['remember'] = array(
|
||||||
|
'#type' => 'checkbox',
|
||||||
|
'#title' => t('Remember'),
|
||||||
|
'#description' => t('Remember the last setting the user gave this filter.'),
|
||||||
|
'#default_value' => $this->options['group_info']['remember'],
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!empty($this->options['group_info']['identifier'])) {
|
||||||
|
$identifier = $this->options['group_info']['identifier'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$identifier = 'group_' . $this->options['expose']['identifier'];
|
||||||
|
}
|
||||||
|
$form['group_info']['identifier'] = array(
|
||||||
|
'#type' => 'textfield',
|
||||||
|
'#default_value' => $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',
|
||||||
|
);
|
||||||
|
$form['group_info']['label'] = array(
|
||||||
|
'#type' => 'textfield',
|
||||||
|
'#default_value' => $this->options['group_info']['label'],
|
||||||
|
'#title' => t('Label'),
|
||||||
|
'#size' => 40,
|
||||||
|
);
|
||||||
|
$form['group_info']['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['group_info']['optional'],
|
||||||
|
);
|
||||||
|
$form['group_info']['widget'] = array(
|
||||||
|
'#type' => 'radios',
|
||||||
|
'#default_value' => $this->options['group_info']['widget'],
|
||||||
|
'#title' => t('Widget type'),
|
||||||
|
'#options' => array(
|
||||||
|
'radios' => t('Radios'),
|
||||||
|
'select' => t('Select'),
|
||||||
|
),
|
||||||
|
'#description' => t('Select which kind of widget will be used to render the group of filters'),
|
||||||
|
);
|
||||||
|
$form['group_info']['remember'] = array(
|
||||||
|
'#type' => 'checkbox',
|
||||||
|
'#title' => t('Remember'),
|
||||||
|
'#description' => t('Remember the last setting the user gave this filter.'),
|
||||||
|
'#default_value' => $this->options['group_info']['remember'],
|
||||||
|
);
|
||||||
|
|
||||||
|
$groups = array('All' => '- Any -'); // The string '- Any -' will not be rendered see @theme_views_ui_build_group_filter_form
|
||||||
|
|
||||||
|
// Provide 3 options to start when we are in a new group.
|
||||||
|
if (count($this->options['group_info']['group_items']) == 0) {
|
||||||
|
$this->options['group_info']['group_items'] = array_fill(1, 3, array());
|
||||||
|
}
|
||||||
|
|
||||||
|
// After the general settings, comes a table with all the existent groups.
|
||||||
|
$default_weight = 0;
|
||||||
|
foreach ($this->options['group_info']['group_items'] as $item_id => $item) {
|
||||||
|
if (!empty($form_state['values']['options']['group_info']['group_items'][$item_id]['remove'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Each rows contains three widgets:
|
||||||
|
// a) The title, where users define how they identify a pair of operator | value
|
||||||
|
// b) The operator
|
||||||
|
// c) The value (or values) to use in the filter with the selected operator
|
||||||
|
|
||||||
|
// In each row, we have to display the operator form and the value from
|
||||||
|
// $row acts as a fake form to render each widget in a row.
|
||||||
|
$row = array();
|
||||||
|
$groups[$item_id] = '';
|
||||||
|
$this->operator_form($row, $form_state);
|
||||||
|
// Force the operator form to be a select box. Some handlers uses
|
||||||
|
// radios and they occupy a lot of space in a table row.
|
||||||
|
$row['operator']['#type'] = 'select';
|
||||||
|
$row['operator']['#title'] = '';
|
||||||
|
$this->value_form($row, $form_state);
|
||||||
|
|
||||||
|
// Fix the dependencies to update value forms when operators
|
||||||
|
// changes. This is needed because forms are inside a new form and
|
||||||
|
// their ids changes. Dependencies are used when operator changes
|
||||||
|
// from to 'Between', 'Not Between', etc, and two or more widgets
|
||||||
|
// are displayed.
|
||||||
|
$without_children = TRUE;
|
||||||
|
foreach (element_children($row['value']) as $children) {
|
||||||
|
if (isset($row['value'][$children]['#dependency']['edit-options-operator'])) {
|
||||||
|
$row['value'][$children]['#dependency']["edit-options-group-info-group-items-$item_id-operator"] = $row['value'][$children]['#dependency']['edit-options-operator'];
|
||||||
|
unset($row['value'][$children]['#dependency']['edit-options-operator']);
|
||||||
|
$row['value'][$children]['#title'] = '';
|
||||||
|
|
||||||
|
if (!empty($this->options['group_info']['group_items'][$item_id]['value'][$children])) {
|
||||||
|
$row['value'][$children]['#default_value'] = $this->options['group_info']['group_items'][$item_id]['value'][$children];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$without_children = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($without_children) {
|
||||||
|
if (!empty($this->options['group_info']['group_items'][$item_id]['value'])) {
|
||||||
|
$row['value']['#default_value'] = $this->options['group_info']['group_items'][$item_id]['value'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($this->options['group_info']['group_items'][$item_id]['operator'])) {
|
||||||
|
$row['operator']['#default_value'] = $this->options['group_info']['group_items'][$item_id]['operator'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$default_title = '';
|
||||||
|
if (!empty($this->options['group_info']['group_items'][$item_id]['title'])) {
|
||||||
|
$default_title = $this->options['group_info']['group_items'][$item_id]['title'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per item group, we have a title that identifies it.
|
||||||
|
$form['group_info']['group_items'][$item_id] = array(
|
||||||
|
'title' => array(
|
||||||
|
'#type' => 'textfield',
|
||||||
|
'#size' => 20,
|
||||||
|
'#default_value' => $default_title,
|
||||||
|
),
|
||||||
|
'operator' => $row['operator'],
|
||||||
|
'value' => $row['value'],
|
||||||
|
'remove' => array(
|
||||||
|
'#type' => 'checkbox',
|
||||||
|
'#id' => 'views-removed-' . $item_id,
|
||||||
|
'#attributes' => array('class' => array('views-remove-checkbox')),
|
||||||
|
'#default_value' => 0,
|
||||||
|
),
|
||||||
|
'weight' => array(
|
||||||
|
'#type' => 'weight',
|
||||||
|
'#delta' => 10,
|
||||||
|
'#default_value' => $default_weight++,
|
||||||
|
'#attributes' => array('class' => array('weight')),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// From all groups, let chose which is the default.
|
||||||
|
$form['group_info']['default_group'] = array(
|
||||||
|
'#type' => 'radios',
|
||||||
|
'#options' => $groups,
|
||||||
|
'#default_value' => $this->options['group_info']['default_group'],
|
||||||
|
'#required' => TRUE,
|
||||||
|
'#attributes' => array(
|
||||||
|
'class' => array('default-radios'),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// From all groups, let chose which is the default.
|
||||||
|
$form['group_info']['default_group_multiple'] = array(
|
||||||
|
'#type' => 'checkboxes',
|
||||||
|
'#options' => $groups,
|
||||||
|
'#default_value' => $this->options['group_info']['default_group_multiple'],
|
||||||
|
'#attributes' => array(
|
||||||
|
'class' => array('default-checkboxes'),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$form['group_info']['add_group'] = array(
|
||||||
|
'#prefix' => '<div class="views-build-group clear-block">',
|
||||||
|
'#suffix' => '</div>',
|
||||||
|
'#type' => 'submit',
|
||||||
|
'#value' => t('Add another item'),
|
||||||
|
'#submit' => array('views_ui_config_item_form_add_group'),
|
||||||
|
);
|
||||||
|
|
||||||
|
$js = array();
|
||||||
|
$js['tableDrag']['views-filter-groups']['weight'][0] = array(
|
||||||
|
'target' => 'weight',
|
||||||
|
'source' => NULL,
|
||||||
|
'relationship' => 'sibling',
|
||||||
|
'action' => 'order',
|
||||||
|
'hidden' => TRUE,
|
||||||
|
'limit' => 0,
|
||||||
|
);
|
||||||
|
if (!empty($form_state['js settings']) && is_array($js)) {
|
||||||
|
$form_state['js settings'] = array_merge($form_state['js settings'], $js);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$form_state['js settings'] = $js;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make some translations to a form item to make it more suitable to
|
* Make some translations to a form item to make it more suitable to
|
||||||
* exposing.
|
* exposing.
|
||||||
|
|
@ -574,16 +1099,26 @@ abstract class FilterPluginBase extends Handler {
|
||||||
* overridden for particularly complex forms. And maybe not even then.
|
* overridden for particularly complex forms. And maybe not even then.
|
||||||
*
|
*
|
||||||
* @return array|null
|
* @return array|null
|
||||||
* An array with the following keys:
|
* For standard exposed filters. An array with the following keys:
|
||||||
* - operator: The $form key of the operator. Set to NULL if no operator.
|
* - operator: The $form key of the operator. Set to NULL if no operator.
|
||||||
* - value: The $form key of the value. Set to NULL if no value.
|
* - value: The $form key of the value. Set to NULL if no value.
|
||||||
* - label: The label to use for this piece.
|
* - label: The label to use for this piece.
|
||||||
|
* For grouped exposed filters. An array with the following keys:
|
||||||
|
* - value: The $form key of the value. Set to NULL if no value.
|
||||||
|
* - label: The label to use for this piece.
|
||||||
*/
|
*/
|
||||||
function exposed_info() {
|
function exposed_info() {
|
||||||
if (empty($this->options['exposed'])) {
|
if (empty($this->options['exposed'])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->is_a_group()) {
|
||||||
|
return array(
|
||||||
|
'value' => $this->options['group_info']['identifier'],
|
||||||
|
'label' => $this->options['group_info']['label'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'operator' => $this->options['expose']['operator_id'],
|
'operator' => $this->options['expose']['operator_id'],
|
||||||
'value' => $this->options['expose']['identifier'],
|
'value' => $this->options['expose']['identifier'],
|
||||||
|
|
@ -591,6 +1126,110 @@ abstract class FilterPluginBase extends Handler {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Transform the input from a grouped filter into a standard filter.
|
||||||
|
*
|
||||||
|
* When a filter is a group, find the set of operator and values
|
||||||
|
* that the choosed item represents, and inform views that a normal
|
||||||
|
* filter was submitted by telling the operator and the value selected.
|
||||||
|
*
|
||||||
|
* The param $selected_group_id is only passed when the filter uses the
|
||||||
|
* checkboxes widget, and this function will be called for each item
|
||||||
|
* choosed in the checkboxes.
|
||||||
|
*/
|
||||||
|
function convert_exposed_input(&$input, $selected_group_id = NULL) {
|
||||||
|
if ($this->is_a_group()) {
|
||||||
|
// If it is already defined the selected group, use it. Only valid
|
||||||
|
// when the filter uses checkboxes for widget.
|
||||||
|
if (!empty($selected_group_id)) {
|
||||||
|
$selected_group = $selected_group_id;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$selected_group = $input[$this->options['group_info']['identifier']];
|
||||||
|
}
|
||||||
|
if ($selected_group == 'All' && !empty($this->options['group_info']['optional'])) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ($selected_group != 'All' && empty($this->options['group_info']['group_items'][$selected_group])) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (isset($selected_group) && isset($this->options['group_info']['group_items'][$selected_group])) {
|
||||||
|
$input[$this->options['expose']['operator']] = $this->options['group_info']['group_items'][$selected_group]['operator'];
|
||||||
|
|
||||||
|
// Value can be optional, For example for 'empty' and 'not empty' filters.
|
||||||
|
if (!empty($this->options['group_info']['group_items'][$selected_group]['value'])) {
|
||||||
|
$input[$this->options['expose']['identifier']] = $this->options['group_info']['group_items'][$selected_group]['value'];
|
||||||
|
}
|
||||||
|
$this->options['expose']['use_operator'] = TRUE;
|
||||||
|
|
||||||
|
$this->group_info = $input[$this->options['group_info']['identifier']];
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the options available for a grouped filter that users checkboxes
|
||||||
|
* as widget, and therefore has to be applied several times, one per
|
||||||
|
* item selected.
|
||||||
|
*/
|
||||||
|
function group_multiple_exposed_input(&$input) {
|
||||||
|
if (!empty($input[$this->options['group_info']['identifier']])) {
|
||||||
|
return array_filter($input[$this->options['group_info']['identifier']]);
|
||||||
|
}
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if users can select multiple groups items of a
|
||||||
|
* grouped exposed filter.
|
||||||
|
*/
|
||||||
|
function multiple_exposed_input() {
|
||||||
|
return $this->is_a_group() && !empty($this->options['group_info']['multiple']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to remember exposed input in the session, store it there.
|
||||||
|
* This function is similar to store_exposed_input but modified to
|
||||||
|
* work properly when the filter is a group.
|
||||||
|
*/
|
||||||
|
function store_group_input($input, $status) {
|
||||||
|
if (!$this->is_a_group() || empty($this->options['group_info']['identifier'])) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($this->options['group_info']['remember'])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out which display id is responsible for the filters, so we
|
||||||
|
// know where to look for session stored values.
|
||||||
|
$display_id = ($this->view->display_handler->is_defaulted('filters')) ? 'default' : $this->view->current_display;
|
||||||
|
|
||||||
|
// false means that we got a setting that means to recuse ourselves,
|
||||||
|
// so we should erase whatever happened to be there.
|
||||||
|
if ($status === FALSE && isset($_SESSION['views'][$this->view->name][$display_id])) {
|
||||||
|
$session = &$_SESSION['views'][$this->view->name][$display_id];
|
||||||
|
|
||||||
|
if (isset($session[$this->options['group_info']['identifier']])) {
|
||||||
|
unset($session[$this->options['group_info']['identifier']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($status !== FALSE) {
|
||||||
|
if (!isset($_SESSION['views'][$this->view->name][$display_id])) {
|
||||||
|
$_SESSION['views'][$this->view->name][$display_id] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$session = &$_SESSION['views'][$this->view->name][$display_id];
|
||||||
|
|
||||||
|
$session[$this->options['group_info']['identifier']] = $input[$this->options['group_info']['identifier']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if input from the exposed filters should change
|
* Check to see if input from the exposed filters should change
|
||||||
* the behavior of this filter.
|
* the behavior of this filter.
|
||||||
|
|
|
||||||
|
|
@ -304,6 +304,9 @@ class InOperator extends FilterPluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
function admin_summary() {
|
function admin_summary() {
|
||||||
|
if ($this->is_a_group()) {
|
||||||
|
return t('grouped');
|
||||||
|
}
|
||||||
if (!empty($this->options['exposed'])) {
|
if (!empty($this->options['exposed'])) {
|
||||||
return t('exposed');
|
return t('exposed');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,9 @@ class Numeric extends FilterPluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
function admin_summary() {
|
function admin_summary() {
|
||||||
|
if ($this->is_a_group()) {
|
||||||
|
return t('grouped');
|
||||||
|
}
|
||||||
if (!empty($this->options['exposed'])) {
|
if (!empty($this->options['exposed'])) {
|
||||||
return t('exposed');
|
return t('exposed');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,9 @@ class String extends FilterPluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
function admin_summary() {
|
function admin_summary() {
|
||||||
|
if ($this->is_a_group()) {
|
||||||
|
return t('grouped');
|
||||||
|
}
|
||||||
if (!empty($this->options['exposed'])) {
|
if (!empty($this->options['exposed'])) {
|
||||||
return t('exposed');
|
return t('exposed');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ namespace Drupal\views\Tests;
|
||||||
*/
|
*/
|
||||||
class ExposedFormTest extends ViewsSqlTest {
|
class ExposedFormTest extends ViewsSqlTest {
|
||||||
|
|
||||||
|
protected $profile = 'standard';
|
||||||
|
|
||||||
public static function getInfo() {
|
public static function getInfo() {
|
||||||
return array(
|
return array(
|
||||||
'name' => 'Exposed forms',
|
'name' => 'Exposed forms',
|
||||||
|
|
@ -20,15 +22,6 @@ class ExposedFormTest extends ViewsSqlTest {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUp() {
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
// @TODO Figure out why it's required to clear the cache here.
|
|
||||||
views_module_include('views_default', TRUE);
|
|
||||||
views_get_all_views(TRUE);
|
|
||||||
menu_router_rebuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests, whether and how the reset button can be renamed.
|
* Tests, whether and how the reset button can be renamed.
|
||||||
*/
|
*/
|
||||||
|
|
@ -69,13 +62,15 @@ class ExposedFormTest extends ViewsSqlTest {
|
||||||
$edit = array();
|
$edit = array();
|
||||||
|
|
||||||
$this->drupalGet('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/filter/type');
|
$this->drupalGet('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/filter/type');
|
||||||
// Be sure that the button is called exposed
|
// Be sure that the button is called exposed.
|
||||||
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Expose filter'));
|
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Expose filter'));
|
||||||
|
|
||||||
// Click the Expose filter button.
|
// Click the Expose filter button.
|
||||||
$this->drupalPost('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/filter/type', $edit, t('Expose filter'));
|
$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
|
// Check the label of the expose button.
|
||||||
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Hide filter'));
|
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Hide filter'));
|
||||||
|
// Check the label of the grouped exposed button
|
||||||
|
$this->helperButtonHasLabel('edit-options-group-button-button', t('Grouped filters'));
|
||||||
|
|
||||||
// Check the validations of the filter handler.
|
// Check the validations of the filter handler.
|
||||||
$edit = array();
|
$edit = array();
|
||||||
|
|
@ -93,11 +88,49 @@ class ExposedFormTest extends ViewsSqlTest {
|
||||||
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Expose sort'));
|
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Expose sort'));
|
||||||
$this->assertNoFieldById('edit-options-expose-label', '', t('Make sure no label field is shown'));
|
$this->assertNoFieldById('edit-options-expose-label', '', t('Make sure no label field is shown'));
|
||||||
|
|
||||||
|
// Click the Grouped Filters button.
|
||||||
|
$this->drupalGet('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/filter/type');
|
||||||
|
$this->drupalPost(NULL, array(), t('Grouped filters'));
|
||||||
|
// Check that after click on 'Grouped Filters', a new button is shown to
|
||||||
|
// add more items to the list.
|
||||||
|
$this->helperButtonHasLabel('edit-options-group-info-add-group', t('Add another item'));
|
||||||
|
|
||||||
|
// Create a grouped filter
|
||||||
|
$this->drupalGet('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/filter/type');
|
||||||
|
$edit = array();
|
||||||
|
$edit["options[group_info][group_items][1][title]"] = 'Is Article';
|
||||||
|
$edit["options[group_info][group_items][1][value][article]"] = 'article';
|
||||||
|
|
||||||
|
$edit["options[group_info][group_items][2][title]"] = 'Is Page';
|
||||||
|
$edit["options[group_info][group_items][2][value][page]"] = TRUE;
|
||||||
|
|
||||||
|
$edit["options[group_info][group_items][3][title]"] = 'Is Page and Article';
|
||||||
|
$edit["options[group_info][group_items][3][value][article]"] = TRUE;
|
||||||
|
$edit["options[group_info][group_items][3][value][page]"] = TRUE;
|
||||||
|
$this->drupalPost(NULL, $edit, t('Apply'));
|
||||||
|
|
||||||
|
// Validate that all the titles are defined for each group
|
||||||
|
$this->drupalGet('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/filter/type');
|
||||||
|
$edit = array();
|
||||||
|
$edit["options[group_info][group_items][1][title]"] = 'Is Article';
|
||||||
|
$edit["options[group_info][group_items][1][value][article]"] = TRUE;
|
||||||
|
|
||||||
|
// This should trigger an error
|
||||||
|
$edit["options[group_info][group_items][2][title]"] = '';
|
||||||
|
$edit["options[group_info][group_items][2][value][page]"] = TRUE;
|
||||||
|
|
||||||
|
$edit["options[group_info][group_items][3][title]"] = 'Is Page and Article';
|
||||||
|
$edit["options[group_info][group_items][3][value][article]"] = TRUE;
|
||||||
|
$edit["options[group_info][group_items][3][value][page]"] = TRUE;
|
||||||
|
$this->drupalPost(NULL, $edit, t('Apply'));
|
||||||
|
$this->assertRaw(t('The title is required if value for this item is defined.'), t('Group items should have a title'));
|
||||||
|
|
||||||
// Click the Expose sort button.
|
// Click the Expose sort button.
|
||||||
$edit = array();
|
$edit = array();
|
||||||
$this->drupalPost('admin/structure/views/nojs/config-item/test_exposed_admin_ui/default/sort/created', $edit, t('Expose sort'));
|
$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
|
// Check the label of the expose button.
|
||||||
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Hide sort'));
|
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Hide sort'));
|
||||||
$this->assertFieldById('edit-options-expose-label', '', t('Make sure a label field is shown'));
|
$this->assertFieldById('edit-options-expose-label', '', t('Make sure a label field is shown'));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,24 @@ class FilterEqualityTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testEqualGroupedExposed() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Name, Operator: =, Value: Ringo
|
||||||
|
$filters['name']['group_info']['default_group'] = 1;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'Ringo',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
function testNotEqual() {
|
function testNotEqual() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -91,4 +109,69 @@ class FilterEqualityTest extends ViewsSqlTest {
|
||||||
);
|
);
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testEqualGroupedNotExposed() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Name, Operator: !=, Value: Ringo
|
||||||
|
$filters['name']['group_info']['default_group'] = 2;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'John',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'George',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Paul',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Meredith',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected function getGroupedExposedFilters() {
|
||||||
|
$filters = array(
|
||||||
|
'name' => array(
|
||||||
|
'id' => 'name',
|
||||||
|
'table' => 'views_test',
|
||||||
|
'field' => 'name',
|
||||||
|
'relationship' => 'none',
|
||||||
|
'exposed' => TRUE,
|
||||||
|
'expose' => array(
|
||||||
|
'operator' => 'name_op',
|
||||||
|
'label' => 'name',
|
||||||
|
'identifier' => 'name',
|
||||||
|
),
|
||||||
|
'is_grouped' => TRUE,
|
||||||
|
'group_info' => array(
|
||||||
|
'label' => 'name',
|
||||||
|
'identifier' => 'name',
|
||||||
|
'default_group' => 'All',
|
||||||
|
'group_items' => array(
|
||||||
|
1 => array(
|
||||||
|
'title' => 'Name is equal to Ringo',
|
||||||
|
'operator' => '=',
|
||||||
|
'value' => array('value' => 'Ringo'),
|
||||||
|
),
|
||||||
|
2 => array(
|
||||||
|
'title' => 'Name is not equal to Ringo',
|
||||||
|
'operator' => '!=',
|
||||||
|
'value' => array('value' => 'Ringo'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return $filters;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,4 +98,103 @@ class FilterInOperatorTest extends ViewsSqlTest {
|
||||||
'views_test_age' => 'age',
|
'views_test_age' => 'age',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFilterInOperatorGroupedExposedSimple() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Age, Operator: in, Value: 26, 30
|
||||||
|
$filters['age']['group_info']['default_group'] = 1;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
|
||||||
|
$expected_result = array(
|
||||||
|
array(
|
||||||
|
'name' => 'Paul',
|
||||||
|
'age' => 26,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Meredith',
|
||||||
|
'age' => 30,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEqual(2, count($view->result));
|
||||||
|
$this->assertIdenticalResultset($view, $expected_result, array(
|
||||||
|
'views_test_name' => 'name',
|
||||||
|
'views_test_age' => 'age',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFilterNotInOperatorGroupedExposedSimple() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Age, Operator: in, Value: 26, 30
|
||||||
|
$filters['age']['group_info']['default_group'] = 2;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
|
||||||
|
$expected_result = array(
|
||||||
|
array(
|
||||||
|
'name' => 'John',
|
||||||
|
'age' => 25,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'George',
|
||||||
|
'age' => 27,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Ringo',
|
||||||
|
'age' => 28,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEqual(3, count($view->result));
|
||||||
|
$this->assertIdenticalResultset($view, $expected_result, array(
|
||||||
|
'views_test_name' => 'name',
|
||||||
|
'views_test_age' => 'age',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getGroupedExposedFilters() {
|
||||||
|
$filters = array(
|
||||||
|
'age' => array(
|
||||||
|
'id' => 'age',
|
||||||
|
'table' => 'views_test',
|
||||||
|
'field' => 'age',
|
||||||
|
'relationship' => 'none',
|
||||||
|
'exposed' => TRUE,
|
||||||
|
'expose' => array(
|
||||||
|
'operator' => 'age_op',
|
||||||
|
'label' => 'age',
|
||||||
|
'identifier' => 'age',
|
||||||
|
),
|
||||||
|
'is_grouped' => TRUE,
|
||||||
|
'group_info' => array(
|
||||||
|
'label' => 'age',
|
||||||
|
'identifier' => 'age',
|
||||||
|
'default_group' => 'All',
|
||||||
|
'group_items' => array(
|
||||||
|
1 => array(
|
||||||
|
'title' => 'Age is one of 26, 30',
|
||||||
|
'operator' => 'in',
|
||||||
|
'value' => array(26, 30),
|
||||||
|
),
|
||||||
|
2 => array(
|
||||||
|
'title' => 'Age is not one of 26, 30',
|
||||||
|
'operator' => 'not in',
|
||||||
|
'value' => array(26, 30),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return $filters;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class FilterNumericTest extends ViewsSqlTest {
|
||||||
|
|
||||||
public static function getInfo() {
|
public static function getInfo() {
|
||||||
return array(
|
return array(
|
||||||
'name' => 'Handlers: filter_numeric',
|
'name' => 'Filter: Numeric',
|
||||||
'description' => 'Tests the numeric filter handler',
|
'description' => 'Tests the numeric filter handler',
|
||||||
'group' => 'Views Handlers',
|
'group' => 'Views Handlers',
|
||||||
);
|
);
|
||||||
|
|
@ -64,6 +64,25 @@ class FilterNumericTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFilterNumericExposedGroupedSimple() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Age, Operator: =, Value: 28
|
||||||
|
$filters['age']['group_info']['default_group'] = 1;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'Ringo',
|
||||||
|
'age' => 28,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
public function testFilterNumericBetween() {
|
public function testFilterNumericBetween() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -136,6 +155,63 @@ class FilterNumericTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFilterNumericExposedGroupedBetween() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Age, Operator: between, Value: 26 and 29
|
||||||
|
$filters['age']['group_info']['default_group'] = 2;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'George',
|
||||||
|
'age' => 27,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Ringo',
|
||||||
|
'age' => 28,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Paul',
|
||||||
|
'age' => 26,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFilterNumericExposedGroupedNotBetween() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Age, Operator: between, Value: 26 and 29
|
||||||
|
$filters['age']['group_info']['default_group'] = 3;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'John',
|
||||||
|
'age' => 25,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Paul',
|
||||||
|
'age' => 26,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Meredith',
|
||||||
|
'age' => 30,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testFilterNumericEmpty() {
|
public function testFilterNumericEmpty() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -195,6 +271,60 @@ class FilterNumericTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testFilterNumericExposedGroupedEmpty() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Age, Operator: empty, Value:
|
||||||
|
$filters['age']['group_info']['default_group'] = 4;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
$resultset = array(
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFilterNumericExposedGroupedNotEmpty() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Age, Operator: empty, Value:
|
||||||
|
$filters['age']['group_info']['default_group'] = 5;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'John',
|
||||||
|
'age' => 25,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'George',
|
||||||
|
'age' => 27,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Ringo',
|
||||||
|
'age' => 28,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Paul',
|
||||||
|
'age' => 26,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Meredith',
|
||||||
|
'age' => 30,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testAllowEmpty() {
|
public function testAllowEmpty() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -224,4 +354,60 @@ class FilterNumericTest extends ViewsSqlTest {
|
||||||
$this->assertTrue(isset($age_operators['empty']));
|
$this->assertTrue(isset($age_operators['empty']));
|
||||||
$this->assertTrue(isset($age_operators['not empty']));
|
$this->assertTrue(isset($age_operators['not empty']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getGroupedExposedFilters() {
|
||||||
|
$filters = array(
|
||||||
|
'age' => array(
|
||||||
|
'id' => 'age',
|
||||||
|
'table' => 'views_test',
|
||||||
|
'field' => 'age',
|
||||||
|
'relationship' => 'none',
|
||||||
|
'exposed' => TRUE,
|
||||||
|
'expose' => array(
|
||||||
|
'operator' => 'age_op',
|
||||||
|
'label' => 'age',
|
||||||
|
'identifier' => 'age',
|
||||||
|
),
|
||||||
|
'is_grouped' => TRUE,
|
||||||
|
'group_info' => array(
|
||||||
|
'label' => 'age',
|
||||||
|
'identifier' => 'age',
|
||||||
|
'default_group' => 'All',
|
||||||
|
'group_items' => array(
|
||||||
|
1 => array(
|
||||||
|
'title' => 'Age is 28',
|
||||||
|
'operator' => '=',
|
||||||
|
'value' => array('value' => 28),
|
||||||
|
),
|
||||||
|
2 => array(
|
||||||
|
'title' => 'Age is between 26 and 29',
|
||||||
|
'operator' => 'between',
|
||||||
|
'value' => array(
|
||||||
|
'min' => 26,
|
||||||
|
'max' => 29,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
3 => array(
|
||||||
|
'title' => 'Age is not between 26 and 29',
|
||||||
|
'operator' => 'not between',
|
||||||
|
'value' => array(
|
||||||
|
'min' => 26,
|
||||||
|
'max' => 29,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
4 => array(
|
||||||
|
'title' => 'Age is empty',
|
||||||
|
'operator' => 'empty',
|
||||||
|
),
|
||||||
|
5 => array(
|
||||||
|
'title' => 'Age is not empty',
|
||||||
|
'operator' => 'not empty',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return $filters;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,9 +98,29 @@ class FilterStringTest extends ViewsSqlTest {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
$view->destroy();
|
}
|
||||||
|
|
||||||
|
function testFilterStringGroupedExposedEqual() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Name, Operator: =, Value: Ringo
|
||||||
|
$filters['name']['group_info']['default_group'] = 1;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'Ringo',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testFilterStringNotEqual() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
// Change the filtering
|
// Change the filtering
|
||||||
|
|
@ -133,6 +153,36 @@ class FilterStringTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testFilterStringGroupedExposedNotEqual() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Name, Operator: !=, Value: Ringo
|
||||||
|
$filters['name']['group_info']['default_group'] = '2';
|
||||||
|
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'John',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'George',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Paul',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Meredith',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
function testFilterStringContains() {
|
function testFilterStringContains() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -157,6 +207,28 @@ class FilterStringTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function testFilterStringGroupedExposedContains() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Name, Operator: contains, Value: ing
|
||||||
|
$filters['name']['group_info']['default_group'] = '3';
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'Ringo',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function testFilterStringWord() {
|
function testFilterStringWord() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -207,6 +279,47 @@ class FilterStringTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function testFilterStringGroupedExposedWord() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Name, Operator: contains, Value: ing
|
||||||
|
$filters['name']['group_info']['default_group'] = '3';
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'Ringo',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
$view->destroy();
|
||||||
|
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Description, Operator: contains, Value: actor
|
||||||
|
$filters['description']['group_info']['default_group'] = '1';
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'George',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Ringo',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
function testFilterStringStarts() {
|
function testFilterStringStarts() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -231,6 +344,25 @@ class FilterStringTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testFilterStringGroupedExposedStarts() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Name, Operator: starts, Value: George
|
||||||
|
$filters['description']['group_info']['default_group'] = 2;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'George',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
function testFilterStringNotStarts() {
|
function testFilterStringNotStarts() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -262,6 +394,32 @@ class FilterStringTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testFilterStringGroupedExposedNotStarts() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Name, Operator: not_starts, Value: George
|
||||||
|
$filters['description']['group_info']['default_group'] = 3;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'John',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Ringo',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Paul',
|
||||||
|
),
|
||||||
|
// There is no Meredith returned because his description is empty
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
function testFilterStringEnds() {
|
function testFilterStringEnds() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -289,6 +447,28 @@ class FilterStringTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testFilterStringGroupedExposedEnds() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Descriptino, Operator: ends, Value: Beatles
|
||||||
|
$filters['description']['group_info']['default_group'] = 4;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'George',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Ringo',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
function testFilterStringNotEnds() {
|
function testFilterStringNotEnds() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -317,6 +497,29 @@ class FilterStringTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testFilterStringGroupedExposedNotEnds() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Description, Operator: not_ends, Value: Beatles
|
||||||
|
$filters['description']['group_info']['default_group'] = 5;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'John',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Paul',
|
||||||
|
),
|
||||||
|
// There is no Meredith returned because his description is empty
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
function testFilterStringNot() {
|
function testFilterStringNot() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -345,6 +548,31 @@ class FilterStringTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function testFilterStringGroupedExposedNot() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Description, Operator: not (does not contains), Value: Beatles
|
||||||
|
$filters['description']['group_info']['default_group'] = 6;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'John',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Paul',
|
||||||
|
),
|
||||||
|
// There is no Meredith returned because his description is empty
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function testFilterStringShorter() {
|
function testFilterStringShorter() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -372,6 +600,27 @@ class FilterStringTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testFilterStringGroupedExposedShorter() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Name, Operator: shorterthan, Value: 5
|
||||||
|
$filters['name']['group_info']['default_group'] = 4;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'John',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'Paul',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
function testFilterStringLonger() {
|
function testFilterStringLonger() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -396,6 +645,25 @@ class FilterStringTest extends ViewsSqlTest {
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testFilterStringGroupedExposedLonger() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Name, Operator: longerthan, Value: 4
|
||||||
|
$filters['name']['group_info']['default_group'] = 5;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'Meredith',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function testFilterStringEmpty() {
|
function testFilterStringEmpty() {
|
||||||
$view = $this->getBasicView();
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
|
@ -418,4 +686,129 @@ class FilterStringTest extends ViewsSqlTest {
|
||||||
);
|
);
|
||||||
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testFilterStringGroupedExposedEmpty() {
|
||||||
|
$filters = $this->getGroupedExposedFilters();
|
||||||
|
$view = $this->getBasicPageView();
|
||||||
|
|
||||||
|
// Filter: Description, Operator: empty, Value:
|
||||||
|
$filters['description']['group_info']['default_group'] = 7;
|
||||||
|
$view->set_display('page_1');
|
||||||
|
$view->display['page_1']->handler->override_option('filters', $filters);
|
||||||
|
|
||||||
|
$this->executeView($view);
|
||||||
|
$resultset = array(
|
||||||
|
array(
|
||||||
|
'name' => 'Meredith',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$this->assertIdenticalResultset($view, $resultset, $this->column_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getGroupedExposedFilters() {
|
||||||
|
$filters = array(
|
||||||
|
'name' => array(
|
||||||
|
'id' => 'name',
|
||||||
|
'table' => 'views_test',
|
||||||
|
'field' => 'name',
|
||||||
|
'relationship' => 'none',
|
||||||
|
'exposed' => TRUE,
|
||||||
|
'expose' => array(
|
||||||
|
'operator' => 'name_op',
|
||||||
|
'label' => 'name',
|
||||||
|
'identifier' => 'name',
|
||||||
|
),
|
||||||
|
'is_grouped' => TRUE,
|
||||||
|
'group_info' => array(
|
||||||
|
'label' => 'name',
|
||||||
|
'identifier' => 'name',
|
||||||
|
'default_group' => 'All',
|
||||||
|
'group_items' => array(
|
||||||
|
1 => array(
|
||||||
|
'title' => 'Is Ringo',
|
||||||
|
'operator' => '=',
|
||||||
|
'value' => 'Ringo',
|
||||||
|
),
|
||||||
|
2 => array(
|
||||||
|
'title' => 'Is not Ringo',
|
||||||
|
'operator' => '!=',
|
||||||
|
'value' => array('value' => 'Ringo'),
|
||||||
|
),
|
||||||
|
3 => array(
|
||||||
|
'title' => 'Contains ing',
|
||||||
|
'operator' => 'contains',
|
||||||
|
'value' => 'ing',
|
||||||
|
),
|
||||||
|
4 => array(
|
||||||
|
'title' => 'Shorter than 5 letters',
|
||||||
|
'operator' => 'shorterthan',
|
||||||
|
'value' => 5,
|
||||||
|
),
|
||||||
|
5 => array(
|
||||||
|
'title' => 'Longer than 7 letters',
|
||||||
|
'operator' => 'longerthan',
|
||||||
|
'value' => 7,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'description' => array(
|
||||||
|
'id' => 'description',
|
||||||
|
'table' => 'views_test',
|
||||||
|
'field' => 'description',
|
||||||
|
'relationship' => 'none',
|
||||||
|
'exposed' => TRUE,
|
||||||
|
'expose' => array(
|
||||||
|
'operator' => 'description_op',
|
||||||
|
'label' => 'description',
|
||||||
|
'identifier' => 'description',
|
||||||
|
),
|
||||||
|
'is_grouped' => TRUE,
|
||||||
|
'group_info' => array(
|
||||||
|
'label' => 'description',
|
||||||
|
'identifier' => 'description',
|
||||||
|
'default_group' => 'All',
|
||||||
|
'group_items' => array(
|
||||||
|
1 => array(
|
||||||
|
'title' => 'Contains the word: Actor',
|
||||||
|
'operator' => 'word',
|
||||||
|
'value' => 'actor',
|
||||||
|
),
|
||||||
|
2 => array(
|
||||||
|
'title' => 'Starts with George',
|
||||||
|
'operator' => 'starts',
|
||||||
|
'value' => 'George',
|
||||||
|
),
|
||||||
|
3 => array(
|
||||||
|
'title' => 'Not Starts with: George',
|
||||||
|
'operator' => 'not_starts',
|
||||||
|
'value' => 'George',
|
||||||
|
),
|
||||||
|
4 => array(
|
||||||
|
'title' => 'Ends with: Beatles',
|
||||||
|
'operator' => 'ends',
|
||||||
|
'value' => 'Beatles.',
|
||||||
|
),
|
||||||
|
5 => array(
|
||||||
|
'title' => 'Not Ends with: Beatles',
|
||||||
|
'operator' => 'not_ends',
|
||||||
|
'value' => 'Beatles.',
|
||||||
|
),
|
||||||
|
6 => array(
|
||||||
|
'title' => 'Does not contain: Beatles',
|
||||||
|
'operator' => 'not',
|
||||||
|
'value' => 'Beatles.',
|
||||||
|
),
|
||||||
|
7 => array(
|
||||||
|
'title' => 'Empty description',
|
||||||
|
'operator' => 'empty',
|
||||||
|
'value' => '',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return $filters;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ use Drupal\simpletest\WebTestBase;
|
||||||
use Drupal\views\View;
|
use Drupal\views\View;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class for views testing.
|
* Abstract class for views testing.
|
||||||
*/
|
*/
|
||||||
abstract class ViewsSqlTest extends WebTestBase {
|
abstract class ViewsSqlTest extends WebTestBase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -160,6 +160,22 @@ abstract class ViewsSqlTest extends WebTestBase {
|
||||||
$this->verbose('<pre>Executed view: ' . ((string) $view->build_info['query']) . '</pre>');
|
$this->verbose('<pre>Executed view: ' . ((string) $view->build_info['query']) . '</pre>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build and return a Page view of the views_test table.
|
||||||
|
*
|
||||||
|
* @return view
|
||||||
|
*/
|
||||||
|
protected function getBasicPageView() {
|
||||||
|
$view = $this->getBasicView();
|
||||||
|
|
||||||
|
// In order to test exposed filters, we have to disable
|
||||||
|
// the exposed forms cache.
|
||||||
|
drupal_static_reset('views_exposed_form_cache');
|
||||||
|
|
||||||
|
$display = $view->new_display('page', 'Page', 'page_1');
|
||||||
|
return $view;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The schema definition.
|
* The schema definition.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1087,17 +1087,32 @@ class View extends ViewsDbObject {
|
||||||
function _build($key) {
|
function _build($key) {
|
||||||
$handlers = &$this->$key;
|
$handlers = &$this->$key;
|
||||||
foreach ($handlers as $id => $data) {
|
foreach ($handlers as $id => $data) {
|
||||||
|
|
||||||
if (!empty($handlers[$id]) && is_object($handlers[$id])) {
|
if (!empty($handlers[$id]) && is_object($handlers[$id])) {
|
||||||
// Give this handler access to the exposed filter input.
|
$multiple_exposed_input = array(0 => NULL);
|
||||||
if (!empty($this->exposed_data)) {
|
if ($handlers[$id]->multiple_exposed_input()) {
|
||||||
$rc = $handlers[$id]->accept_exposed_input($this->exposed_data);
|
$multiple_exposed_input = $handlers[$id]->group_multiple_exposed_input($this->exposed_data);
|
||||||
$handlers[$id]->store_exposed_input($this->exposed_data, $rc);
|
}
|
||||||
if (!$rc) {
|
foreach ($multiple_exposed_input as $group_id) {
|
||||||
continue;
|
// Give this handler access to the exposed filter input.
|
||||||
}
|
if (!empty($this->exposed_data)) {
|
||||||
|
$converted = FALSE;
|
||||||
|
if ($handlers[$id]->is_a_group()) {
|
||||||
|
$converted = $handlers[$id]->convert_exposed_input($this->exposed_data, $group_id);
|
||||||
|
$handlers[$id]->store_group_input($this->exposed_data, $converted);
|
||||||
|
if (!$converted) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$rc = $handlers[$id]->accept_exposed_input($this->exposed_data);
|
||||||
|
$handlers[$id]->store_exposed_input($this->exposed_data, $rc);
|
||||||
|
if (!$rc) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$handlers[$id]->set_relationship();
|
||||||
|
$handlers[$id]->query($this->display_handler->use_group_by());
|
||||||
}
|
}
|
||||||
$handlers[$id]->set_relationship();
|
|
||||||
$handlers[$id]->query($this->display_handler->use_group_by());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
views.module
22
views.module
|
|
@ -2049,7 +2049,18 @@ function views_exposed_form($form, &$form_state) {
|
||||||
foreach ($view->display_handler->handlers as $type => $value) {
|
foreach ($view->display_handler->handlers as $type => $value) {
|
||||||
foreach ($view->$type as $id => $handler) {
|
foreach ($view->$type as $id => $handler) {
|
||||||
if ($handler->can_expose() && $handler->is_exposed()) {
|
if ($handler->can_expose() && $handler->is_exposed()) {
|
||||||
$handler->exposed_form($form, $form_state);
|
// Grouped exposed filters have their own forms.
|
||||||
|
// Instead of render the standard exposed form, a new Select or
|
||||||
|
// Radio form field is rendered with the available groups.
|
||||||
|
// When an user choose an option the selected value is split
|
||||||
|
// into the operator and value that the item represents.
|
||||||
|
if ($handler->is_a_group()) {
|
||||||
|
$handler->group_form($form, $form_state);
|
||||||
|
$id = $handler->options['group_info']['identifier'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$handler->exposed_form($form, $form_state);
|
||||||
|
}
|
||||||
if ($info = $handler->exposed_info()) {
|
if ($info = $handler->exposed_info()) {
|
||||||
$form['#info']["$type-$id"] = $info;
|
$form['#info']["$type-$id"] = $info;
|
||||||
}
|
}
|
||||||
|
|
@ -2539,6 +2550,15 @@ function views_trim_text($alter, $value) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter by no empty values, though allow to use "0".
|
||||||
|
* @param $var
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function _views_array_filter_zero($var) {
|
||||||
|
return trim($var) != "";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds one to each key of the array.
|
* Adds one to each key of the array.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,12 @@ function views_ui_theme() {
|
||||||
'file' => "includes/admin.inc",
|
'file' => "includes/admin.inc",
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// Group of filters.
|
||||||
|
'views_ui_build_group_filter_form' => array(
|
||||||
|
'render element' => 'form',
|
||||||
|
'file' => 'includes/admin.inc',
|
||||||
|
),
|
||||||
|
|
||||||
// tab themes
|
// tab themes
|
||||||
'views_tabset' => array(
|
'views_tabset' => array(
|
||||||
'variables' => array('tabs' => NULL),
|
'variables' => array('tabs' => NULL),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue