Yii Advanced Filters Extension
  • Package
  • Class

Packages

  • advancedfilters
    • components
    • dbhelpers
    • filters

Classes

  • AfBaseFilter
  • AfDefaultFilter
  • AfExactFilter
  • AfRangeFilter
  • AfRegexFilter
  • AfSubstringFilter
  1 <?php
  2 
  3 /**
  4  * AfRangeFilter class file.
  5  * 
  6  * @author Keith Burton <kburton@kappasoft.net>
  7  * @package advancedfilters.filters
  8  */
  9 
 10 /**
 11  * This filter handles numeric ranges.
 12  * 
 13  * If a prefix, infix or suffix string is set to an empty string, it will not
 14  * be used when identifying the expression type.
 15  */
 16 class AfRangeFilter extends AfBaseFilter
 17 {
 18     /**
 19      * @var string the prefix string for 'between' expressions.
 20      */
 21     public $betweenPrefix = '';
 22     
 23     /**
 24      * @var string the infix string for 'between' expressions.
 25      */
 26     public $betweenInfix = ' to ';
 27     
 28     /**
 29      * @var string the suffix string for 'between' expressions.
 30      */
 31     public $betweenSuffix = '';
 32     
 33     /**
 34      * @var string the prefix string for 'less than' expressions.
 35      */
 36     public $lessThanPrefix = '<';
 37     
 38     /**
 39      * @var string the suffix string for 'less than' expressions.
 40      */
 41     public $lessThanSuffix = '';
 42     
 43     
 44     /**
 45      * @var string the prefix string for 'less than or equal to' expressions.
 46      */
 47     public $lessThanEqualPrefix = '<=';
 48     
 49     /**
 50      * @var string the suffix string for 'less than or equal to' expressions.
 51      */
 52     public $lessThanEqualSuffix = '';
 53     
 54     
 55     /**
 56      * @var string the prefix string for 'greater than' expressions.
 57      */
 58     public $greaterThanPrefix = '>';
 59     
 60     /**
 61      * @var string the suffix string for 'greater than' expressions.
 62      */
 63     public $greaterThanSuffix = '';
 64     
 65     
 66     /**
 67      * @var string the prefix string for 'greater than or equal to' expressions.
 68      */
 69     public $greaterThanEqualPrefix = '>=';
 70     
 71     /**
 72      * @var string the suffix string for 'greater than or equal to' expressions.
 73      */
 74     public $greaterThanEqualSuffix = '';
 75     
 76     
 77     /**
 78      * @var string the prefix string for 'equal to' expressions.
 79      */
 80     public $equalPrefix = '=';
 81     
 82     /**
 83      * @var string the suffix string for 'equal to' expressions.
 84      */
 85     public $equalSuffix = '';
 86     
 87     /**
 88      * @var string the regular expression pattern used to identify numbers in
 89      * the provided filter expression.
 90      */
 91     public $numberPattern = '-?\\d*\\.?\\d+';
 92     
 93     /**
 94      * @var integer the number of digits that will be used to represent
 95      * database values once they are converted to a decimal format. Change this
 96      * if your data contains values that are too large to fit in a decimal of
 97      * this size.
 98      */
 99     public $conversionNumDigits = 20;
100     
101     /**
102      * @var integer the number of decimal places that will be used when
103      * converting database values to a decimal format. Change this if your data
104      * contains values with more decimal places. You may also need to override
105      * the $conversionNumDigits property.
106      */
107     public $conversionDecimalPlaces = 4;
108     
109     /**
110      * @var boolean whether columns which can't be converted to a number should
111      * be treated as having a zero value in numeric comparisons. If this is
112      * false, rows where the column is non-numeric will never be returned.
113      */
114     public $treatNonNumericValuesAsZero = false;
115     
116     private $startOfRange;
117     private $endOfRange;
118     private $rangeIsInclusive = true;
119     
120     /**
121      * Overrides the parent implementation to include a cast to decimal.
122      * 
123      * If $this->treatNonNumericTextAsZero is false, non-numeric column values
124      * will be converted to null.
125      * 
126      * @return string the updated column expression.
127      */
128     protected function getColumnExpression()
129     {
130         $columnExpression = parent::getColumnExpression();
131         
132         $nonNumericResultValue = $this->treatNonNumericValuesAsZero ? 0 : null;
133         
134         return $this->getDbHelper()->convertExpressionToDecimal(
135                 $columnExpression, $this->conversionNumDigits,
136                 $this->conversionDecimalPlaces, $nonNumericResultValue);
137     }
138     
139     /**
140      * Determines whether the provided expression can be processed by this
141      * filter class.
142      * 
143      * @return boolean whether this class can process the expression.
144      */
145     public function acceptsFilterExpression()
146     {
147         return $this->parseExpression();
148     }
149     
150     /**
151      * Builds a new CDbCriteria object based on the expression provided.
152      * 
153      * @return CDbCriteria the new criteria object.
154      */
155     public function getCriteria()
156     {
157         $this->parseExpression();
158         
159         $criteria = new CDbCriteria;
160         
161         $column = $this->columnExpression;
162         
163         $hash = md5($this->filterExpression . $this->columnExpression);
164         $startParam = ':rangeStart' . $hash;
165         $endParam = ':rangeEnd' . $hash;
166         
167         if ($this->startOfRange !== null)
168         {
169             $operator = $this->rangeIsInclusive
170                     ? ($this->invertLogic ? '<' : '>=')
171                     : ($this->invertLogic ? '<=' : '>');
172             
173             $criteria->addCondition("$column $operator $startParam");
174             $criteria->params[$startParam] = $this->startOfRange;
175         }
176         
177         if ($this->endOfRange !== null)
178         {
179             $operator = $this->rangeIsInclusive
180                     ? ($this->invertLogic ? '>' : '<=')
181                     : ($this->invertLogic ? '>=' : '<');
182             
183             // Merge type only applies for between and equal ranges
184             $mergeType = $this->invertLogic ? 'OR' : 'AND';
185             
186             $criteria->addCondition("$column $operator $endParam",
187                     $mergeType);
188             $criteria->params[$endParam] = $this->endOfRange;
189         }
190         
191         return $criteria;
192     }
193     
194     private $_expressionAccepted;
195     private function parseExpression()
196     {
197         // Only need to parse the expression once
198         if ($this->_expressionAccepted !== null)
199             return $this->_expressionAccepted;
200         
201         $this->_expressionAccepted = true;
202         
203         $expression = $this->filterExpression;
204         
205         // First check for between matches and return early if found
206         $betweenMatches = array();
207         
208         if (preg_match($this->getBetweenPattern(), $expression,
209                 $betweenMatches))
210         {
211             $this->startOfRange = $betweenMatches[1];
212             $this->endOfRange = $betweenMatches[2];
213             return $this->_expressionAccepted;
214         }
215         
216         // Check for any other pattern matches
217         $matches = array();
218         
219         if (preg_match($this->getLessThanPattern(), $expression, $matches))
220         {
221             $this->endOfRange = $matches[1];
222             $this->rangeIsInclusive = false;
223         }
224         else if (preg_match($this->getLessThanEqualPattern(), $expression,
225                 $matches))
226         {
227             $this->endOfRange = $matches[1];
228         }
229         else if (preg_match($this->getGreaterThanPattern(), $expression,
230                 $matches))
231         {
232             $this->startOfRange = $matches[1];
233             $this->rangeIsInclusive = false;
234         }
235         else if (preg_match($this->getGreaterThanEqualPattern(), $expression,
236                 $matches))
237         {
238             $this->startOfRange = $matches[1];
239         }
240         else if (preg_match($this->getEqualPattern(), $expression, $matches))
241         {
242             $this->startOfRange = $matches[1];
243             $this->endOfRange = $matches[1];
244         }
245         else
246         {
247             $this->_expressionAccepted = false;
248         }
249         
250         return $this->_expressionAccepted;
251     }
252     
253     private function getBetweenPattern()
254     {
255         return '/^'
256                 . preg_quote($this->betweenPrefix, '/')
257                 . '\\s*(' . $this->numberPattern . ')\\s*'
258                 . preg_quote($this->betweenInfix, '/')
259                 . '\\s*(' . $this->numberPattern . ')\\s*'
260                 . preg_quote($this->betweenSuffix, '/')
261                 . '$/i';
262     }
263     
264     private function getLessThanPattern()
265     {
266         return '/^'
267                 . preg_quote($this->lessThanPrefix, '/')
268                 . '\\s*(' . $this->numberPattern . ')\\s*'
269                 . preg_quote($this->lessThanSuffix, '/')
270                 . '$/i';
271     }
272     
273     private function getLessThanEqualPattern()
274     {
275         return '/^'
276                 . preg_quote($this->lessThanEqualPrefix, '/')
277                 . '\\s*(' . $this->numberPattern . ')\\s*'
278                 . preg_quote($this->lessThanEqualSuffix, '/')
279                 . '$/i';
280     }
281     
282     private function getGreaterThanPattern()
283     {
284         return '/^'
285                 . preg_quote($this->greaterThanPrefix, '/')
286                 . '\\s*(' . $this->numberPattern . ')\\s*'
287                 . preg_quote($this->greaterThanSuffix, '/')
288                 . '$/i';
289     }
290     
291     private function getGreaterThanEqualPattern()
292     {
293         return '/^'
294                 . preg_quote($this->greaterThanEqualPrefix, '/')
295                 . '\\s*(' . $this->numberPattern . ')\\s*'
296                 . preg_quote($this->greaterThanEqualSuffix, '/')
297                 . '$/i';
298     }
299     
300     private function getEqualPattern()
301     {
302         return '/^'
303                 . preg_quote($this->equalPrefix, '/')
304                 . '\\s*(' . $this->numberPattern . ')\\s*'
305                 . preg_quote($this->equalSuffix, '/')
306                 . '$/i';
307     }
308 }
309 
Yii Advanced Filters Extension API documentation generated by ApiGen