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