1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Spatie\EloquentSortable; |
4
|
|
|
|
5
|
|
|
trait SortableTrait |
6
|
|
|
{ |
7
|
|
|
/** |
8
|
|
|
* Modify the order column value. |
9
|
|
|
*/ |
10
|
|
|
public function setHighestOrderNumber() |
11
|
|
|
{ |
12
|
|
|
$orderColumnName = $this->determineOrderColumnName(); |
13
|
|
|
$this->$orderColumnName = $this->getHighestOrderNumber() + 1; |
14
|
|
|
} |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Determine the order value for the new record. |
18
|
|
|
* |
19
|
|
|
* @return int |
20
|
|
|
*/ |
21
|
|
|
public function getHighestOrderNumber() |
22
|
|
|
{ |
23
|
|
|
return ((int) static::max($this->determineOrderColumnName())); |
24
|
|
|
} |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Let's be nice and provide an ordered scope. |
28
|
|
|
* |
29
|
|
|
* @param \Illuminate\Database\Eloquent\Builder $query |
30
|
|
|
* |
31
|
|
|
* @return \Illuminate\Database\Query\Builder |
32
|
|
|
*/ |
33
|
|
|
public function scopeOrdered(\Illuminate\Database\Eloquent\Builder $query) |
34
|
|
|
{ |
35
|
|
|
return $query->orderBy($this->determineOrderColumnName()); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* This function reorders the records: the record with the first id in the array |
40
|
|
|
* will get order 1, the record with the second it will get order 2, ... |
41
|
|
|
* |
42
|
|
|
* A starting order number can be optionally supplied (defaults to 1). |
43
|
|
|
* |
44
|
|
|
* @param array $ids |
45
|
|
|
* @param int $startOrder |
46
|
|
|
* |
47
|
|
|
* @throws SortableException |
48
|
|
|
*/ |
49
|
|
|
public static function setNewOrder($ids, $startOrder = 1) |
50
|
|
|
{ |
51
|
|
|
if (!is_array($ids)) { |
52
|
|
|
throw new SortableException('You must pass an array to setNewOrder'); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
foreach ($ids as $id) { |
56
|
|
|
$model = static::find($id); |
57
|
|
|
$orderColumnName = $model->determineOrderColumnName(); |
58
|
|
|
$model->$orderColumnName = $startOrder++; |
59
|
|
|
$model->save(); |
60
|
|
|
} |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Determine the column name of the order column. |
65
|
|
|
* |
66
|
|
|
* @return string |
67
|
|
|
*/ |
68
|
|
|
public function determineOrderColumnName() |
69
|
|
|
{ |
70
|
|
|
if ( |
71
|
|
|
isset($this->sortable['order_column_name']) && |
72
|
|
|
!empty($this->sortable['order_column_name']) |
73
|
|
|
) { |
74
|
|
|
return $this->sortable['order_column_name']; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
return 'order_column'; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Determine if the order column should be set when saving a new model instance. |
82
|
|
|
* |
83
|
|
|
* @return bool |
84
|
|
|
*/ |
85
|
|
|
public function shouldSortWhenCreating() |
86
|
|
|
{ |
87
|
|
|
if (!isset($this->sortable)) { |
88
|
|
|
return true; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
if (!isset($this->sortable['sort_when_creating'])) { |
92
|
|
|
return true; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
return $this->sortable['sort_when_creating']; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* Swaps the order of this model with the model 'below' this model |
100
|
|
|
* |
101
|
|
|
* @return $this |
102
|
|
|
* |
103
|
|
|
* @throws SortableException |
104
|
|
|
*/ |
105
|
|
View Code Duplication |
public function moveOrderDown() |
|
|
|
|
106
|
|
|
{ |
107
|
|
|
$orderColumnName = $this->determineOrderColumnName(); |
108
|
|
|
|
109
|
|
|
$swapWithModel = static::limit(1) |
110
|
|
|
->ordered() |
111
|
|
|
->where($orderColumnName, '>', $this->$orderColumnName) |
112
|
|
|
->first(); |
113
|
|
|
|
114
|
|
|
if (!$swapWithModel) { |
115
|
|
|
throw new SortableException('The model you try to move down has already the lowest order'); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
return $this->swapOrderWithModel($swapWithModel); |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* Swaps the order of this model with the model 'above' this model |
123
|
|
|
* |
124
|
|
|
* @return $this |
125
|
|
|
* |
126
|
|
|
* @throws SortableException |
127
|
|
|
*/ |
128
|
|
View Code Duplication |
public function moveOrderUp() |
|
|
|
|
129
|
|
|
{ |
130
|
|
|
$orderColumnName = $this->determineOrderColumnName(); |
131
|
|
|
|
132
|
|
|
$swapWithModel = static::limit(1) |
133
|
|
|
->ordered() |
134
|
|
|
->where($orderColumnName, '<', $this->$orderColumnName) |
135
|
|
|
->first(); |
136
|
|
|
|
137
|
|
|
if (!$swapWithModel) { |
138
|
|
|
throw new SortableException('The model you try to move up has already the highest order'); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
return $this->swapOrderWithModel($swapWithModel); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Swap the order of this model with the order of another model |
146
|
|
|
* |
147
|
|
|
* @param \Spatie\EloquentSortable\Sortable $model |
148
|
|
|
* |
149
|
|
|
* @return $this |
150
|
|
|
*/ |
151
|
|
|
protected function swapOrderWithModel(Sortable $model) |
152
|
|
|
{ |
153
|
|
|
$thisModelColumnName = $this->determineOrderColumnName(); |
154
|
|
|
$otherModelColumnName = $model->determineOrderColumnName(); |
155
|
|
|
|
156
|
|
|
$currentOtherModelOrder = $model->$otherModelColumnName; |
157
|
|
|
|
158
|
|
|
$model->$otherModelColumnName = $this->$thisModelColumnName; |
159
|
|
|
$model->save(); |
160
|
|
|
|
161
|
|
|
$this->$thisModelColumnName = $currentOtherModelOrder; |
162
|
|
|
$this->save(); |
|
|
|
|
163
|
|
|
|
164
|
|
|
return $this; |
165
|
|
|
} |
166
|
|
|
} |
167
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.