1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @link https://www.yiiframework.com/ |
4
|
|
|
* @copyright Copyright (c) 2008 Yii Software LLC |
5
|
|
|
* @license https://www.yiiframework.com/license/ |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace yii\data; |
9
|
|
|
|
10
|
|
|
use Yii; |
11
|
|
|
use yii\base\BaseObject; |
12
|
|
|
use yii\base\InvalidConfigException; |
13
|
|
|
use yii\helpers\Html; |
14
|
|
|
use yii\helpers\Inflector; |
15
|
|
|
use yii\web\Request; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Sort represents information relevant to sorting. |
19
|
|
|
* |
20
|
|
|
* When data needs to be sorted according to one or several attributes, |
21
|
|
|
* we can use Sort to represent the sorting information and generate |
22
|
|
|
* appropriate hyperlinks that can lead to sort actions. |
23
|
|
|
* |
24
|
|
|
* A typical usage example is as follows, |
25
|
|
|
* |
26
|
|
|
* ```php |
27
|
|
|
* public function actionIndex() |
28
|
|
|
* { |
29
|
|
|
* $sort = new Sort([ |
30
|
|
|
* 'attributes' => [ |
31
|
|
|
* 'age', |
32
|
|
|
* 'name' => [ |
33
|
|
|
* 'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC], |
34
|
|
|
* 'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC], |
35
|
|
|
* 'default' => SORT_DESC, |
36
|
|
|
* 'label' => 'Name', |
37
|
|
|
* ], |
38
|
|
|
* ], |
39
|
|
|
* ]); |
40
|
|
|
* |
41
|
|
|
* $models = Article::find() |
42
|
|
|
* ->where(['status' => 1]) |
43
|
|
|
* ->orderBy($sort->orders) |
44
|
|
|
* ->all(); |
45
|
|
|
* |
46
|
|
|
* return $this->render('index', [ |
47
|
|
|
* 'models' => $models, |
48
|
|
|
* 'sort' => $sort, |
49
|
|
|
* ]); |
50
|
|
|
* } |
51
|
|
|
* ``` |
52
|
|
|
* |
53
|
|
|
* View: |
54
|
|
|
* |
55
|
|
|
* ```php |
56
|
|
|
* // display links leading to sort actions |
57
|
|
|
* echo $sort->link('name') . ' | ' . $sort->link('age'); |
58
|
|
|
* |
59
|
|
|
* foreach ($models as $model) { |
60
|
|
|
* // display $model here |
61
|
|
|
* } |
62
|
|
|
* ``` |
63
|
|
|
* |
64
|
|
|
* In the above, we declare two [[attributes]] that support sorting: `name` and `age`. |
65
|
|
|
* We pass the sort information to the Article query so that the query results are |
66
|
|
|
* sorted by the orders specified by the Sort object. In the view, we show two hyperlinks |
67
|
|
|
* that can lead to pages with the data sorted by the corresponding attributes. |
68
|
|
|
* |
69
|
|
|
* For more details and usage information on Sort, see the [guide article on sorting](guide:output-sorting). |
70
|
|
|
* |
71
|
|
|
* @property array $attributeOrders Sort directions indexed by attribute names. Sort direction can be either |
72
|
|
|
* `SORT_ASC` for ascending order or `SORT_DESC` for descending order. Note that the type of this property |
73
|
|
|
* differs in getter and setter. See [[getAttributeOrders()]] and [[setAttributeOrders()]] for details. |
74
|
|
|
* @property-read array $orders The columns (keys) and their corresponding sort directions (values). This can |
75
|
|
|
* be passed to [[\yii\db\Query::orderBy()]] to construct a DB query. |
76
|
|
|
* |
77
|
|
|
* @author Qiang Xue <[email protected]> |
78
|
|
|
* @since 2.0 |
79
|
|
|
*/ |
80
|
|
|
class Sort extends BaseObject |
81
|
|
|
{ |
82
|
|
|
/** |
83
|
|
|
* @var bool whether the sorting can be applied to multiple attributes simultaneously. |
84
|
|
|
* Defaults to `false`, which means each time the data can only be sorted by one attribute. |
85
|
|
|
*/ |
86
|
|
|
public $enableMultiSort = false; |
87
|
|
|
/** |
88
|
|
|
* @var array list of attributes that are allowed to be sorted. Its syntax can be |
89
|
|
|
* described using the following example: |
90
|
|
|
* |
91
|
|
|
* ```php |
92
|
|
|
* [ |
93
|
|
|
* 'age', |
94
|
|
|
* 'name' => [ |
95
|
|
|
* 'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC], |
96
|
|
|
* 'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC], |
97
|
|
|
* 'default' => SORT_DESC, |
98
|
|
|
* 'label' => 'Name', |
99
|
|
|
* ], |
100
|
|
|
* ] |
101
|
|
|
* ``` |
102
|
|
|
* |
103
|
|
|
* In the above, two attributes are declared: `age` and `name`. The `age` attribute is |
104
|
|
|
* a simple attribute which is equivalent to the following: |
105
|
|
|
* |
106
|
|
|
* ```php |
107
|
|
|
* 'age' => [ |
108
|
|
|
* 'asc' => ['age' => SORT_ASC], |
109
|
|
|
* 'desc' => ['age' => SORT_DESC], |
110
|
|
|
* 'default' => SORT_ASC, |
111
|
|
|
* 'label' => Inflector::camel2words('age'), |
112
|
|
|
* ] |
113
|
|
|
* ``` |
114
|
|
|
* |
115
|
|
|
* Since 2.0.12 particular sort direction can be also specified as direct sort expression, like following: |
116
|
|
|
* |
117
|
|
|
* ```php |
118
|
|
|
* 'name' => [ |
119
|
|
|
* 'asc' => '[[last_name]] ASC NULLS FIRST', // PostgreSQL specific feature |
120
|
|
|
* 'desc' => '[[last_name]] DESC NULLS LAST', |
121
|
|
|
* ] |
122
|
|
|
* ``` |
123
|
|
|
* |
124
|
|
|
* The `name` attribute is a composite attribute: |
125
|
|
|
* |
126
|
|
|
* - The `name` key represents the attribute name which will appear in the URLs leading |
127
|
|
|
* to sort actions. |
128
|
|
|
* - The `asc` and `desc` elements specify how to sort by the attribute in ascending |
129
|
|
|
* and descending orders, respectively. Their values represent the actual columns and |
130
|
|
|
* the directions by which the data should be sorted by. |
131
|
|
|
* - The `default` element specifies by which direction the attribute should be sorted |
132
|
|
|
* if it is not currently sorted (the default value is ascending order). |
133
|
|
|
* - The `label` element specifies what label should be used when calling [[link()]] to create |
134
|
|
|
* a sort link. If not set, [[Inflector::camel2words()]] will be called to get a label. |
135
|
|
|
* Note that it will not be HTML-encoded. |
136
|
|
|
* |
137
|
|
|
* Note that if the Sort object is already created, you can only use the full format |
138
|
|
|
* to configure every attribute. Each attribute must include these elements: `asc` and `desc`. |
139
|
|
|
*/ |
140
|
|
|
public $attributes = []; |
141
|
|
|
/** |
142
|
|
|
* @var string the name of the parameter that specifies which attributes to be sorted |
143
|
|
|
* in which direction. Defaults to `sort`. |
144
|
|
|
* @see params |
145
|
|
|
*/ |
146
|
|
|
public $sortParam = 'sort'; |
147
|
|
|
/** |
148
|
|
|
* @var array|null the order that should be used when the current request does not specify any order. |
149
|
|
|
* The array keys are attribute names and the array values are the corresponding sort directions. For example, |
150
|
|
|
* |
151
|
|
|
* ```php |
152
|
|
|
* [ |
153
|
|
|
* 'name' => SORT_ASC, |
154
|
|
|
* 'created_at' => SORT_DESC, |
155
|
|
|
* ] |
156
|
|
|
* ``` |
157
|
|
|
* |
158
|
|
|
* @see attributeOrders |
159
|
|
|
*/ |
160
|
|
|
public $defaultOrder; |
161
|
|
|
/** |
162
|
|
|
* @var string|null the route of the controller action for displaying the sorted contents. |
163
|
|
|
* If not set, it means using the currently requested route. |
164
|
|
|
*/ |
165
|
|
|
public $route; |
166
|
|
|
/** |
167
|
|
|
* @var string the character used to separate different attributes that need to be sorted by. |
168
|
|
|
*/ |
169
|
|
|
public $separator = ','; |
170
|
|
|
/** |
171
|
|
|
* @var array|null parameters (name => value) that should be used to obtain the current sort directions |
172
|
|
|
* and to create new sort URLs. If not set, `$_GET` will be used instead. |
173
|
|
|
* |
174
|
|
|
* In order to add hash to all links use `array_merge($_GET, ['#' => 'my-hash'])`. |
175
|
|
|
* |
176
|
|
|
* The array element indexed by [[sortParam]] is considered to be the current sort directions. |
177
|
|
|
* If the element does not exist, the [[defaultOrder|default order]] will be used. |
178
|
|
|
* |
179
|
|
|
* @see sortParam |
180
|
|
|
* @see defaultOrder |
181
|
|
|
*/ |
182
|
|
|
public $params; |
183
|
|
|
/** |
184
|
|
|
* @var \yii\web\UrlManager|null the URL manager used for creating sort URLs. If not set, |
185
|
|
|
* the `urlManager` application component will be used. |
186
|
|
|
*/ |
187
|
|
|
public $urlManager; |
188
|
|
|
/** |
189
|
|
|
* @var int Allow to control a value of the fourth parameter which will be |
190
|
|
|
* passed to [[ArrayHelper::multisort()]] |
191
|
|
|
* @since 2.0.33 |
192
|
|
|
*/ |
193
|
|
|
public $sortFlags = SORT_REGULAR; |
194
|
|
|
/** |
195
|
|
|
* @var string|null the name of the [[\yii\base\Model]]-based class used by the [[link()]] method to retrieve |
196
|
|
|
* attributes' labels. See [[link]] method for details. |
197
|
|
|
* @since 2.0.49 |
198
|
|
|
*/ |
199
|
|
|
public $modelClass; |
200
|
|
|
|
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* Normalizes the [[attributes]] property. |
204
|
|
|
*/ |
205
|
97 |
|
public function init() |
206
|
|
|
{ |
207
|
97 |
|
$attributes = []; |
208
|
97 |
|
foreach ($this->attributes as $name => $attribute) { |
209
|
40 |
|
if (!is_array($attribute)) { |
210
|
35 |
|
$attributes[$attribute] = [ |
211
|
35 |
|
'asc' => [$attribute => SORT_ASC], |
212
|
35 |
|
'desc' => [$attribute => SORT_DESC], |
213
|
|
|
]; |
214
|
24 |
|
} elseif (!isset($attribute['asc'], $attribute['desc'])) { |
215
|
|
|
$attributes[$name] = array_merge([ |
216
|
|
|
'asc' => [$name => SORT_ASC], |
217
|
|
|
'desc' => [$name => SORT_DESC], |
218
|
|
|
], $attribute); |
219
|
|
|
} else { |
220
|
24 |
|
$attributes[$name] = $attribute; |
221
|
|
|
} |
222
|
|
|
} |
223
|
97 |
|
$this->attributes = $attributes; |
224
|
97 |
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* Returns the columns and their corresponding sort directions. |
228
|
|
|
* @param bool $recalculate whether to recalculate the sort directions |
229
|
|
|
* @return array the columns (keys) and their corresponding sort directions (values). |
230
|
|
|
* This can be passed to [[\yii\db\Query::orderBy()]] to construct a DB query. |
231
|
|
|
*/ |
232
|
75 |
|
public function getOrders($recalculate = false) |
233
|
|
|
{ |
234
|
75 |
|
$attributeOrders = $this->getAttributeOrders($recalculate); |
235
|
75 |
|
$orders = []; |
236
|
75 |
|
foreach ($attributeOrders as $attribute => $direction) { |
237
|
17 |
|
$definition = $this->attributes[$attribute]; |
238
|
17 |
|
$columns = $definition[$direction === SORT_ASC ? 'asc' : 'desc']; |
239
|
17 |
|
if (is_array($columns) || $columns instanceof \Traversable) { |
240
|
16 |
|
foreach ($columns as $name => $dir) { |
241
|
16 |
|
$orders[$name] = $dir; |
242
|
|
|
} |
243
|
|
|
} else { |
244
|
1 |
|
$orders[] = $columns; |
245
|
|
|
} |
246
|
|
|
} |
247
|
|
|
|
248
|
75 |
|
return $orders; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* @var array the currently requested sort order as computed by [[getAttributeOrders]]. |
253
|
|
|
*/ |
254
|
|
|
private $_attributeOrders; |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* Returns the currently requested sort information. |
258
|
|
|
* @param bool $recalculate whether to recalculate the sort directions |
259
|
|
|
* @return array sort directions indexed by attribute names. |
260
|
|
|
* Sort direction can be either `SORT_ASC` for ascending order or |
261
|
|
|
* `SORT_DESC` for descending order. |
262
|
|
|
*/ |
263
|
97 |
|
public function getAttributeOrders($recalculate = false) |
264
|
|
|
{ |
265
|
97 |
|
if ($this->_attributeOrders === null || $recalculate) { |
266
|
96 |
|
$this->_attributeOrders = []; |
267
|
96 |
|
if (($params = $this->params) === null) { |
268
|
69 |
|
$request = Yii::$app->getRequest(); |
269
|
69 |
|
$params = $request instanceof Request ? $request->getQueryParams() : []; |
270
|
|
|
} |
271
|
96 |
|
if (isset($params[$this->sortParam])) { |
272
|
26 |
|
foreach ($this->parseSortParam($params[$this->sortParam]) as $attribute) { |
273
|
26 |
|
$descending = false; |
274
|
26 |
|
if (strncmp($attribute, '-', 1) === 0) { |
275
|
21 |
|
$descending = true; |
276
|
21 |
|
$attribute = substr($attribute, 1); |
277
|
|
|
} |
278
|
|
|
|
279
|
26 |
|
if (isset($this->attributes[$attribute])) { |
280
|
21 |
|
$this->_attributeOrders[$attribute] = $descending ? SORT_DESC : SORT_ASC; |
281
|
21 |
|
if (!$this->enableMultiSort) { |
282
|
15 |
|
return $this->_attributeOrders; |
283
|
|
|
} |
284
|
|
|
} |
285
|
|
|
} |
286
|
|
|
|
287
|
13 |
|
return $this->_attributeOrders; |
288
|
|
|
} |
289
|
70 |
|
if (empty($this->_attributeOrders) && is_array($this->defaultOrder)) { |
290
|
9 |
|
$this->_attributeOrders = $this->defaultOrder; |
291
|
|
|
} |
292
|
|
|
} |
293
|
|
|
|
294
|
82 |
|
return $this->_attributeOrders; |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* Parses the value of [[sortParam]] into an array of sort attributes. |
299
|
|
|
* |
300
|
|
|
* The format must be the attribute name only for ascending |
301
|
|
|
* or the attribute name prefixed with `-` for descending. |
302
|
|
|
* |
303
|
|
|
* For example the following return value will result in ascending sort by |
304
|
|
|
* `category` and descending sort by `created_at`: |
305
|
|
|
* |
306
|
|
|
* ```php |
307
|
|
|
* [ |
308
|
|
|
* 'category', |
309
|
|
|
* '-created_at' |
310
|
|
|
* ] |
311
|
|
|
* ``` |
312
|
|
|
* |
313
|
|
|
* @param string $param the value of the [[sortParam]]. |
314
|
|
|
* @return array the valid sort attributes. |
315
|
|
|
* @since 2.0.12 |
316
|
|
|
* @see separator for the attribute name separator. |
317
|
|
|
* @see sortParam |
318
|
|
|
*/ |
319
|
25 |
|
protected function parseSortParam($param) |
320
|
|
|
{ |
321
|
25 |
|
return is_scalar($param) ? explode($this->separator, $param) : []; |
|
|
|
|
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* Sets up the currently sort information. |
326
|
|
|
* @param array|null $attributeOrders sort directions indexed by attribute names. |
327
|
|
|
* Sort direction can be either `SORT_ASC` for ascending order or |
328
|
|
|
* `SORT_DESC` for descending order. |
329
|
|
|
* @param bool $validate whether to validate given attribute orders against [[attributes]] and [[enableMultiSort]]. |
330
|
|
|
* If validation is enabled incorrect entries will be removed. |
331
|
|
|
* @since 2.0.10 |
332
|
|
|
*/ |
333
|
1 |
|
public function setAttributeOrders($attributeOrders, $validate = true) |
334
|
|
|
{ |
335
|
1 |
|
if ($attributeOrders === null || !$validate) { |
336
|
1 |
|
$this->_attributeOrders = $attributeOrders; |
337
|
|
|
} else { |
338
|
1 |
|
$this->_attributeOrders = []; |
339
|
1 |
|
foreach ($attributeOrders as $attribute => $order) { |
340
|
1 |
|
if (isset($this->attributes[$attribute])) { |
341
|
1 |
|
$this->_attributeOrders[$attribute] = $order; |
342
|
1 |
|
if (!$this->enableMultiSort) { |
343
|
1 |
|
break; |
344
|
|
|
} |
345
|
|
|
} |
346
|
|
|
} |
347
|
|
|
} |
348
|
1 |
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Returns the sort direction of the specified attribute in the current request. |
352
|
|
|
* @param string $attribute the attribute name |
353
|
|
|
* @return int|null Sort direction of the attribute. Can be either `SORT_ASC` |
354
|
|
|
* for ascending order or `SORT_DESC` for descending order. Null is returned |
355
|
|
|
* if the attribute is invalid or does not need to be sorted. |
356
|
|
|
*/ |
357
|
19 |
|
public function getAttributeOrder($attribute) |
358
|
|
|
{ |
359
|
19 |
|
$orders = $this->getAttributeOrders(); |
360
|
|
|
|
361
|
19 |
|
return isset($orders[$attribute]) ? $orders[$attribute] : null; |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
/** |
365
|
|
|
* Generates a hyperlink that links to the sort action to sort by the specified attribute. |
366
|
|
|
* Based on the sort direction, the CSS class of the generated hyperlink will be appended |
367
|
|
|
* with "asc" or "desc". |
368
|
|
|
* @param string $attribute the attribute name by which the data should be sorted by. |
369
|
|
|
* @param array $options additional HTML attributes for the hyperlink tag. |
370
|
|
|
* There is one special attribute `label` which will be used as the label of the hyperlink. |
371
|
|
|
* If this is not set, the label defined in [[attributes]] will be used. |
372
|
|
|
* If no label is defined, it will be retrieved from the instance of [[modelClass]] (if [[modelClass]] is not null) |
373
|
|
|
* or generated from attribute name using [[\yii\helpers\Inflector::camel2words()]]. |
374
|
|
|
* Note that it will not be HTML-encoded. |
375
|
|
|
* @return string the generated hyperlink |
376
|
|
|
* @throws InvalidConfigException if the attribute is unknown |
377
|
|
|
*/ |
378
|
17 |
|
public function link($attribute, $options = []) |
379
|
|
|
{ |
380
|
17 |
|
if (($direction = $this->getAttributeOrder($attribute)) !== null) { |
381
|
8 |
|
$class = $direction === SORT_DESC ? 'desc' : 'asc'; |
382
|
8 |
|
if (isset($options['class'])) { |
383
|
|
|
$options['class'] .= ' ' . $class; |
384
|
|
|
} else { |
385
|
8 |
|
$options['class'] = $class; |
386
|
|
|
} |
387
|
|
|
} |
388
|
|
|
|
389
|
17 |
|
$url = $this->createUrl($attribute); |
390
|
17 |
|
$options['data-sort'] = $this->createSortParam($attribute); |
391
|
|
|
|
392
|
17 |
|
if (isset($options['label'])) { |
393
|
1 |
|
$label = $options['label']; |
394
|
1 |
|
unset($options['label']); |
395
|
|
|
} else { |
396
|
16 |
|
if (isset($this->attributes[$attribute]['label'])) { |
397
|
|
|
$label = $this->attributes[$attribute]['label']; |
398
|
16 |
|
} elseif ($this->modelClass !== null) { |
399
|
2 |
|
$modelClass = $this->modelClass; |
400
|
|
|
/** @var \yii\base\Model $model */ |
401
|
2 |
|
$model = $modelClass::instance(); |
402
|
2 |
|
$label = $model->getAttributeLabel($attribute); |
403
|
|
|
} else { |
404
|
14 |
|
$label = Inflector::camel2words($attribute); |
405
|
|
|
} |
406
|
|
|
} |
407
|
|
|
|
408
|
17 |
|
return Html::a($label, $url, $options); |
409
|
|
|
} |
410
|
|
|
|
411
|
|
|
/** |
412
|
|
|
* Creates a URL for sorting the data by the specified attribute. |
413
|
|
|
* This method will consider the current sorting status given by [[attributeOrders]]. |
414
|
|
|
* For example, if the current page already sorts the data by the specified attribute in ascending order, |
415
|
|
|
* then the URL created will lead to a page that sorts the data by the specified attribute in descending order. |
416
|
|
|
* @param string $attribute the attribute name |
417
|
|
|
* @param bool $absolute whether to create an absolute URL. Defaults to `false`. |
418
|
|
|
* @return string the URL for sorting. False if the attribute is invalid. |
419
|
|
|
* @throws InvalidConfigException if the attribute is unknown |
420
|
|
|
* @see attributeOrders |
421
|
|
|
* @see params |
422
|
|
|
*/ |
423
|
18 |
|
public function createUrl($attribute, $absolute = false) |
424
|
|
|
{ |
425
|
18 |
|
if (($params = $this->params) === null) { |
426
|
10 |
|
$request = Yii::$app->getRequest(); |
427
|
10 |
|
$params = $request instanceof Request ? $request->getQueryParams() : []; |
428
|
|
|
} |
429
|
18 |
|
$params[$this->sortParam] = $this->createSortParam($attribute); |
430
|
18 |
|
$params[0] = $this->route === null ? Yii::$app->controller->getRoute() : $this->route; |
431
|
18 |
|
$urlManager = $this->urlManager === null ? Yii::$app->getUrlManager() : $this->urlManager; |
432
|
18 |
|
if ($absolute) { |
433
|
|
|
return $urlManager->createAbsoluteUrl($params); |
434
|
|
|
} |
435
|
|
|
|
436
|
18 |
|
return $urlManager->createUrl($params); |
437
|
|
|
} |
438
|
|
|
|
439
|
|
|
/** |
440
|
|
|
* Creates the sort variable for the specified attribute. |
441
|
|
|
* The newly created sort variable can be used to create a URL that will lead to |
442
|
|
|
* sorting by the specified attribute. |
443
|
|
|
* @param string $attribute the attribute name |
444
|
|
|
* @return string the value of the sort variable |
445
|
|
|
* @throws InvalidConfigException if the specified attribute is not defined in [[attributes]] |
446
|
|
|
*/ |
447
|
19 |
|
public function createSortParam($attribute) |
448
|
|
|
{ |
449
|
19 |
|
if (!isset($this->attributes[$attribute])) { |
450
|
|
|
throw new InvalidConfigException("Unknown attribute: $attribute"); |
451
|
|
|
} |
452
|
19 |
|
$definition = $this->attributes[$attribute]; |
453
|
19 |
|
$directions = $this->getAttributeOrders(); |
454
|
19 |
|
if (isset($directions[$attribute])) { |
455
|
10 |
|
if ($this->enableMultiSort) { |
456
|
6 |
|
if ($directions[$attribute] === SORT_ASC) { |
457
|
5 |
|
$direction = SORT_DESC; |
458
|
|
|
} else { |
459
|
6 |
|
$direction = null; |
460
|
|
|
} |
461
|
|
|
} else { |
462
|
4 |
|
$direction = $directions[$attribute] === SORT_DESC ? SORT_ASC : SORT_DESC; |
463
|
|
|
} |
464
|
|
|
|
465
|
10 |
|
unset($directions[$attribute]); |
466
|
|
|
} else { |
467
|
10 |
|
$direction = isset($definition['default']) ? $definition['default'] : SORT_ASC; |
468
|
|
|
} |
469
|
|
|
|
470
|
19 |
|
if ($this->enableMultiSort) { |
471
|
10 |
|
if ($direction !== null) { |
472
|
10 |
|
$directions = array_merge([$attribute => $direction], $directions); |
473
|
|
|
} |
474
|
|
|
} else { |
475
|
9 |
|
$directions = [$attribute => $direction]; |
476
|
|
|
} |
477
|
|
|
|
478
|
19 |
|
$sorts = []; |
479
|
19 |
|
foreach ($directions as $attribute => $direction) { |
|
|
|
|
480
|
18 |
|
$sorts[] = $direction === SORT_DESC ? '-' . $attribute : $attribute; |
481
|
|
|
} |
482
|
|
|
|
483
|
19 |
|
return implode($this->separator, $sorts); |
484
|
|
|
} |
485
|
|
|
|
486
|
|
|
/** |
487
|
|
|
* Returns a value indicating whether the sort definition supports sorting by the named attribute. |
488
|
|
|
* @param string $name the attribute name |
489
|
|
|
* @return bool whether the sort definition supports sorting by the named attribute. |
490
|
|
|
*/ |
491
|
1 |
|
public function hasAttribute($name) |
492
|
|
|
{ |
493
|
1 |
|
return isset($this->attributes[$name]); |
494
|
|
|
} |
495
|
|
|
} |
496
|
|
|
|