• Main Page
  • Related Pages
  • Modules
  • Classes
  • Files
  • File List
  • File Members

handlers/views_handler_filter.inc

00001 <?php
00026 class views_handler_filter extends views_handler {
00031   var $value = NULL;
00032 
00036   var $operator = '=';
00037 
00042   var $always_multiple = FALSE;
00043 
00048   var $no_operator = FALSE;
00049 
00054   var $always_required = FALSE;
00055 
00062   function init(&$view, &$options) {
00063     parent::init($view, $options);
00064 
00065     $this->operator = $this->options['operator'];
00066     $this->value = $this->options['value'];
00067 
00068     // Compatibility: The new UI changed several settings.
00069     if (!empty($options['exposed']) && !empty($options['expose']['optional']) && !isset($options['expose']['required'])) {
00070       $this->options['expose']['required'] = !$options['expose']['optional'];
00071     }
00072     if (!empty($options['exposed']) && !empty($options['expose']['single']) && !isset($options['expose']['multiple'])) {
00073       $this->options['expose']['multiple'] = !$options['expose']['single'];
00074     }
00075     if (!empty($options['exposed']) && !empty($options['expose']['operator']) && !isset($options['expose']['operator_id'])) {
00076       $this->options['expose']['operator_id'] = $options['expose']['operator_id'] = $options['expose']['operator'];
00077     }
00078 
00079     // If there are relationships in the view, allow empty should be true
00080     // so that we can do IS NULL checks on items. Not all filters respect
00081     // allow empty, but string and numeric do and that covers enough.
00082     if ($this->view->display_handler->get_option('relationships')) {
00083       $this->definition['allow empty'] = TRUE;
00084     }
00085   }
00086 
00087   function option_definition() {
00088     $options = parent::option_definition();
00089 
00090     $options['operator'] = array('default' => '=');
00091     $options['value'] = array('default' => '');
00092     $options['group'] = array('default' => '1');
00093     $options['exposed'] = array('default' => FALSE);
00094     $options['expose'] = array(
00095       'contains' => array(
00096         'operator_id' => array('default' => FALSE),
00097         'label' => array('default' => '', 'translatable' => TRUE),
00098         'use_operator' => array('default' => 0),
00099         'operator' => array('default' => ''),
00100         'identifier' => array('default' => ''),
00101         'required' => array('default' => 0),
00102         'remember' => array('default' => 0),
00103         'multiple' => array('default' => 0),
00104       ),
00105     );
00106 
00107     return $options;
00108   }
00109 
00113   function admin_summary() {
00114     return check_plain((string) $this->operator) . ' ' . check_plain((string) $this->value);
00115   }
00116 
00120   function can_expose() { return TRUE; }
00121 
00128   function options_form(&$form, &$form_state) {
00129     parent::options_form($form, $form_state);
00130     if ($this->can_expose()) {
00131       $this->show_expose_button($form, $form_state);
00132     }
00133     $form['clear_markup_start'] = array(
00134       '#markup' => '<div class="clearfix">',
00135     );
00136     // Add the subform from operator_form().
00137     $this->show_operator_form($form, $form_state);
00138     // Add the subform from value_form().
00139     $this->show_value_form($form, $form_state);
00140     $form['clear_markup_end'] = array(
00141       '#markup' => '</div>',
00142     );
00143     if ($this->can_expose()) {
00144       // Add the subform from expose_form().
00145       $this->show_expose_form($form, $form_state);
00146     }
00147   }
00148 
00152   function options_validate(&$form, &$form_state) {
00153     $this->operator_validate($form, $form_state);
00154     $this->value_validate($form, $form_state);
00155     if (!empty($this->options['exposed'])) {
00156       $this->expose_validate($form, $form_state);
00157     }
00158   }
00159 
00163   function options_submit(&$form, &$form_state) {
00164     unset($form_state['values']['expose_button']); // don't store this.
00165     $this->operator_submit($form, $form_state);
00166     $this->value_submit($form, $form_state);
00167     if (!empty($this->options['exposed'])) {
00168       $this->expose_submit($form, $form_state);
00169     }
00170   }
00171 
00175   function show_operator_form(&$form, &$form_state) {
00176     $this->operator_form($form, $form_state);
00177     $form['operator']['#prefix'] = '<div class="views-group-box views-left-30">';
00178     $form['operator']['#suffix'] = '</div>';
00179   }
00180 
00189   function operator_form(&$form, &$form_state) {
00190     $options = $this->operator_options();
00191     if (!empty($options)) {
00192       $form['operator'] = array(
00193         '#type' => count($options) < 10 ? 'radios' : 'select',
00194         '#title' => t('Operator'),
00195         '#default_value' => $this->operator,
00196         '#options' => $options,
00197       );
00198     }
00199   }
00200 
00205   function operator_options() { return array(); }
00206 
00210   function operator_validate($form, &$form_state) { }
00211 
00216   function operator_submit($form, &$form_state) { }
00217 
00221   function show_value_form(&$form, &$form_state) {
00222     $this->value_form($form, $form_state);
00223     if (empty($this->no_operator)) {
00224       $form['value']['#prefix'] = '<div class="views-group-box views-right-70">' . (isset($form['value']['#prefix']) ? $form['value']['#prefix'] : '');
00225       $form['value']['#suffix'] = (isset($form['value']['#suffix']) ? $form['value']['#suffix'] : '') . '</div>';
00226     }
00227   }
00228 
00237   function value_form(&$form, &$form_state) { $form['value'] = array(); }
00238 
00242   function value_validate($form, &$form_state) { }
00243 
00248   function value_submit($form, &$form_state) { }
00249 
00253   function show_expose_button(&$form, &$form_state) {
00254     $form['expose_button'] = array(
00255       '#prefix' => '<div class="views-expose clearfix">',
00256       '#suffix' => '</div>',
00257       // Should always come after the description and the relationship.
00258       '#weight' => -200,
00259     );
00260 
00261     // Add a checkbox for JS users, which will have behavior attached to it
00262     // so it can replace the button.
00263     $form['expose_button']['checkbox'] = array(
00264       '#theme_wrappers' => array('container'),
00265       '#attributes' => array('class' => array('js-only')),
00266     );
00267     $form['expose_button']['checkbox']['checkbox'] = array(
00268       '#title' => t('Expose this filter to visitors, to allow them to change it'),
00269       '#type' => 'checkbox',
00270     );
00271 
00272     // Then add the button itself.
00273     if (empty($this->options['exposed'])) {
00274       $form['expose_button']['markup'] = array(
00275         '#markup' => '<div class="description exposed-description">' . t('This filter is not exposed. Expose it to allow the users to change it.') . '</div>',
00276       );
00277       $form['expose_button']['button'] = array(
00278         '#limit_validation_errors' => array(),
00279         '#type' => 'submit',
00280         '#value' => t('Expose filter'),
00281         '#submit' => array('views_ui_config_item_form_expose'),
00282       );
00283       $form['expose_button']['checkbox']['checkbox']['#default_value'] = 0;
00284     }
00285     else {
00286       $form['expose_button']['markup'] = array(
00287         '#markup' => '<div class="description exposed-description">' . t('This filter is exposed. If you hide it, users will not be able to change it.') . '</div>',
00288       );
00289       $form['expose_button']['button'] = array(
00290         '#limit_validation_errors' => array(),
00291         '#type' => 'submit',
00292         '#value' => t('Hide filter'),
00293         '#submit' => array('views_ui_config_item_form_expose'),
00294       );
00295       $form['expose_button']['checkbox']['checkbox']['#default_value'] = 1;
00296     }
00297   }
00298 
00304   function expose_form(&$form, &$form_state) {
00305     $form['#theme'] = 'views_ui_expose_filter_form';
00306     // #flatten will move everything from $form['expose'][$key] to $form[$key]
00307     // prior to rendering. That's why the pre_render for it needs to run first,
00308     // so that when the next pre_render (the one for fieldsets) runs, it gets
00309     // the flattened data.
00310     array_unshift($form['#pre_render'], 'views_ui_pre_render_flatten_data');
00311     $form['expose']['#flatten'] = TRUE;
00312 
00313     if (empty($this->always_required)) {
00314       $form['expose']['required'] = array(
00315         '#type' => 'checkbox',
00316         '#title' => t('Required'),
00317         '#default_value' => $this->options['expose']['required'],
00318       );
00319     }
00320     else {
00321       $form['expose']['required'] = array(
00322         '#type' => 'value',
00323         '#value' => TRUE,
00324       );
00325     }
00326     $form['expose']['label'] = array(
00327       '#type' => 'textfield',
00328       '#default_value' => $this->options['expose']['label'],
00329       '#title' => t('Label'),
00330       '#size' => 40,
00331     );
00332 
00333     if (!empty($form['operator']['#type'])) {
00334        // Increase the width of the left (operator) column.
00335       $form['operator']['#prefix'] = '<div class="views-group-box views-left-40">';
00336       $form['operator']['#suffix'] = '</div>';
00337       $form['value']['#prefix'] = '<div class="views-group-box views-right-60">';
00338       $form['value']['#suffix'] = '</div>';
00339 
00340       $form['expose']['use_operator'] = array(
00341         '#type' => 'checkbox',
00342         '#title' => t('Expose operator'),
00343         '#description' => t('Allow the user to choose the operator.'),
00344         '#default_value' => !empty($this->options['expose']['use_operator']),
00345       );
00346       $form['expose']['operator_id'] = array(
00347         '#type' => 'textfield',
00348         '#default_value' => $this->options['expose']['operator_id'],
00349         '#title' => t('Operator identifier'),
00350         '#size' => 40,
00351         '#description' => t('This will appear in the URL after the ? to identify this operator.'),
00352         '#dependency' => array(
00353           'edit-options-expose-use-operator' => array(1)
00354         ),
00355         '#fieldset' => 'more',
00356       );
00357     }
00358     else {
00359       $form['expose']['operator_id'] = array(
00360         '#type' => 'value',
00361         '#value' => '',
00362       );
00363     }
00364 
00365     if (empty($this->always_multiple)) {
00366       $form['expose']['multiple'] = array(
00367         '#type' => 'checkbox',
00368         '#title' => t('Allow multiple selections'),
00369         '#description' => t('Enable to allow users to select multiple items.'),
00370         '#default_value' => $this->options['expose']['multiple'],
00371       );
00372     }
00373     $form['expose']['remember'] = array(
00374       '#type' => 'checkbox',
00375       '#title' => t('Remember the last selection'),
00376       '#description' => t('Enable to remember the last selection made by the user.'),
00377       '#default_value' => $this->options['expose']['remember'],
00378     );
00379 
00380     $form['expose']['identifier'] = array(
00381       '#type' => 'textfield',
00382       '#default_value' => $this->options['expose']['identifier'],
00383       '#title' => t('Filter identifier'),
00384       '#size' => 40,
00385       '#description' => t('This will appear in the URL after the ? to identify this filter. Cannot be blank.'),
00386       '#fieldset' => 'more',
00387     );
00388   }
00389 
00393   function expose_validate($form, &$form_state) {
00394     if (empty($form_state['values']['options']['expose']['identifier'])) {
00395       form_error($form['expose']['identifier'], t('The identifier is required if the filter is exposed.'));
00396     }
00397 
00398     if (!empty($form_state['values']['options']['expose']['identifier']) && $form_state['values']['options']['expose']['identifier'] == 'value') {
00399       form_error($form['expose']['identifier'], t('This identifier is not allowed.'));
00400     }
00401 
00402     if (!$this->view->display_handler->is_identifier_unique($form_state['id'], $form_state['values']['options']['expose']['identifier'])) {
00403       form_error($form['expose']['identifier'], t('This identifier is used by another handler.'));
00404     }
00405   }
00406 
00410   function expose_options() {
00411     $this->options['expose'] = array(
00412       'use_operator' => FALSE,
00413       'operator' => $this->options['id'] . '_op',
00414       'identifier' => $this->options['id'],
00415       'label' => $this->definition['title'],
00416       'remember' => FALSE,
00417       'multiple' => FALSE,
00418       'required' => FALSE,
00419     );
00420   }
00421 
00427   function exposed_form(&$form, &$form_state) {
00428     if (empty($this->options['exposed'])) {
00429       return;
00430     }
00431 
00432     // Build the exposed form, when its based on an operator.
00433     if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id'])) {
00434       $operator = $this->options['expose']['operator_id'];
00435       $this->operator_form($form, $form_state);
00436       $form[$operator] = $form['operator'];
00437 
00438       if (isset($form[$operator]['#title'])) {
00439         unset($form[$operator]['#title']);
00440       }
00441 
00442       $this->exposed_translate($form[$operator], 'operator');
00443 
00444       unset($form['operator']);
00445     }
00446 
00447     // Build the form and set the value based on the identifier.
00448     if (!empty($this->options['expose']['identifier'])) {
00449       $value = $this->options['expose']['identifier'];
00450       $this->value_form($form, $form_state);
00451       $form[$value] = $form['value'];
00452 
00453       if (isset($form[$value]['#title']) && !empty($form[$value]['#type']) && $form[$value]['#type'] != 'checkbox') {
00454         unset($form[$value]['#title']);
00455       }
00456 
00457       $this->exposed_translate($form[$value], 'value');
00458 
00459       if (!empty($form['#type']) && ($form['#type'] == 'checkboxes' || ($form['#type'] == 'select' && !empty($form['#multiple'])))) {
00460         unset($form[$value]['#default_value']);
00461       }
00462 
00463       if (!empty($form['#type']) && $form['#type'] == 'select' && empty($form['#multiple'])) {
00464         $form[$value]['#default_value'] = 'All';
00465       }
00466 
00467       if ($value != 'value') {
00468         unset($form['value']);
00469       }
00470     }
00471   }
00472 
00477   function exposed_translate(&$form, $type) {
00478     if (!isset($form['#type'])) {
00479       return;
00480     }
00481 
00482     if ($form['#type'] == 'radios') {
00483       $form['#type'] = 'select';
00484     }
00485     // Checkboxes don't work so well in exposed forms due to GET conversions.
00486     if ($form['#type'] == 'checkboxes') {
00487       if (empty($form['#no_convert']) || empty($this->options['expose']['multiple'])) {
00488         $form['#type'] = 'select';
00489       }
00490       if (!empty($this->options['expose']['multiple'])) {
00491         $form['#multiple'] = TRUE;
00492       }
00493     }
00494     if (empty($this->options['expose']['multiple']) && isset($form['#multiple'])) {
00495       unset($form['#multiple']);
00496       $form['#size'] = NULL;
00497     }
00498 
00499     if ($type == 'value' && empty($this->always_required) && empty($this->options['expose']['required']) && $form['#type'] == 'select' && empty($form['#multiple'])) {
00500       $any_label = variable_get('views_exposed_filter_any_label', 'new_any') == 'old_any' ? t('<Any>') : t('- Any -');
00501       $form['#options'] = array('All' => $any_label) + $form['#options'];
00502       $form['#default_value'] = 'All';
00503     }
00504 
00505     if (!empty($this->options['expose']['required'])) {
00506       $form['#required'] = TRUE;
00507     }
00508   }
00509 
00520   function exposed_info() {
00521     if (empty($this->options['exposed'])) {
00522       return;
00523     }
00524 
00525     return array(
00526       'operator' => $this->options['expose']['operator_id'],
00527       'value' => $this->options['expose']['identifier'],
00528       'label' => $this->options['expose']['label'],
00529     );
00530   }
00531 
00536   function accept_exposed_input($input) {
00537     if (empty($this->options['exposed'])) {
00538       return TRUE;
00539     }
00540 
00541 
00542     if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']) && isset($input[$this->options['expose']['operator_id']])) {
00543       $this->operator = $input[$this->options['expose']['operator_id']];
00544     }
00545 
00546     if (!empty($this->options['expose']['identifier'])) {
00547       $value = $input[$this->options['expose']['identifier']];
00548 
00549       // Various ways to check for the absence of non-required input.
00550       if (empty($this->options['expose']['required'])) {
00551         if (($this->operator == 'empty' || $this->operator == 'not empty') && $value === '') {
00552           $value = ' ';
00553         }
00554 
00555         if ($this->operator != 'empty' && $this->operator != 'not empty') {
00556           if ($value == 'All' || $value === array()) {
00557             return FALSE;
00558           }
00559         }
00560 
00561         if (!empty($this->always_multiple) && $value === '') {
00562           return FALSE;
00563         }
00564       }
00565 
00566 
00567       if (isset($value)) {
00568         $this->value = $value;
00569         if (empty($this->always_multiple) && empty($this->options['expose']['multiple'])) {
00570           $this->value = array($value);
00571         }
00572       }
00573       else {
00574         return FALSE;
00575       }
00576     }
00577 
00578     return TRUE;
00579   }
00580 
00581   function store_exposed_input($input, $status) {
00582     if (empty($this->options['exposed']) || empty($this->options['expose']['identifier'])) {
00583       return TRUE;
00584     }
00585 
00586     if (empty($this->options['expose']['remember'])) {
00587       return;
00588     }
00589 
00590     // Figure out which display id is responsible for the filters, so we
00591     // know where to look for session stored values.
00592     $display_id = ($this->view->display_handler->is_defaulted('filters')) ? 'default' : $this->view->current_display;
00593 
00594     // shortcut test.
00595     $operator = !empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']);
00596 
00597     // false means that we got a setting that means to recuse ourselves,
00598     // so we should erase whatever happened to be there.
00599     if (!$status && isset($_SESSION['views'][$this->view->name][$display_id])) {
00600       $session = &$_SESSION['views'][$this->view->name][$display_id];
00601       if ($operator && isset($session[$this->options['expose']['operator_id']])) {
00602         unset($session[$this->options['expose']['operator_id']]);
00603       }
00604 
00605       if (isset($session[$this->options['expose']['identifier']])) {
00606         unset($session[$this->options['expose']['identifier']]);
00607       }
00608     }
00609 
00610     if ($status) {
00611       if (!isset($_SESSION['views'][$this->view->name][$display_id])) {
00612         $_SESSION['views'][$this->view->name][$display_id] = array();
00613       }
00614 
00615       $session = &$_SESSION['views'][$this->view->name][$display_id];
00616 
00617       if ($operator && isset($input[$this->options['expose']['operator_id']])) {
00618         $session[$this->options['expose']['operator_id']] = $input[$this->options['expose']['operator_id']];
00619       }
00620 
00621       $session[$this->options['expose']['identifier']] = $input[$this->options['expose']['identifier']];
00622     }
00623   }
00624 
00632   function query() {
00633     $this->ensure_my_table();
00634     $this->query->add_where($this->options['group'], "$this->table_alias.$this->real_field", $this->value, $this->operator);
00635   }
00636 
00647    function can_group() {
00648      return TRUE;
00649    }
00650 }
00651 
00652 
00658 class views_handler_filter_broken extends views_handler_filter {
00659   function ui_name($short = FALSE) {
00660     return t('Broken/missing handler');
00661   }
00662 
00663   function ensure_my_table() { /* No table to ensure! */ }
00664   function query($group_by = FALSE) { /* No query to run */ }
00665   function options_form(&$form, &$form_state) {
00666     $form['markup'] = array(
00667       '#markup' => '<div class="form-item description">' . t('The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.') . '</div>',
00668     );
00669   }
00670 
00674   function broken() { return TRUE; }
00675 }
00676 
00677 

Generated on Sun Feb 26 2012 12:52:51 for Views by  doxygen 1.7.1