1 <?php
2
3 /**
4 * AdvancedFilters class file.
5 *
6 * @author Keith Burton <kburton@kappasoft.net>
7 * @package advancedfilters
8 */
9
10 // Define a different path alias for this extension in the config file to
11 // override this default.
12 defined('ADVANCED_FILTERS_BASE_PATH_ALIAS') or
13 define('ADVANCED_FILTERS_BASE_PATH_ALIAS', 'advancedFiltersBasePath');
14
15 // Set path alias and import extension sub-directories
16 Yii::setPathOfAlias(ADVANCED_FILTERS_BASE_PATH_ALIAS, dirname(__FILE__));
17 Yii::import(ADVANCED_FILTERS_BASE_PATH_ALIAS . '.components.*');
18 Yii::import(ADVANCED_FILTERS_BASE_PATH_ALIAS . '.dbhelpers.*');
19 Yii::import(ADVANCED_FILTERS_BASE_PATH_ALIAS . '.filters.*');
20
21 /**
22 * This class is the application component for the advanced filters extension.
23 * All interaction with the extension should be initiated through this class.
24 *
25 * If you're not using an extended version of CDbCriteria, the easiest way to
26 * use this extension is to create an AfDbCriteria object. You can use this
27 * in the same way as CDbCriteria, with an additional method to add advanced
28 * filter conditions:
29 *
30 * $criteria = Yii::app()->advancedFilters->createCriteria();
31 * $criteria->addInCondition('id', array(1, 2, 3, 4));
32 * $criteria->addAdvancedFilterCondition('code', '/^[A-C]/');
33 * $items = Item::model()->findAll($criteria);
34 *
35 * If you have extended CDbCriteria, you can instead use the following method to
36 * update your criteria:
37 *
38 * $criteria = new YourCriteriaClass;
39 * $criteria->addInCondition('id', array(1, 2, 3, 4));
40 * Yii::app()->advancedFilters
41 * ->addAdvancedFilterCondition($criteria, 'code', '/^[A-C]/');
42 * $items = Item::model()->findAll($criteria);
43 *
44 * All configuration is passed through to the AfParser class. The
45 * filterConfig array is used to override the default config for the inbuilt
46 * filter classes and to add new classes.
47 *
48 * To override the properties of an existing filter class, use one of the
49 * predefined array keys: 'range', 'exact', 'substring', 'regex', 'default'.
50 *
51 * To add a new filter, add an array with an unused key in the following format:
52 *
53 * 'advancedFilters'=>array(
54 * 'example'=>array(
55 * 'class'=>'path.to.ExampleFilterClass',
56 * 'priority'=>25,
57 * ),
58 * ),
59 *
60 * The filter class should extend AfBaseFilter.
61 *
62 * The priority defines when the filter is processed in relation to the other
63 * filters. Filters with lower numbers are processed first, and the first filter
64 * that accepts a pattern segment will process that segment. You can change the
65 * order of default filters by altering their priority in the same way.
66 *
67 * You can deactivate any filter by setting its 'active' property to false.
68 *
69 * Each filter class only receives a segment of the entered filter expression
70 * produced by splitting the expression on the "and" and "or" delimiters and
71 * removing any invert prefix and suffix. Whitespace around the segment is
72 * also removed.
73 */
74 class AdvancedFilters extends CApplicationComponent
75 {
76 /**
77 * @var string the string used to 'or' filter expressions together.
78 * Set this to an empty string to remove this functionality.
79 */
80 public $orDelimiter;
81
82 /**
83 * @var string the string used to 'and' filter expressions together.
84 * Set this to an empty string to remove this functionality.
85 */
86 public $andDelimiter;
87
88 /**
89 * @var string the string which can be prepended to a delimiter string to
90 * allow its use within a filter expression.
91 * Set this to an empty string to disallow escaping.
92 */
93 public $escapeSequence;
94
95 /**
96 * @var string the string which can be prepended to a filter expression in
97 * order to invert its logic and return the opposite results.
98 * You can specify values for both $invertLogicPrefix and
99 * $invertLogicSuffix to require that the expression be enclosed
100 * between two specific strings in order to invert the logic.
101 * Set both to an empty string to prevent logic inversion.
102 */
103 public $invertLogicPrefix;
104
105 /**
106 * @var string the string which can be appended to a filter expression in
107 * order to invert its logic and return the opposite results.
108 * You can specify values for both $invertLogicPrefix and
109 * $invertLogicSuffix to require that the expression be enclosed
110 * between two specific strings in order to invert the logic.
111 * Set both to an empty string to prevent logic inversion.
112 */
113 public $invertLogicSuffix;
114
115 /**
116 * @var CDbConnection|string either a CDbConnection object or the string
117 * name of an application component representing a CDbConnection.
118 * Defaults to 'db'.
119 */
120 public $dbConnection;
121
122 /**
123 * @var array mapping between PDO driver and database helper class name.
124 * Each database helper must extend AfBaseDbHelper.
125 * If the $dbConnection has a driver name that is not specified in this
126 * array, or it maps to null, an AfException will be thrown.
127 */
128 public $driverMap;
129
130 /**
131 * @var array the default filters to load, and the priorities of each.
132 * Lower priority values mean that the pattern will be tested against the
133 * filter earlier, so more specific filters should be given a lower number
134 * than more general filters.
135 * Override the 'active' property to specify whether each filter should be
136 * used when processing filter expressions. The default filter cannot be
137 * deactivated.
138 * Any additional configuration will be applied to the specific filter class
139 * when it is instantiated.
140 */
141 public $filterConfig;
142
143 /**
144 * Instantiates and returns a new AfDbCriteria object.
145 * Applies any application level configuration defined in your config file,
146 * which can be overridden using the $config parameter.
147 *
148 * Use this method if you have not extended CDbCriteria with a customised
149 * class.
150 *
151 * @param array $data the initial property values to pass to the base
152 * CDbCriteria class.
153 * @param array $config override the application level AdvancedFilters
154 * configuration.
155 * @return AfDbCriteria the configured criteria object.
156 */
157 public function createCriteria($data=array(), $config=array())
158 {
159 // Merge the default properties with the provided config
160 $config = CMap::mergeArray(get_object_vars($this), $config);
161
162 return new AfDbCriteria($data, $config);
163 }
164
165 /**
166 * Add an advanced filter condition to an existing instance of CDbCriteria
167 * or a class extending CDbCriteria.
168 *
169 * Use this method if you have extended CDbCriteria with a customised class.
170 *
171 * @param CDbCriteria $criteria the criteria to update.
172 * @param string $columnExpression the disambiguated column name (or a
173 * valid SQL expression).
174 * @param string $filterExpression the entered filter expression.
175 * @param string $operator the operator used to concatenate the new
176 * condition with the existing one. Defaults to 'AND'.
177 * @param array $config override the application level AdvancedFilters
178 * configuration.
179 */
180 public function addAdvancedFilterCondition($criteria, $columnExpression,
181 $filterExpression, $operator='AND', $config=array())
182 {
183 $newCriteria = $this->createCriteria();
184
185 $newCriteria->addAdvancedFilterCondition($columnExpression,
186 $filterExpression, $operator, $config);
187
188 $criteria->mergeWith($newCriteria);
189 }
190 }
191