1<?php 2/** 3 * Simple filter to handle matching of boolean values 4 * 5 * Definition items: 6 * - label: (REQUIRED) The label for the checkbox. 7 * - type: For basic 'true false' types, an item can specify the following: 8 * - true-false: True/false (this is the default) 9 * - yes-no: Yes/No 10 * - on-off: On/Off 11 * - accept null: Treat a NULL value as false. 12 */ 13class views_handler_filter_boolean_operator extends views_handler_filter { 14 // exposed filter options 15 var $no_single = TRUE; 16 // Don't display empty space where the operator would be. 17 var $no_operator = TRUE; 18 // Whether to accept NULL as a false value or not 19 var $accept_null = FALSE; 20 21 function construct() { 22 $this->value_value = t('True'); 23 if (isset($this->definition['label'])) { 24 $this->value_value = $this->definition['label']; 25 } 26 if (isset($this->definition['accept null'])) { 27 $this->accept_null = (bool) $this->definition['accept null']; 28 } 29 else if (isset($this->definition['accept_null'])) { 30 $this->accept_null = (bool) $this->definition['accept_null']; 31 } 32 $this->value_options = NULL; 33 parent::construct(); 34 } 35 36 /** 37 * Return the possible options for this filter. 38 * 39 * Child classes should override this function to set the possible values 40 * for the filter. Since this is a boolean filter, the array should have 41 * two possible keys: 1 for "True" and 0 for "False", although the labels 42 * can be whatever makes sense for the filter. These values are used for 43 * configuring the filter, when the filter is exposed, and in the admin 44 * summary of the filter. Normally, this should be static data, but if it's 45 * dynamic for some reason, child classes should use a guard to reduce 46 * database hits as much as possible. 47 */ 48 function get_value_options() { 49 if (isset($this->definition['type'])) { 50 if ($this->definition['type'] == 'yes-no') { 51 $this->value_options = array(1 => t('Yes'), 0 => t('No')); 52 } 53 if ($this->definition['type'] == 'on-off') { 54 $this->value_options = array(1 => t('On'), 0 => t('Off')); 55 } 56 } 57 58 // Provide a fallback if the above didn't set anything. 59 if (!isset($this->value_options)) { 60 $this->value_options = array(1 => t('True'), 0 => t('False')); 61 } 62 } 63 64 function option_definition() { 65 $options = parent::option_definition(); 66 67 $options['value']['default'] = FALSE; 68 69 return $options; 70 } 71 72 function operator_form(&$form, &$form_state) { 73 $form['operator'] = array(); 74 } 75 76 function value_form(&$form, &$form_state) { 77 if (empty($this->value_options)) { 78 // Initialize the array of possible values for this filter. 79 $this->get_value_options(); 80 } 81 if (!empty($form_state['exposed'])) { 82 // Exposed filter: use a select box to save space. 83 $filter_form_type = 'select'; 84 } 85 else { 86 // Configuring a filter: use radios for clarity. 87 $filter_form_type = 'radios'; 88 } 89 $form['value'] = array( 90 '#type' => $filter_form_type, 91 '#title' => $this->value_value, 92 '#options' => $this->value_options, 93 '#default_value' => $this->value, 94 ); 95 if (!empty($this->options['exposed'])) { 96 $identifier = $this->options['expose']['identifier']; 97 if (!isset($form_state['input'][$identifier])) { 98 $form_state['input'][$identifier] = $this->value; 99 } 100 // If we're configuring an exposed filter, add an <Any> option. 101 if (empty($form_state['exposed']) || !empty($this->options['optional'])) { 102 $any_label = variable_get('views_exposed_filter_any_label', 'old_any') == 'old_any' ? '<Any>' : t('- Any -'); 103 if ($form['value']['#type'] != 'select') { 104 $any_label = check_plain($any_label); 105 } 106 $form['value']['#options'] = array('All' => $any_label) + $form['value']['#options']; 107 } 108 } 109 } 110 111 function value_validate($form, &$form_state) { 112 if ($form_state['values']['options']['value'] == 'All' && empty($form_state['values']['options']['expose']['optional'])) { 113 form_set_error('value', t('You must select a value unless this is an optional exposed filter.')); 114 } 115 } 116 117 function admin_summary() { 118 if (!empty($this->options['exposed'])) { 119 return t('exposed'); 120 } 121 if (empty($this->value_options)) { 122 $this->get_value_options(); 123 } 124 // Now that we have the valid options for this filter, just return the 125 // human-readable label based on the current value. The value_options 126 // array is keyed with either 0 or 1, so if the current value is not 127 // empty, use the label for 1, and if it's empty, use the label for 0. 128 return $this->value_options[!empty($this->value)]; 129 } 130 131 function expose_options() { 132 parent::expose_options(); 133 $this->options['expose']['operator'] = ''; 134 $this->options['expose']['label'] = $this->value_value; 135 $this->options['expose']['optional'] = FALSE; 136 } 137 138 function query() { 139 $this->ensure_my_table(); 140 141 $where = "$this->table_alias.$this->real_field "; 142 143 if (empty($this->value)) { 144 $where .= '= 0'; 145 if ($this->accept_null) { 146 $where = '(' . $where . " OR $this->table_alias.$this->real_field IS NULL)"; 147 } 148 } 149 else { 150 if (!empty($this->definition['use equal'])) { 151 $where .= '= 1'; 152 } 153 else { 154 $where .= '<> 0'; 155 } 156 } 157 $this->query->add_where($this->options['group'], $where); 158 } 159} 160