Completed
Push — master ( 72d72a...bb8091 )
by Yaro
06:09
created

CRUD::baseUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
ccs 3
cts 3
cp 1
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Yaro\Jarboe\Table;
4
5
use Yaro\Jarboe\Table\Actions\ActionsContainer;
6
use Yaro\Jarboe\Table\Fields\AbstractField;
7
use Yaro\Jarboe\Table\Fields\Text;
8
use Yaro\Jarboe\Table\Repositories\ModelRepository;
9
use Yaro\Jarboe\Table\Repositories\PreferencesRepository;
10
use Yaro\Jarboe\Table\Toolbar\AbstractTool;
11
use Yaro\Jarboe\Table\Toolbar\Interfaces\ToolInterface;
12
13
class CRUD
14
{
15
    const BASE_URL_DELIMITER = '/~/';
16
17
    private $fields = [];
18
    private $actions;
19
    private $model = '';
20
    private $repo;
21
    private $preferences;
22
    private $tableIdentifier;
23
    private $rawPerPage;
24
    private $columns = [];
25
    private $formClass = 'col-sm-12 col-md-12 col-lg-12';
26
    private $toolbar = [];
27
    private $locales = [];
28
    private $batchCheckboxesEnabled = false;
29
    private $sortableWeightField = null;
30
    private $softDeleteEnabled = false;
31
32 18
    public function __construct(ModelRepository $repo, PreferencesRepository $preferences, ActionsContainer $actions)
33
    {
34 18
        $this->repo = $repo;
35 18
        $this->preferences = $preferences;
36 18
        $this->actions = $actions;
37 18
    }
38
39 17
    public function formClass(string $class = null)
40
    {
41 17
        if (!is_null($class)) {
42 17
            $this->formClass = $class;
43
        }
44
45 17
        return $this->formClass;
46
    }
47
48
    public function getRawPerPage()
49
    {
50
        return $this->rawPerPage;
51
    }
52
53
    /**
54
     * @param string|AbstractField $column
55
     */
56
    public function addColumn($column)
57
    {
58
        $this->columns[] = $column;
59
    }
60
61 13
    public function getColumns()
62
    {
63 13
        return $this->columns;
64
    }
65
66
    /**
67
     * Get columns as field objects, or fields if there are no columns.
68
     *
69
     * @return array
70
     */
71
    public function getColumnsAsFields()
72
    {
73
        $columns = [];
74
        foreach ($this->getColumns() as $column) {
75
            if (!is_object($column)) {
76
                $column = $this->getFieldByName($column) ?: $this->makeDefaultColumnField($column);
77
            }
78
79
            if ($column) {
80
                $columns[] = $column;
81
            }
82
        }
83
84
        return $columns ?: $this->getFields();
85
    }
86
87
    /**
88
     * Get list of columns that initialized as field object.
89
     *
90
     * @return array
91
     */
92 13
    public function getColumnsWithoutRelatedField()
93
    {
94 13
        $columns = [];
95 13
        foreach ($this->getColumns() as $column) {
96
            if (is_object($column)) {
97
                $columns[] = $column;
98
            }
99
        }
100
101 13
        return $columns;
102
    }
103
104 13
    public function getAllFieldObjects()
105
    {
106 13
        $fieldsAndColumns = array_merge(
107 13
            $this->getFieldsWithoutMarkup(),
108 13
            $this->getColumnsWithoutRelatedField()
109
        );
110
111 13
        return $fieldsAndColumns;
112
    }
113
114
    /**
115
     * @param $name
116
     * @return null|AbstractField
117
     */
118 1
    public function getFieldByName($name)
119
    {
120 1
        $fields = $this->getFieldsWithoutMarkup();
121 1
        foreach ($fields as $field) {
122 1
            if ($field->name() === $name) {
123 1
                return $field;
124
            }
125
        }
126
127
        return null;
128
    }
129
130 13
    public function addField(AbstractField $field)
131
    {
132 13
        $this->fields[] = $field;
133 13
    }
134
135 13
    public function getFields()
136
    {
137 13
        return $this->fields;
138
    }
139
140 13
    public function getFieldsWithoutMarkup(): array
141
    {
142 13
        $fields = [];
143 13
        foreach ($this->getFields() as $field) {
144 13
            $this->extractField($field, $fields);
145
        }
146
147 13
        return $fields;
148
    }
149
150 13
    private function extractField(AbstractField $field, &$fields)
151
    {
152 13
        if (!$field->isMarkupRow()) {
153 13
            $fields[] = $field;
154 13
            return;
155
        }
156
157
        foreach ($field->getFields() as $field) {
158
            $this->extractField($field, $fields);
159
        }
160
    }
161
162
    public function getTabs($skipHiddenType = null)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
163
    {
164
        $tabs = [];
165
        foreach ($this->getFields() as $field) {
166
            if ($skipHiddenType && $field->hidden($skipHiddenType)) {
167
                continue;
168
            }
169
            $tabs[$field->getTab()][] = $field;
170
        }
171
172
        $this->moveDefaultTabToEnd($tabs);
173
174
        return $tabs;
175
    }
176
177
    private function moveDefaultTabToEnd(&$tabs)
178
    {
179
        $defaultTab = AbstractField::DEFAULT_TAB_IDENT;
180
        if (!array_key_exists($defaultTab, $tabs)) {
181
            return;
182
        }
183
184
        $defaultTabFields = $tabs[$defaultTab];
185
        unset($tabs[$defaultTab]);
186
        $tabs[$defaultTab] = $defaultTabFields;
187
    }
188
189 13
    public function setModel($model)
190
    {
191 13
        $this->model = $model;
192
193 13
        return $this;
194
    }
195
196 13
    public function repo()
197
    {
198 13
        $this->repo->setCrud($this);
199
200 13
        return $this->repo;
201
    }
202
203 4
    public function preferences()
204
    {
205 4
        return $this->preferences;
206
    }
207
208
    /**
209
     * @param int|array $perPage
210
     */
211
    public function paginate($perPage)
212
    {
213
        $this->rawPerPage = $perPage;
214
215
        $storedPerPage = $this->getPerPageParam();
216
        if (is_array($perPage)) {
217
            $perPage = array_shift($perPage);
218
        }
219
        if (!$storedPerPage) {
220
            $this->setPerPageParam($perPage ?: $this->repo()->perPage());
221
            $storedPerPage = $perPage;
222
        }
223
        $this->repo()->perPage($storedPerPage);
224
225
        return $this;
226
    }
227
228
    public function order(string $column, string $direction)
229
    {
230
        $this->repo()->order($column, $direction);
231
232
        return $this;
233
    }
234
235 13
    public function filter(\Closure $callback)
236
    {
237 13
        $this->repo()->filter($callback);
238
239 13
        return $this;
240
    }
241
242 13
    public function getModel()
243
    {
244 13
        return $this->model;
245
    }
246
247
    public function hasAnyFieldFilter()
248
    {
249
        foreach ($this->getColumnsAsFields() as $field) {
250
            if (!$field->hidden('list') && $field->filter()) {
251
                return true;
252
            }
253
        }
254
255
        return false;
256
    }
257
258
    public function editUrl($id)
259
    {
260
        return sprintf('%s%s%s', $this->baseUrl(), self::BASE_URL_DELIMITER, $id);
261
    }
262
263
    public function createUrl()
264
    {
265
        return sprintf('%s%screate', $this->baseUrl(), self::BASE_URL_DELIMITER);
266
    }
267
268
    public function deleteUrl($id)
269
    {
270
        return sprintf('%s%s%s/delete', $this->baseUrl(), self::BASE_URL_DELIMITER, $id);
271
    }
272
273
    public function restoreUrl($id)
274
    {
275
        return sprintf('%s%s%s/restore', $this->baseUrl(), self::BASE_URL_DELIMITER, $id);
276
    }
277
278
    public function forceDeleteUrl($id)
279
    {
280
        return sprintf('%s%s%s/force-delete', $this->baseUrl(), self::BASE_URL_DELIMITER, $id);
281
    }
282
283
    public function toolbarUrl($identifier)
284
    {
285
        return sprintf('%s%stoolbar/%s', $this->baseUrl(), self::BASE_URL_DELIMITER, $identifier);
286
    }
287
288 5
    public function listUrl()
289
    {
290 5
        return $this->baseUrl();
291
    }
292
293
    public function perPageUrl($perPage)
294
    {
295
        return sprintf('%s%sper-page/%s', $this->baseUrl(), self::BASE_URL_DELIMITER, $perPage);
296
    }
297
298
    public function searchUrl()
299
    {
300
        return sprintf('%s%ssearch', $this->baseUrl(), self::BASE_URL_DELIMITER);
301
    }
302
303
    public function relationSearchUrl()
304
    {
305
        return sprintf('%s%ssearch/relation', $this->baseUrl(), self::BASE_URL_DELIMITER);
306
    }
307
308 13
    public function inlineUrl()
309
    {
310 13
        return sprintf('%s%sinline', $this->baseUrl(), self::BASE_URL_DELIMITER);
311
    }
312
313
    public function orderUrl($column, $direction)
314
    {
315
        return sprintf('%s%sorder/%s/%s', $this->baseUrl(), self::BASE_URL_DELIMITER, $column, $direction);
316
    }
317
318
    public function reorderUrl()
319
    {
320
        return sprintf('%s%sreorder/switch', $this->baseUrl(), self::BASE_URL_DELIMITER);
321
    }
322
323
    public function reorderMoveItemUrl($id)
324
    {
325
        return sprintf('%s%sreorder/move/%s', $this->baseUrl(), self::BASE_URL_DELIMITER, $id);
326
    }
327
328 14
    public function baseUrl()
329
    {
330 14
        $chunks = explode(self::BASE_URL_DELIMITER, request()->url());
331
332 14
        return rtrim($chunks[0], '/');
333
    }
334
335
    /**
336
     * @param null $ident
337
     * @return mixed|void
338
     */
339 17
    public function tableIdentifier($ident = null)
340
    {
341 17
        if (is_null($ident)) {
342 4
            return $this->tableIdentifier;
343
        }
344
345 17
        $this->tableIdentifier = $ident;
346 17
    }
347
348 1
    public function saveSearchFilterParams(array $params)
349
    {
350 1
        $this->preferences()->saveSearchFilterParams($this->tableIdentifier(), $params);
351 1
    }
352
353 1
    public function getOrderFilterParam($column)
354
    {
355 1
        return $this->preferences()->getOrderFilterParam($this->tableIdentifier(), $column);
356
    }
357
358 1
    public function saveOrderFilterParam($column, $direction)
359
    {
360 1
        $this->preferences()->saveOrderFilterParam($this->tableIdentifier(), $column, $direction);
361 1
    }
362
363 1
    public function getPerPageParam()
364
    {
365 1
        return $this->preferences()->getPerPageParam($this->tableIdentifier());
366
    }
367
368 1
    public function setPerPageParam($perPage)
369
    {
370 1
        $this->preferences()->setPerPageParam($this->tableIdentifier(), $perPage);
371 1
    }
372
373
    public function getCurrentLocale()
374
    {
375
        return $this->preferences()->getCurrentLocale($this->tableIdentifier()) ?: key($this->getLocales());
376
    }
377
378
    public function saveCurrentLocale($locale)
379
    {
380
        $this->preferences()->saveCurrentLocale($this->tableIdentifier(), $locale);
381
    }
382
383
    /**
384
     * @param $ident
385
     * @throws \RuntimeException
386
     * @return AbstractTool
387
     */
388 2
    public function getTool($ident)
389
    {
390 2
        if (array_key_exists($ident, $this->toolbar)) {
391 2
            return $this->toolbar[$ident];
392
        }
393
394
        throw new \RuntimeException('Not allowed toolbar');
395
    }
396
397 2
    public function addTool(ToolInterface $tool)
398
    {
399 2
        $this->toolbar[$tool->identifier()] = $tool;
400 2
    }
401
402 2
    public function getTools()
403
    {
404 2
        return $this->toolbar;
405
    }
406
407
    public function getActiveHeaderToolbarTools()
408
    {
409
        $list = [];
410
        /** @var ToolInterface $tool */
411
        foreach ($this->toolbar as $tool) {
412
            if ($tool->position() == ToolInterface::POSITION_HEADER && $tool->check()) {
413
                $list[] = $tool;
414
            }
415
        }
416
417
        return $list;
418
    }
419
420
    public function getActiveBodyToolbarToolsOnTop()
421
    {
422
        return $this->getActiveBodyToolbarTools(ToolInterface::POSITION_BODY_TOP);
423
    }
424
425
    public function getActiveBodyToolbarToolsOnBottom()
426
    {
427
        return $this->getActiveBodyToolbarTools(ToolInterface::POSITION_BODY_BOTTOM);
428
    }
429
430
    public function getActiveBodyToolbarTools($position)
431
    {
432
        $list = [];
433
        /** @var ToolInterface $tool */
434
        foreach ($this->toolbar as $tool) {
435
            $isPositioned = $tool->position() == $position || $tool->position() == ToolInterface::POSITION_BODY_BOTH;
436
            if ($isPositioned && $tool->check()) {
437
                $list[] = $tool;
438
            }
439
        }
440
441
        return $list;
442
    }
443
444
    public function getTabErrorsCount($tabTitle, $errors)
445
    {
446
        $count = 0;
447
        $tabs = $this->getTabs();
448
        $fields = $tabs[$tabTitle];
449
450
        foreach ($fields as $field) {
451
            $count += count($errors->get($field->name()));
452
        }
453
454
        return $count;
455
    }
456
457
    public function locales(array $locales)
458
    {
459
        $this->normalizeLocales($locales);
460
        $this->locales = $locales;
461
462
        return $this;
463
    }
464
465
    public function getLocales()
466
    {
467
        return $this->locales;
468
    }
469
470
    // TODO: move helper to trait or smth
471
    private function isAssociativeArray(array $array)
472
    {
473
        if ($array === []) {
474
            return false;
475
        }
476
477
        return array_keys($array) !== range(0, count($array) - 1);
478
    }
479
480
    private function normalizeLocales(array &$locales)
481
    {
482
        if (!$this->isAssociativeArray($locales)) {
483
            $locales = array_combine(
484
                array_values($locales),
485
                array_values($locales)
486
            );
487
        }
488
    }
489
490 17
    public function actions()
491
    {
492 17
        return $this->actions;
493
    }
494
495 1
    public function enableBatchCheckboxes(bool $enabled = true)
496
    {
497 1
        $this->batchCheckboxesEnabled = $enabled;
498 1
    }
499
500
    public function isBatchCheckboxesEnabled()
501
    {
502
        return $this->batchCheckboxesEnabled;
503
    }
504
505
    public function enableSortableByWeight(string $field)
506
    {
507
        $this->sortableWeightField = $field;
508
    }
509
510
    public function isSortableByWeight()
511
    {
512
        return (bool) $this->getSortableWeightFieldName();
513
    }
514
515 1
    public function isSortableByWeightActive()
516
    {
517 1
        return $this->preferences()->isSortableByWeightActive($this->tableIdentifier());
518
    }
519
520
    public function getSortableWeightFieldName()
521
    {
522
        return $this->sortableWeightField;
523
    }
524
525
    public function setSortableOrderState(bool $active)
526
    {
527
        $this->preferences()->setSortableOrderState($this->tableIdentifier(), $active);
528
    }
529
530 13
    public function enableSoftDelete(bool $enabled = true)
531
    {
532 13
        $this->softDeleteEnabled = $enabled;
533 13
    }
534
535 3
    public function isSoftDeleteEnabled(): bool
536
    {
537 3
        return $this->softDeleteEnabled;
538
    }
539
540
    private function makeDefaultColumnField($column)
541
    {
542
        return Text::make($column);
543
    }
544
}
545