-
Notifications
You must be signed in to change notification settings - Fork 0
/
DataFilterer.php
243 lines (208 loc) · 7.01 KB
/
DataFilterer.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
<?php
/**
* Basic component for the data-filter extension
*
* @author Steve Guns <[email protected]>
* @package dataFilter
* @category com.bedezign.extensions
* @copyright 2013 B&E DeZign
*/
/**
* The DataFilterer class is the hub of the filter support. This class connects the actual filters and the widget.
*
* It also allows you to serialize data in between calls (eg if you want to save a filter selection to apply to multiple pages).
* Keep in mind that because the extension wants to be as expandable as possible, it also saves the actual filters that are added.
* This way you can dynamically add filters without having to create the entire structure on each page call.
* It does result in a bit more work as you have to check (when creating the Filterer instance) if it has filters already.
*/
class DataFilterer extends CComponent
{
protected $_oModel = NULL;
protected $_aFilters = array();
protected $_sSessionVariable = NULL;
protected $_sIdentifier = NULL;
/** @var array Contains the data from the last load */
protected $_aLastRequest = NULL;
/**
* Model that can be used by the filters as a base to generate their HTML from, or interpret the incoming data.
* @param CModel $oModel
* @throws RuntimeException If the specified model does not implement IFilterable
*/
public function setModel($oModel)
{
if (!$oModel instanceof IFilterable)
throw new RuntimeException('The specified model should implement IFilterable');
$this->_oModel = $oModel;
if ($this->_sIdentifier === NULL)
$this->_sIdentifier = get_class($oModel) . 'Filter';
}
public function getModel() { return $this->_oModel; }
/**
* The base name for the form. This is usually the model class name + Filter (set by assigning a model).
* @param string $sIdentifier
*/
public function setId($sIdentifier) { $this->_sIdentifier = $sIdentifier; }
public function getId() { return $this->_sIdentifier; }
/**
* If you set this to a non-NULL value the filterer will save itself in the session between calls.
* This includes the filters and their values
* @param string $sSessionVariable
*/
public function setSessionVariable($sSessionVariable)
{
$this->_sSessionVariable = $sSessionVariable;
// Make sure we get the opportunity to save ourselves
Yii::app()->attachEventHandler('onEndRequest', array($this, 'saveToSession'));
}
public function getSessionVariable()
{
return $this->_sSessionVariable;
}
/**
* @param DataFilter $oFilter
* @param bool $bReplace
* @return DataFilter|NULL The filter instance (if it was added)
*/
public function addFilter($oFilter, $bReplace = FALSE)
{
$oFilter->filterer = $this;
if (isset($this->_aFilters[$oFilter->activeId]) && !$bReplace)
return NULL;
$this->_aFilters[$oFilter->activeId] = $oFilter;
$this->onFilterAdd(new CEvent($this, array('filter' => $oFilter)));
return $oFilter;
}
public function removeFilter($sIdentifier)
{
if (!isset($this->_aFilters[$sIdentifier]))
return;
$this->onFilterRemoved(new CEvent($this, array('filter' => $this->_aFilters[$sIdentifier])));
unset($this->_aFilters[$sIdentifier]);
}
public function getFilters() { return $this->_aFilters; }
public function getFilterCount() { return count($this->_aFilters); }
/**
* Collects the HTML code for all the filters and returns it.
* The return format is an array of separate html blocks with the filter-id as key (and sometimes an extra label)
* @param CWidget $oWidget
* @param bool $bRenderDisabled
* @return string[]
*/
public function getHtml($oWidget, $bRenderDisabled = FALSE)
{
$aHtml = array();
foreach ($this->_aFilters as $oFilter)
if ($oFilter->enabled || $bRenderDisabled)
$aHtml = array_merge($aHtml, $oFilter->getHtml($oWidget));
return $aHtml;
}
/**
* Applies the filters to the given Criteria object.
* @param CDbCriteria $oCriteria
*/
public function apply($oCriteria)
{
foreach ($this->_aFilters as $oFilter)
if ($oFilter->enabled)
$oFilter->apply($oCriteria);
}
/**
* If anything was submitted for the filterer, this function will return it
* @return array
*/
public function getIsSubmitted()
{
return Yii::app()->request->getParam($this->id) !== NULL;
}
/**
* Returns whether the filterer has received data and can run (you can use this to auto-run the filterer after
* either a submit or a restore that had previous data)
* @return bool
*/
public function getHasData()
{
return $this->_aLastRequest !== NULL;
}
/**
* Instructs the filterer to load either the specified data (or the submitted one if $aData is NULL)
* @param array|NULL $aData If NULL, load from either GET or POST
* @return bool TRUE if data was loaded, FALSE if not
*/
public function loadData($aData = NULL)
{
if (!$aData)
$aData = Yii::app()->request->getParam($this->id);
if (!$aData)
return FALSE;
foreach ($this->_aFilters as $oFilter)
$oFilter->loadData($aData);
$this->_aLastRequest = $aData;
return TRUE;
}
/**
* Adds all the filter data to the session (if a sessionVariable was specified).
* Note that the complete filters are saved. During restore all these filters will be pre-created. Make sure to
* not add them again (duplicates).
* @return bool
*/
public function saveToSession()
{
if (!$this->sessionVariable)
return FALSE;
$aFilters = array();
foreach ($this->_aFilters as $sFilterId => $oFilter)
$aFilters[$sFilterId] = $oFilter->save();
Yii::app()->user->setState($this->sessionVariable, array('last' => $this->_aLastRequest, 'filters' => $aFilters));
return TRUE;
}
/**
* @return bool
*/
public function loadFromSession()
{
if (!$this->sessionVariable)
return FALSE;
$aData = Yii::app()->user->getState($this->sessionVariable);
if (!$aData)
return FALSE;
foreach ($aData['filters'] as $sFilterId => $aFilter)
if ($oFilter = DataFilter::restore($this, $aFilter))
$this->_aFilters[$sFilterId] = $oFilter;
$this->_aLastRequest = isset($aData['last']) ? $aData['last'] : NULL;
return TRUE;
}
public function clearFromSession()
{
if ($this->sessionVariable)
Yii::app()->user->setState($this->sessionVariable, NULL);
}
public static function cleanup($sSessionVariable)
{
Yii::app()->user->setState($sSessionVariable, NULL);
}
/**
* Create a new filterer for the given model and loads the data/configuration from the session if needed
* @param CModel $oModel
* @param String $sSessionVariable
* @return self
*/
public static function create($oModel, $sSessionVariable = NULL)
{
$oDataFilter = new self;
$oDataFilter->model = is_string($oModel) ? new $oModel : $oModel;
if ($sSessionVariable !== NULL)
{
$oDataFilter->sessionVariable = $sSessionVariable;
$oDataFilter->loadFromSession();
}
return $oDataFilter;
}
public function onFilterAdd($oEvent)
{
$this->raiseEvent('onFilterAdd', $oEvent);
}
public function onFilterRemoved($oEvent)
{
$this->raiseEvent('onFilterRemoved', $oEvent);
}
}