Completed
Pull Request — master (#16)
by Timo
06:00
created

Sorter::addField()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 1
1
<?php
2
3
namespace hamburgscleanest\DataTables\Models\DataComponents;
4
5
use hamburgscleanest\DataTables\Facades\SessionHelper;
6
use hamburgscleanest\DataTables\Models\Column;
7
use hamburgscleanest\DataTables\Models\DataComponent;
8
use Illuminate\Database\Eloquent\Builder;
9
use Illuminate\Support\Facades\DB;
10
11
/**
12
 * Class Sorter
13
 * @package hamburgscleanest\DataTables\Models\DataComponents
14
 */
15
class Sorter extends DataComponent {
16
17
    const SORTING_SEPARATOR = '~';
18
    const COLUMN_SEPARATOR  = '.';
19
20
    /** @var array */
21
    private $_sortFields = [];
22
23
    /**
24
     * Sorter constructor.
25
     * @param null|array $fields
26
     * @param bool $remember
27
     */
28 10
    public function __construct(array $fields = null, bool $remember = false)
29
    {
30 10
        $this->_rememberKey = 'sort';
31 10
        $this->_rememberState = $remember;
32
33 10
        if ($fields !== null)
34
        {
35 7
            foreach ($fields as $fieldName => $direction)
36
            {
37 7
                if (\is_int($fieldName))
38
                {
39 4
                    $fieldName = $direction;
40 4
                    $direction = 'asc';
41
                }
42
43 7
                $this->_sortFields[$fieldName] = \mb_strtolower($direction);
44
            }
45
        }
46 10
    }
47
48
    /**
49
     * Sort by this column.
50
     *
51
     * @param string $field
52
     * @param string $direction
53
     *
54
     * @return Sorter
55
     */
56 1
    public function addField(string $field, string $direction = 'asc') : Sorter
57
    {
58 1
        $this->_sortFields[$field] = \mb_strtolower($direction);
59
60 1
        return $this;
61
    }
62
63
    /**
64
     * @return string
65
     */
66 1
    public function render() : string
67
    {
68 1
        return implode(', ', \array_keys($this->_sortFields));
69
    }
70
71
    /**
72
     * @return Builder
73
     */
74 8
    protected function _shapeData() : Builder
75
    {
76 8
        if (\count($this->_sortFields) > 0)
77
        {
78 6
            foreach ($this->_sortFields as $fieldName => $direction)
79
            {
80 6
                if ($direction === 'none')
81
                {
82 1
                    $this->removeField($fieldName);
83 1
                    continue;
84
                }
85
86 5
                $this->_sortField($fieldName, $direction);
87
            }
88
        }
89
90 8
        return $this->_dataTable->query();
91
    }
92
93
    /**
94
     * Stop sorting by this column
95
     *
96
     * @param string $field
97
     *
98
     * @return Sorter
99
     */
100 1
    public function removeField(string $field) : Sorter
101
    {
102 1
        if (isset($this->_sortFields[$field]))
103
        {
104 1
            unset($this->_sortFields[$field]);
105
        }
106
107 1
        return $this;
108
    }
109
110
    /**
111
     * @param string $fieldName
112
     * @param string $direction
113
     */
114
    private function _sortField(string $fieldName, string $direction) : void
115
    {
116
        /** @var Column $column */
117 5
        $column = \array_first($this->_dataTable->getColumns(), function($index, $column) use ($fieldName) {
118
            /** @var Column $column */
119 5
            return $column->getKey() === $fieldName;
120 5
        });
121
122 5
        if ($column !== null)
123
        {
124 4
            $this->_dataTable->query()->orderBy(DB::raw($column->getAttributeName()), $direction);
125 4
            $this->_addGroupingForAggregate($column);
126
        }
127 5
    }
128
129
    /**
130
     * @param Column $column
131
     */
132 4
    private function _addGroupingForAggregate(Column $column) : void
133
    {
134 4
        $relation = $column->getRelation();
135 4
        if ($relation === null || $relation->aggregate === 'first')
136
        {
137 4
            return;
138
        }
139
140
        $this->_dataTable->query()->groupBy($relation->name . '.' . $column->getName());
141
    }
142
143 1
    protected function _readFromSession() : void
144
    {
145 1
        $this->_sortFields = (array) SessionHelper::getState($this->_rememberKey, []);
146 1
    }
147
148 1
    protected function _storeInSession() : void
149
    {
150 1
        SessionHelper::saveState($this->_rememberKey, $this->_sortFields);
151 1
    }
152
153 9
    protected function _afterInit() : void
154
    {
155
        /** @var string $sortFields */
156 9
        $sortFields = \request()->get('sort');
157 9
        if (empty($sortFields))
158
        {
159 7
            return;
160
        }
161
162 2
        $this->_initFields($sortFields);
163 2
    }
164
165
    /**
166
     * @param string $fields
167
     */
168 2
    private function _initFields(string $fields) : void
169
    {
170 2
        $this->_sortFields = [];
171 2
        foreach (\explode(self::COLUMN_SEPARATOR, $fields) as $field)
172
        {
173 2
            $sortParts = \explode(self::SORTING_SEPARATOR, $field);
174 2
            if (\count($sortParts) === 1)
175
            {
176 1
                $sortParts[1] = 'asc';
177
            }
178
179 2
            if ($sortParts[1] === 'none')
180
            {
181 1
                SessionHelper::removeState($this->_rememberKey . '.' . $sortParts[0]);
182
            }
183
184 2
            $this->_sortFields[$sortParts[0]] = $sortParts[1];
185
        }
186
    }
187
}