1: <?php
2:
3: namespace Baril\Orderly;
4:
5: use Illuminate\Database\Eloquent\Collection as EloquentCollection;
6: use Illuminate\Support\Arr;
7:
8: class OrderableCollection extends EloquentCollection
9: {
10: public function saveOrder()
11: {
12: if ($this->isEmpty()) {
13: return $this;
14: }
15:
16: $instance = $this->first();
17: $orderColumn = $instance->getOrderColumn();
18: $groupColumn = $instance->getGroupColumn();
19:
20: // Check that all items are in the same group:
21: if ($groupColumn) {
22: foreach ((array) $groupColumn as $column) {
23: if ($this->pluck($column)->unique()->count() > 1) {
24: throw new GroupException('All models must be in same group!');
25: }
26: }
27: }
28:
29: // Get current positions:
30: $positions = $this->pluck($orderColumn)->sort()->all();
31: reset($positions);
32:
33: // Save the new order:
34: $instance->getConnection()->transaction(function () use ($orderColumn, &$positions) {
35: $this->values()->each(function ($model) use ($orderColumn, &$positions) {
36: // Update the order field without triggering the listeners:
37: $model->newQuery()->whereKey($model->getKey())->update([$orderColumn => current($positions)]);
38: $model->setAttribute($orderColumn, current($positions));
39: next($positions);
40: });
41: });
42:
43: return $this;
44: }
45:
46: public function setOrder($ids)
47: {
48: $count = $this->count();
49: $isList = Arr::isList($this->keys()->all());
50:
51: return $this->sortBy(function ($item) use ($ids, $count) {
52: $index = array_search($item->getKey(), $ids);
53: return ($index === false) ? $count + $item->getPosition() : $index;
54: })->saveOrder()->when($isList, function ($orderedCollection) {
55: return $orderedCollection->values();
56: });
57: }
58: }
59: