|
@@ -15,15 +15,14 @@
|
|
|
* available as standard operators.
|
|
|
*
|
|
|
* Object flags:
|
|
|
- * You can set some specific behavior by setting up the following flags on
|
|
|
- * your custom class.
|
|
|
- *
|
|
|
- * - always_multiple:
|
|
|
- * Disable the possibility to force a single value.
|
|
|
- * - no_operator:
|
|
|
- * Disable the possibility to use operators.
|
|
|
- * - always_required:
|
|
|
- * Disable the possibility to allow a exposed input to be optional.
|
|
|
+ * It's possible to set specific behavior using the following flags on the
|
|
|
+ * custom class:
|
|
|
+ * - always_multiple:
|
|
|
+ * Disable the possibility to force a single value.
|
|
|
+ * - no_operator:
|
|
|
+ * Disable the possibility to use operators.
|
|
|
+ * - always_required:
|
|
|
+ * Disable the possibility to allow a exposed input to be optional.
|
|
|
*/
|
|
|
|
|
|
/**
|
|
@@ -34,8 +33,10 @@
|
|
|
class views_handler_filter extends views_handler {
|
|
|
|
|
|
/**
|
|
|
- * Contains the actual value of the field,either configured in the views ui
|
|
|
- * or entered in the exposed filters.
|
|
|
+ * Contains the actual value of the field.
|
|
|
+ *
|
|
|
+ * This will be either configured in the views UI or entered in the exposed
|
|
|
+ * filters.
|
|
|
*
|
|
|
* @var mixed
|
|
|
*/
|
|
@@ -135,13 +136,17 @@ class views_handler_filter extends views_handler {
|
|
|
'use_operator' => array('default' => FALSE, 'bool' => TRUE),
|
|
|
'operator_label' => array('default' => '', 'translatable' => TRUE),
|
|
|
'operator' => array('default' => ''),
|
|
|
+ 'limit_operators' => array('default' => FALSE, 'bool' => TRUE),
|
|
|
+ 'available_operators' => array('default' => array()),
|
|
|
'identifier' => array('default' => ''),
|
|
|
'required' => array('default' => FALSE, 'bool' => TRUE),
|
|
|
'remember' => array('default' => FALSE, 'bool' => TRUE),
|
|
|
'multiple' => array('default' => FALSE, 'bool' => TRUE),
|
|
|
- 'remember_roles' => array('default' => array(
|
|
|
- DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID,
|
|
|
- )),
|
|
|
+ 'remember_roles' => array(
|
|
|
+ 'default' => array(
|
|
|
+ DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
),
|
|
|
);
|
|
|
|
|
@@ -205,9 +210,8 @@ class views_handler_filter extends views_handler {
|
|
|
/**
|
|
|
* Provide the basic form which calls through to subforms.
|
|
|
*
|
|
|
- * If overridden, it is best to call through to the parent,
|
|
|
- * or to at least make sure all of the functions in this form
|
|
|
- * are called.
|
|
|
+ * If overridden, it is best to call through to the parent, or to at least
|
|
|
+ * make sure all of the functions in this form are called.
|
|
|
*/
|
|
|
public function options_form(&$form, &$form_state) {
|
|
|
parent::options_form($form, $form_state);
|
|
@@ -248,7 +252,7 @@ class views_handler_filter extends views_handler {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Simple validate handler
|
|
|
+ * Simple validate handler.
|
|
|
*/
|
|
|
public function options_validate(&$form, &$form_state) {
|
|
|
$this->operator_validate($form, $form_state);
|
|
@@ -274,6 +278,8 @@ class views_handler_filter extends views_handler {
|
|
|
$this->value_submit($form, $form_state);
|
|
|
}
|
|
|
if (!empty($this->options['exposed'])) {
|
|
|
+ $options = &$form_state['values']['options']['expose'];
|
|
|
+ $options['available_operators'] = (!empty($options['use_operator']) && !empty($options['limit_operators'])) ? array_filter($options['available_operators']) : array();
|
|
|
$this->expose_submit($form, $form_state);
|
|
|
}
|
|
|
if ($this->is_a_group()) {
|
|
@@ -293,14 +299,29 @@ class views_handler_filter extends views_handler {
|
|
|
/**
|
|
|
* Options form subform for setting the operator.
|
|
|
*
|
|
|
- * This may be overridden by child classes, and it must
|
|
|
- * define $form['operator'];
|
|
|
+ * This may be overridden by child classes, and it must define
|
|
|
+ * $form['operator'].
|
|
|
*
|
|
|
* @see options_form()
|
|
|
*/
|
|
|
public function operator_form(&$form, &$form_state) {
|
|
|
$options = $this->operator_options();
|
|
|
if (!empty($options)) {
|
|
|
+ $available = $this->options['expose']['available_operators'];
|
|
|
+ if ($this->options['expose']['limit_operators'] && count($available)) {
|
|
|
+ foreach ($options as $key => $value) {
|
|
|
+ if (!isset($available[$key])) {
|
|
|
+ unset($options[$key]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Make sure we have a valid default value if the current one is
|
|
|
+ // excluded.
|
|
|
+ if (!isset($options[$this->operator])) {
|
|
|
+ // Just choose the first.
|
|
|
+ $this->operator = key($options);
|
|
|
+ }
|
|
|
+ }
|
|
|
$form['operator'] = array(
|
|
|
'#type' => count($options) < 10 ? 'radios' : 'select',
|
|
|
'#title' => t('Operator'),
|
|
@@ -313,7 +334,7 @@ class views_handler_filter extends views_handler {
|
|
|
/**
|
|
|
* Provide a list of options for the default operator form.
|
|
|
*
|
|
|
- * Should be overridden by classes that don't override operator_form
|
|
|
+ * Should be overridden by classes that don't override operator_form.
|
|
|
*/
|
|
|
public function operator_options() {
|
|
|
return array();
|
|
@@ -511,6 +532,33 @@ class views_handler_filter extends views_handler {
|
|
|
'#title' => t('Required'),
|
|
|
'#default_value' => $this->options['expose']['required'],
|
|
|
);
|
|
|
+
|
|
|
+ $operator_options = $this->operator_options();
|
|
|
+ if (count($operator_options)) {
|
|
|
+ $form['expose']['limit_operators'] = array(
|
|
|
+ '#type' => 'checkbox',
|
|
|
+ '#title' => t('Limit operators'),
|
|
|
+ '#description' => t('When checked, the operator will be exposed to the user'),
|
|
|
+ '#default_value' => !empty($this->options['expose']['limit_operators']),
|
|
|
+ '#dependency' => array(
|
|
|
+ 'edit-options-expose-use-operator' => array(1),
|
|
|
+ ),
|
|
|
+ '#description' => t('Restrict which operators will be available to select in the exposed operator form.'),
|
|
|
+ );
|
|
|
+
|
|
|
+ $form['expose']['available_operators'] = array(
|
|
|
+ '#type' => 'checkboxes',
|
|
|
+ '#title' => t('Limit the exposed operators'),
|
|
|
+ '#default_value' => $this->options['expose']['available_operators'],
|
|
|
+ '#prefix' => '<div id="edit-options-expose-available-operators-wrapper"><div id="edit-options-expose-available-operators">',
|
|
|
+ '#suffix' => '</div></div>',
|
|
|
+ '#description' => t('Select which operators will be available to select in the exposed operator form. If none are selected, all the operators listed here will be used.'),
|
|
|
+ '#options' => $operator_options,
|
|
|
+ '#dependency' => array(
|
|
|
+ 'edit-options-expose-limit-operators' => array(1),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
}
|
|
|
else {
|
|
|
$form['expose']['required'] = array(
|
|
@@ -533,7 +581,7 @@ class views_handler_filter extends views_handler {
|
|
|
);
|
|
|
|
|
|
if (!empty($form['operator']['#type'])) {
|
|
|
- // Increase the width of the left (operator) column.
|
|
|
+ // Increase the width of the left (operator) column.
|
|
|
$form['operator']['#prefix'] = '<div class="views-group-box views-left-40">';
|
|
|
$form['operator']['#suffix'] = '</div>';
|
|
|
$form['value']['#prefix'] = '<div class="views-group-box views-right-60">';
|
|
@@ -552,7 +600,7 @@ class views_handler_filter extends views_handler {
|
|
|
'#size' => 40,
|
|
|
'#description' => t('This will appear before your operator select field.'),
|
|
|
'#dependency' => array(
|
|
|
- 'edit-options-expose-use-operator' => array(1)
|
|
|
+ 'edit-options-expose-use-operator' => array(1),
|
|
|
),
|
|
|
);
|
|
|
$form['expose']['operator_id'] = array(
|
|
@@ -562,7 +610,7 @@ class views_handler_filter extends views_handler {
|
|
|
'#size' => 40,
|
|
|
'#description' => t('This will appear in the URL after the ? to identify this operator.'),
|
|
|
'#dependency' => array(
|
|
|
- 'edit-options-expose-use-operator' => array(1)
|
|
|
+ 'edit-options-expose-use-operator' => array(1),
|
|
|
),
|
|
|
'#fieldset' => 'more',
|
|
|
);
|
|
@@ -629,6 +677,12 @@ class views_handler_filter extends views_handler {
|
|
|
if (!$this->view->display_handler->is_identifier_unique($form_state['id'], $form_state['values']['options']['expose']['identifier'])) {
|
|
|
form_error($form['expose']['identifier'], t('This identifier is used by another handler.'));
|
|
|
}
|
|
|
+
|
|
|
+ // Filter out roles which weren't selected, so that they aren't exported.
|
|
|
+ // This is purely cosmetic.
|
|
|
+ if (!empty($form_state['values']['options']['expose']['remember_roles'])) {
|
|
|
+ $form_state['values']['options']['expose']['remember_roles'] = array_filter($form_state['values']['options']['expose']['remember_roles']);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -657,10 +711,13 @@ class views_handler_filter extends views_handler {
|
|
|
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.'));
|
|
|
+ // No value is needed for 'empty' and 'not empty' operator.
|
|
|
+ if (!in_array($group['operator'], array('empty', 'not empty'))) {
|
|
|
+ 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.'));
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -786,9 +843,8 @@ class views_handler_filter extends views_handler {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
- * Render our chunk of the exposed filter form when selecting
|
|
|
+ * Render our chunk of the exposed filter form when selecting.
|
|
|
*
|
|
|
* You can override this if it doesn't do what you expect.
|
|
|
*/
|
|
@@ -802,7 +858,7 @@ class views_handler_filter extends views_handler {
|
|
|
$operator = $this->options['expose']['operator_id'];
|
|
|
$this->operator_form($form, $form_state);
|
|
|
$form[$operator] = $form['operator'];
|
|
|
- $form[$operator]['#title'] = $this->options['expose']['operator_label'];
|
|
|
+ $form[$operator]['#title'] = $this->options['expose']['operator_label'];
|
|
|
$form[$operator]['#title_display'] = 'invisible';
|
|
|
|
|
|
$this->exposed_translate($form[$operator], 'operator');
|
|
@@ -813,7 +869,19 @@ class views_handler_filter extends views_handler {
|
|
|
// Build the form and set the value based on the identifier.
|
|
|
if (!empty($this->options['expose']['identifier'])) {
|
|
|
$value = $this->options['expose']['identifier'];
|
|
|
- $this->value_form($form, $form_state);
|
|
|
+ if ($this->operator == 'empty' || $this->operator == 'not empty') {
|
|
|
+ $boolean = new views_handler_filter_boolean_operator();
|
|
|
+ $boolean->value = $this->value = 'All';
|
|
|
+ $boolean->value_value = $this->value_value = '';
|
|
|
+ $boolean->value_options = $this->value_options = array(
|
|
|
+ 1 => t('Yes'),
|
|
|
+ 0 => t('No'),
|
|
|
+ );
|
|
|
+ $boolean->value_form($form, $form_state);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $this->value_form($form, $form_state);
|
|
|
+ }
|
|
|
$form[$value] = $form['value'];
|
|
|
|
|
|
if (isset($form[$value]['#title']) && !empty($form[$value]['#type']) && $form[$value]['#type'] != 'checkbox') {
|
|
@@ -955,7 +1023,7 @@ class views_handler_filter extends views_handler {
|
|
|
|
|
|
// The string '- Any -' will not be rendered.
|
|
|
// @see theme_views_ui_build_group_filter_form()
|
|
|
- $groups = array('All' => '- Any -');
|
|
|
+ $groups = array('All' => '- Any -');
|
|
|
|
|
|
// Provide 3 options to start when we are in a new group.
|
|
|
if (count($this->options['group_info']['group_items']) == 0) {
|
|
@@ -968,6 +1036,7 @@ class views_handler_filter extends views_handler {
|
|
|
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.
|
|
@@ -979,14 +1048,14 @@ class views_handler_filter extends views_handler {
|
|
|
$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.
|
|
|
+ // 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
|
|
|
+ // 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;
|
|
@@ -1041,6 +1110,7 @@ class views_handler_filter extends views_handler {
|
|
|
),
|
|
|
);
|
|
|
}
|
|
|
+
|
|
|
// From all groups, let chose which is the default.
|
|
|
$form['group_info']['default_group'] = array(
|
|
|
'#type' => 'radios',
|
|
@@ -1049,8 +1119,9 @@ class views_handler_filter extends views_handler {
|
|
|
'#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',
|
|
@@ -1058,7 +1129,7 @@ class views_handler_filter extends views_handler {
|
|
|
'#default_value' => $this->options['group_info']['default_group_multiple'],
|
|
|
'#attributes' => array(
|
|
|
'class' => array('default-checkboxes'),
|
|
|
- )
|
|
|
+ ),
|
|
|
);
|
|
|
|
|
|
$form['group_info']['add_group'] = array(
|
|
@@ -1086,7 +1157,6 @@ class views_handler_filter extends views_handler {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* Make some translations to a form item to make it more suitable to exposing.
|
|
|
*/
|
|
@@ -1190,13 +1260,13 @@ class views_handler_filter extends views_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.
|
|
|
+ * When a filter is a group, find the set of operator and values that the
|
|
|
+ * choosen 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.
|
|
|
+ * checkboxes widget, and this function will be called for each item choosen
|
|
|
+ * in the checkboxes.
|
|
|
*/
|
|
|
public function convert_exposed_input(&$input, $selected_group_id = NULL) {
|
|
|
if ($this->is_a_group()) {
|
|
@@ -1234,9 +1304,12 @@ class views_handler_filter extends views_handler {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 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.
|
|
|
+ * Options available for a grouped filter which uses checkboxes.
|
|
|
+ *
|
|
|
+ * Note: has to be applied several times, one per item selected.
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ * The options available for a grouped filter.
|
|
|
*/
|
|
|
public function group_multiple_exposed_input(&$input) {
|
|
|
if (!empty($input[$this->options['group_info']['identifier']])) {
|
|
@@ -1246,7 +1319,7 @@ class views_handler_filter extends views_handler {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- *
|
|
|
+ * Indicate whether users can select multiple group items.
|
|
|
*
|
|
|
* @return bool
|
|
|
* TRUE if users can select multiple groups items of a grouped exposed
|
|
@@ -1258,8 +1331,9 @@ class views_handler_filter extends views_handler {
|
|
|
|
|
|
/**
|
|
|
* 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.
|
|
|
+ *
|
|
|
+ * This function is similar to store_exposed_input but modified to work
|
|
|
+ * properly when the filter is a group.
|
|
|
*/
|
|
|
public function store_group_input($input, $status) {
|
|
|
if (!$this->is_a_group() || empty($this->options['group_info']['identifier'])) {
|
|
@@ -1312,14 +1386,13 @@ class views_handler_filter extends views_handler {
|
|
|
|
|
|
// Various ways to check for the absence of non-required input.
|
|
|
if (empty($this->options['expose']['required'])) {
|
|
|
- if (($this->operator == 'empty' || $this->operator == 'not empty') && $value === '') {
|
|
|
- $value = ' ';
|
|
|
+ if ($this->operator == 'empty' || $this->operator == 'not empty') {
|
|
|
+ $value = is_array($value) ? $value['value'] : $value;
|
|
|
+ $this->operator = ($this->operator == 'empty' && empty($value)) || ($this->operator == 'not empty' && !empty($value)) ? 'not empty' : 'empty';
|
|
|
}
|
|
|
|
|
|
- if ($this->operator != 'empty' && $this->operator != 'not empty') {
|
|
|
- if ($value == 'All' || $value === array()) {
|
|
|
- return FALSE;
|
|
|
- }
|
|
|
+ if ($value == 'All' || $value === array()) {
|
|
|
+ return FALSE;
|
|
|
}
|
|
|
|
|
|
if (!empty($this->always_multiple) && $value === '') {
|
|
@@ -1342,7 +1415,7 @@ class views_handler_filter extends views_handler {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- *
|
|
|
+ * Store the exposed input for processing later.
|
|
|
*/
|
|
|
public function store_exposed_input($input, $status) {
|
|
|
if (empty($this->options['exposed']) || empty($this->options['expose']['identifier'])) {
|
|
@@ -1392,7 +1465,9 @@ class views_handler_filter extends views_handler {
|
|
|
$session[$this->options['expose']['operator_id']] = $input[$this->options['expose']['operator_id']];
|
|
|
}
|
|
|
|
|
|
- $session[$this->options['expose']['identifier']] = $input[$this->options['expose']['identifier']];
|
|
|
+ if (isset($input[$this->options['expose']['identifier']])) {
|
|
|
+ $session[$this->options['expose']['identifier']] = $input[$this->options['expose']['identifier']];
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1419,9 +1494,9 @@ class views_handler_filter extends views_handler {
|
|
|
* @return bool
|
|
|
* Whether the filter can be used in OR groups.
|
|
|
*/
|
|
|
- public function can_group() {
|
|
|
- return TRUE;
|
|
|
- }
|
|
|
+ public function can_group() {
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
@@ -1476,14 +1551,15 @@ class views_handler_filter_broken extends views_handler_filter {
|
|
|
* Filter by no empty values, though allow to use "0".
|
|
|
*
|
|
|
* @param string $var
|
|
|
+ * The string to check.
|
|
|
*
|
|
|
* @return bool
|
|
|
+ * Indicates if the argument is an empty string.
|
|
|
*/
|
|
|
function _views_array_filter_zero($var) {
|
|
|
- return trim($var) != "";
|
|
|
+ return trim($var) != '';
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* @}
|
|
|
*/
|