Completed
Push — master ( 7133d1...bb16e7 )
by Arjay
01:47
created

CollectionEngine::make()   A

Complexity

Conditions 3
Paths 11

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 13
nc 11
nop 1
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Yajra\Datatables\Engines;
4
5
use Illuminate\Contracts\Support\Arrayable;
6
use Illuminate\Support\Arr;
7
use Illuminate\Support\Collection;
8
use Illuminate\Support\Str;
9
10
/**
11
 * Class CollectionEngine.
12
 *
13
 * @package Yajra\Datatables\Engines
14
 * @author  Arjay Angeles <[email protected]>
15
 */
16
class CollectionEngine extends BaseEngine
17
{
18
    /**
19
     * Collection object
20
     *
21
     * @var \Illuminate\Support\Collection
22
     */
23
    public $collection;
24
25
    /**
26
     * Collection object
27
     *
28
     * @var \Illuminate\Support\Collection
29
     */
30
    public $original;
31
32
    /**
33
     * CollectionEngine constructor.
34
     *
35
     * @param \Illuminate\Support\Collection $collection
36
     */
37
    public function __construct(Collection $collection)
38
    {
39
        $this->request    = resolve('datatables.request');
40
        $this->config     = resolve('datatables.config');
41
        $this->collection = $collection;
42
        $this->original   = $collection;
43
        $this->columns    = array_keys($this->serialize($collection->first()));
44
    }
45
46
    /**
47
     * Serialize collection
48
     *
49
     * @param  mixed $collection
50
     * @return mixed|null
51
     */
52
    protected function serialize($collection)
53
    {
54
        return $collection instanceof Arrayable ? $collection->toArray() : (array) $collection;
55
    }
56
57
    /**
58
     * Set auto filter off and run your own filter.
59
     * Overrides global search.
60
     *
61
     * @param callable $callback
62
     * @param bool     $globalSearch
63
     * @return $this
64
     */
65
    public function filter(callable $callback, $globalSearch = false)
66
    {
67
        $this->overrideGlobalSearch($callback, $this, $globalSearch);
68
69
        return $this;
70
    }
71
72
    /**
73
     * Append debug parameters on output.
74
     *
75
     * @param  array $output
76
     * @return array
77
     */
78
    public function showDebugger(array $output)
79
    {
80
        $output["input"] = $this->request->all();
81
82
        return $output;
83
    }
84
85
    /**
86
     * Count results.
87
     *
88
     * @return integer
89
     */
90
    public function count()
91
    {
92
        return $this->collection->count() > $this->totalRecords ? $this->totalRecords : $this->collection->count();
93
    }
94
95
    /**
96
     * Perform column search.
97
     *
98
     * @return void
99
     */
100
    public function columnSearch()
101
    {
102
        $columns = $this->request->get('columns');
103
        for ($i = 0, $c = count($columns); $i < $c; $i++) {
104
            if ($this->request->isColumnSearchable($i)) {
105
                $this->isFilterApplied = true;
106
                $regex                 = $this->request->isRegex($i);
107
108
                $column  = $this->getColumnName($i);
109
                $keyword = $this->request->columnKeyword($i);
110
111
                $this->collection = $this->collection->filter(
112
                    function ($row) use ($column, $keyword, $regex) {
113
                        $data = $this->serialize($row);
114
115
                        $value = Arr::get($data, $column);
116
117
                        if ($this->config->isCaseInsensitive()) {
118 View Code Duplication
                            if ($regex) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
119
                                return preg_match('/' . $keyword . '/i', $value) == 1;
120
                            } else {
121
                                return strpos(Str::lower($value), Str::lower($keyword)) !== false;
122
                            }
123 View Code Duplication
                        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
124
                            if ($regex) {
125
                                return preg_match('/' . $keyword . '/', $value) == 1;
126
                            } else {
127
                                return strpos($value, $keyword) !== false;
128
                            }
129
                        }
130
                    }
131
                );
132
            }
133
        }
134
    }
135
136
    /**
137
     * Perform pagination.
138
     *
139
     * @return void
140
     */
141
    public function paging()
142
    {
143
        $this->collection = $this->collection->slice(
144
            $this->request->input('start'),
145
            (int) $this->request->input('length') > 0 ? $this->request->input('length') : 10
146
        );
147
    }
148
149
    /**
150
     * Get results.
151
     *
152
     * @return mixed
153
     */
154
    public function results()
155
    {
156
        return $this->collection->all();
157
    }
158
159
    /**
160
     * Organizes works.
161
     *
162
     * @param bool $mDataSupport
163
     * @return \Illuminate\Http\JsonResponse
164
     */
165
    public function make($mDataSupport = false)
166
    {
167
        try {
168
            $this->totalRecords = $this->totalCount();
169
170
            if ($this->totalRecords) {
171
                $data   = $this->getProcessedData($mDataSupport);
172
                $output = $this->transform($data);
173
174
                $this->collection = collect($output);
175
                $this->ordering();
176
                $this->filterRecords();
177
                $this->paginate();
178
            }
179
180
            return $this->render($this->collection->values()->all());
181
        } catch (\Exception $exception) {
182
            return $this->errorResponse($exception);
183
        }
184
    }
185
186
    /**
187
     * Count total items.
188
     *
189
     * @return integer
190
     */
191
    public function totalCount()
192
    {
193
        return $this->totalRecords ? $this->totalRecords : $this->collection->count();
194
    }
195
196
    /**
197
     * Perform global search for the given keyword.
198
     *
199
     * @param string $keyword
200
     */
201
    protected function globalSearch($keyword)
202
    {
203
        if ($this->config->isCaseInsensitive()) {
204
            $keyword = Str::lower($keyword);
205
        }
206
207
        $columns          = $this->request->columns();
208
        $this->collection = $this->collection->filter(
209
            function ($row) use ($columns, $keyword) {
210
                $data                  = $this->serialize($row);
211
                $this->isFilterApplied = true;
212
213
                foreach ($this->request->searchableColumnIndex() as $index) {
214
                    $column = $this->getColumnName($index);
215
                    if (!$value = Arr::get($data, $column)) {
216
                        continue;
217
                    }
218
219
                    if (is_array($value)) {
220
                        continue;
221
                    }
222
223
                    if ($this->config->isCaseInsensitive()) {
224
                        $value = Str::lower($value);
225
                    }
226
227
                    if (Str::contains($value, $keyword)) {
228
                        return true;
229
                    }
230
                }
231
232
                return false;
233
            }
234
        );
235
    }
236
237
    /**
238
     * Perform default query orderBy clause.
239
     */
240
    protected function defaultOrdering()
241
    {
242
        foreach ($this->request->orderableColumns() as $orderable) {
243
            $column = $this->getColumnName($orderable['column']);
244
245
            $options = SORT_NATURAL;
246
            if ($this->config->isCaseInsensitive()) {
247
                $options = SORT_NATURAL | SORT_FLAG_CASE;
248
            }
249
250
            $this->collection = $this->collection->sortBy(function ($row) use ($column) {
251
                $data = $this->serialize($row);
252
253
                return Arr::get($data, $column);
254
            }, $options);
255
256
            if ($orderable['direction'] == 'desc') {
257
                $this->collection = $this->collection->reverse();
258
            }
259
        }
260
    }
261
262
    /**
263
     * Resolve callback parameter instance.
264
     *
265
     * @return mixed
266
     */
267
    protected function resolveCallbackParameter()
268
    {
269
        return $this;
270
    }
271
}
272