Completed
Push — master ( 194cbe...2ee496 )
by Yaro
05:39 queued 19s
created

CRUD::getFieldsWithoutMarkup()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
ccs 5
cts 5
cp 1
cc 2
nc 2
nop 0
crap 2
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\Interfaces\ToolInterface;
11
12
class CRUD
13
{
14
    const BASE_URL_DELIMITER = '/~/';
15
16
    private $fields = [];
17
    private $actions;
18
    private $model = '';
19
    private $repo;
20
    private $preferences;
21
    private $tableIdentifier;
22
    private $rawPerPage;
23
    private $columns = [];
24
    private $formClass = 'col-sm-12 col-md-12 col-lg-12';
25
    private $toolbar = [];
26
    private $locales = [];
27
    private $batchCheckboxesEnabled = false;
28
    private $sortableWeightField = null;
29
    private $softDeleteEnabled = false;
30
31 18
    public function __construct(ModelRepository $repo, PreferencesRepository $preferences, ActionsContainer $actions)
32
    {
33 18
        $this->repo = $repo;
34 18
        $this->preferences = $preferences;
35 18
        $this->actions = $actions;
36 18
    }
37
38 17
    public function formClass(string $class = null)
39
    {
40 17
        if (!is_null($class)) {
41 17
            $this->formClass = $class;
42
        }
43
44 17
        return $this->formClass;
45
    }
46
47
    public function getRawPerPage()
48
    {
49
        return $this->rawPerPage;
50
    }
51
52
    /**
53
     * @param string|AbstractField $column
54
     */
55
    public function addColumn($column)
56
    {
57
        $this->columns[] = $column;
58
    }
59
60 13
    public function getColumns()
61
    {
62 13
        return $this->columns;
63
    }
64
65
    /**
66
     * Get columns as field objects, or fields if there are no columns.
67
     *
68
     * @return array
69
     */
70
    public function getColumnsAsFields()
71
    {
72
        $columns = [];
73
        foreach ($this->getColumns() as $column) {
74
            if (!is_object($column)) {
75
                $column = $this->getFieldByName($column) ?: $this->makeDefaultColumnField($column);
76
            }
77
78
            if ($column) {
79
                $columns[] = $column;
80
            }
81
        }
82
83
        return $columns ?: $this->getFields();
84
    }
85
86
    /**
87
     * Get list of columns that initialized as field object.
88
     *
89
     * @return array
90
     */
91 13
    public function getColumnsWithoutRelatedField()
92
    {
93 13
        $columns = [];
94 13
        foreach ($this->getColumns() as $column) {
95
            if (is_object($column)) {
96
                $columns[] = $column;
97
            }
98
        }
99
100 13
        return $columns;
101
    }
102
103 13
    public function getAllFieldObjects()
104
    {
105 13
        $fieldsAndColumns = array_merge(
106 13
            $this->getFieldsWithoutMarkup(),
107 13
            $this->getColumnsWithoutRelatedField()
108
        );
109
110 13
        return $fieldsAndColumns;
111
    }
112
113 1
    public function getFieldByName($name)
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...
114
    {
115 1
        $fields = $this->getFieldsWithoutMarkup();
116 1
        foreach ($fields as $field) {
117 1
            if ($field->name() === $name) {
118 1
                return $field;
119
            }
120
        }
121
122
        return null;
123
    }
124
125 13
    public function addField(AbstractField $field)
126
    {
127 13
        $this->fields[] = $field;
128 13
    }
129
130 13
    public function getFields()
131
    {
132 13
        return $this->fields;
133
    }
134
135 13
    public function getFieldsWithoutMarkup()
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...
136
    {
137 13
        $fields = [];
138 13
        foreach ($this->getFields() as $field) {
139 13
            $this->extractField($field, $fields);
140
        }
141
142 13
        return $fields;
143
    }
144
145 13
    private function extractField(AbstractField $field, &$fields)
146
    {
147 13
        if (!$field->isMarkupRow()) {
148 13
            $fields[] = $field;
149 13
            return;
150
        }
151
152
        foreach ($field->getFields() as $field) {
153
            $this->extractField($field, $fields);
154
        }
155
    }
156
157
    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...
158
    {
159
        $tabs = [];
160
        foreach ($this->getFields() as $field) {
161
            if ($skipHiddenType && $field->hidden($skipHiddenType)) {
162
                continue;
163
            }
164
            $tabs[$field->getTab()][] = $field;
165
        }
166
167
        $this->moveDefaultTabToEnd($tabs);
168
169
        return $tabs;
170
    }
171
172
    private function moveDefaultTabToEnd(&$tabs)
173
    {
174
        $defaultTab = AbstractField::DEFAULT_TAB_IDENT;
175
        if (!array_key_exists($defaultTab, $tabs)) {
176
            return;
177
        }
178
179
        $defaultTabFields = $tabs[$defaultTab];
180
        unset($tabs[$defaultTab]);
181
        $tabs[$defaultTab] = $defaultTabFields;
182
    }
183
184 13
    public function setModel($model)
185
    {
186 13
        $this->model = $model;
187
188 13
        return $this;
189
    }
190
191 13
    public function repo()
192
    {
193 13
        return $this->repo->setCrud($this);
194
    }
195
196 4
    public function preferences()
197
    {
198 4
        return $this->preferences;
199
    }
200
201
    /**
202
     * @param int|array $perPage
203
     */
204
    public function paginate($perPage)
205
    {
206
        $this->rawPerPage = $perPage;
207
208
        $storedPerPage = $this->getPerPageParam();
209
        if (is_array($perPage)) {
210
            $perPage = array_shift($perPage);
211
        }
212
        if (!$storedPerPage) {
213
            $this->setPerPageParam($perPage ?: $this->repo()->perPage());
214
            $storedPerPage = $perPage;
215
        }
216
        $this->repo()->perPage($storedPerPage);
217
218
        return $this;
219
    }
220
221
    public function order(string $column, string $direction)
222
    {
223
        $this->repo()->order($column, $direction);
224
225
        return $this;
226
    }
227
228 13
    public function filter(\Closure $callback)
229
    {
230 13
        $this->repo()->filter($callback);
231
232 13
        return $this;
233
    }
234
235 13
    public function getModel()
236
    {
237 13
        return $this->model;
238
    }
239
240
    public function hasAnyFieldFilter()
241
    {
242
        foreach ($this->getColumnsAsFields() as $field) {
243
            if (!$field->hidden('list') && $field->filter()) {
244
                return true;
245
            }
246
        }
247
248
        return false;
249
    }
250
251
    public function editUrl($id)
252
    {
253
        return sprintf('%s%s%s', $this->baseUrl(), self::BASE_URL_DELIMITER, $id);
254
    }
255
256
    public function createUrl()
257
    {
258
        return sprintf('%s%screate', $this->baseUrl(), self::BASE_URL_DELIMITER);
259
    }
260
261
    public function deleteUrl($id)
262
    {
263
        return sprintf('%s%s%s/delete', $this->baseUrl(), self::BASE_URL_DELIMITER, $id);
264
    }
265
266
    public function restoreUrl($id)
267
    {
268
        return sprintf('%s%s%s/restore', $this->baseUrl(), self::BASE_URL_DELIMITER, $id);
269
    }
270
271
    public function forceDeleteUrl($id)
272
    {
273
        return sprintf('%s%s%s/force-delete', $this->baseUrl(), self::BASE_URL_DELIMITER, $id);
274
    }
275
276
    public function toolbarUrl($identifier)
277
    {
278
        return sprintf('%s%stoolbar/%s', $this->baseUrl(), self::BASE_URL_DELIMITER, $identifier);
279
    }
280
281 5
    public function listUrl()
282
    {
283 5
        return $this->baseUrl();
284
    }
285
286
    public function perPageUrl($perPage)
287
    {
288
        return sprintf('%s%sper-page/%s', $this->baseUrl(), self::BASE_URL_DELIMITER, $perPage);
289
    }
290
291
    public function searchUrl()
292
    {
293
        return sprintf('%s%ssearch', $this->baseUrl(), self::BASE_URL_DELIMITER);
294
    }
295
296
    public function relationSearchUrl()
297
    {
298
        return sprintf('%s%ssearch/relation', $this->baseUrl(), self::BASE_URL_DELIMITER);
299
    }
300
301 13
    public function inlineUrl()
302
    {
303 13
        return sprintf('%s%sinline', $this->baseUrl(), self::BASE_URL_DELIMITER);
304
    }
305
306
    public function orderUrl($column, $direction)
307
    {
308
        return sprintf('%s%sorder/%s/%s', $this->baseUrl(), self::BASE_URL_DELIMITER, $column, $direction);
309
    }
310
311
    public function reorderUrl()
312
    {
313
        return sprintf('%s%sreorder/switch', $this->baseUrl(), self::BASE_URL_DELIMITER);
314
    }
315
316
    public function reorderMoveItemUrl($id)
317
    {
318
        return sprintf('%s%sreorder/move/%s', $this->baseUrl(), self::BASE_URL_DELIMITER, $id);
319
    }
320
321 14
    public function baseUrl()
322
    {
323 14
        $chunks = explode(self::BASE_URL_DELIMITER, request()->url());
324
325 14
        return rtrim($chunks[0], '/');
326
    }
327
328 17
    public function tableIdentifier($ident = 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...
329
    {
330 17
        if (is_null($ident)) {
331 4
            return $this->tableIdentifier;
332
        }
333
334 17
        $this->tableIdentifier = $ident;
335 17
    }
336
337 1
    public function saveSearchFilterParams(array $params)
338
    {
339 1
        $this->preferences()->saveSearchFilterParams($this->tableIdentifier(), $params);
340 1
    }
341
342 1
    public function getOrderFilterParam($column)
343
    {
344 1
        return $this->preferences()->getOrderFilterParam($this->tableIdentifier(), $column);
345
    }
346
347 1
    public function saveOrderFilterParam($column, $direction)
348
    {
349 1
        $this->preferences()->saveOrderFilterParam($this->tableIdentifier(), $column, $direction);
350 1
    }
351
352 1
    public function getPerPageParam()
353
    {
354 1
        return $this->preferences()->getPerPageParam($this->tableIdentifier());
355
    }
356
357 1
    public function setPerPageParam($perPage)
358
    {
359 1
        $this->preferences()->setPerPageParam($this->tableIdentifier(), $perPage);
360 1
    }
361
362
    public function getCurrentLocale()
363
    {
364
        return $this->preferences()->getCurrentLocale($this->tableIdentifier()) ?: key($this->getLocales());
365
    }
366
367
    public function saveCurrentLocale($locale)
368
    {
369
        $this->preferences()->saveCurrentLocale($this->tableIdentifier(), $locale);
370
    }
371
372 2
    public function getTool($ident)
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...
373
    {
374 2
        if (array_key_exists($ident, $this->toolbar)) {
375 2
            return $this->toolbar[$ident];
376
        }
377
378
        throw new \RuntimeException('Not allowed toolbar');
379
    }
380
381 2
    public function addTool(ToolInterface $tool)
382
    {
383 2
        $this->toolbar[$tool->identifier()] = $tool;
384 2
    }
385
386 2
    public function getTools()
387
    {
388 2
        return $this->toolbar;
389
    }
390
391
    public function getActiveHeaderToolbarTools()
392
    {
393
        $list = [];
394
        /** @var ToolInterface $tool */
395
        foreach ($this->toolbar as $tool) {
396
            if ($tool->position() == ToolInterface::POSITION_HEADER && $tool->check()) {
397
                $list[] = $tool;
398
            }
399
        }
400
401
        return $list;
402
    }
403
404
    public function getActiveBodyToolbarToolsOnTop()
405
    {
406
        return $this->getActiveBodyToolbarTools(ToolInterface::POSITION_BODY_TOP);
407
    }
408
409
    public function getActiveBodyToolbarToolsOnBottom()
410
    {
411
        return $this->getActiveBodyToolbarTools(ToolInterface::POSITION_BODY_BOTTOM);
412
    }
413
414
    public function getActiveBodyToolbarTools($position)
415
    {
416
        $list = [];
417
        /** @var ToolInterface $tool */
418
        foreach ($this->toolbar as $tool) {
419
            $isPositioned = $tool->position() == $position || $tool->position() == ToolInterface::POSITION_BODY_BOTH;
420
            if ($isPositioned && $tool->check()) {
421
                $list[] = $tool;
422
            }
423
        }
424
425
        return $list;
426
    }
427
428
    public function getTabErrorsCount($tabTitle, $errors)
429
    {
430
        $count = 0;
431
        $tabs = $this->getTabs();
432
        $fields = $tabs[$tabTitle];
433
434
        foreach ($fields as $field) {
435
            $count += count($errors->get($field->name()));
436
        }
437
438
        return $count;
439
    }
440
441
    public function locales(array $locales)
442
    {
443
        $this->normalizeLocales($locales);
444
        $this->locales = $locales;
445
446
        return $this;
447
    }
448
449
    public function getLocales()
450
    {
451
        return $this->locales;
452
    }
453
454
    // TODO: move helper to trait or smth
455
    private function isAssociativeArray(array $array)
456
    {
457
        if ($array === []) {
458
            return false;
459
        }
460
461
        return array_keys($array) !== range(0, count($array) - 1);
462
    }
463
464
    private function normalizeLocales(array &$locales)
465
    {
466
        if (!$this->isAssociativeArray($locales)) {
467
            $locales = array_combine(
468
                array_values($locales),
469
                array_values($locales)
470
            );
471
        }
472
    }
473
474 17
    public function actions()
475
    {
476 17
        return $this->actions;
477
    }
478
479 1
    public function enableBatchCheckboxes(bool $enabled = true)
480
    {
481 1
        $this->batchCheckboxesEnabled = $enabled;
482 1
    }
483
484
    public function isBatchCheckboxesEnabled()
485
    {
486
        return $this->batchCheckboxesEnabled;
487
    }
488
489
    public function enableSortableByWeight(string $field)
490
    {
491
        $this->sortableWeightField = $field;
492
    }
493
494
    public function isSortableByWeight()
495
    {
496
        return (bool) $this->getSortableWeightFieldName();
497
    }
498
499 1
    public function isSortableByWeightActive()
500
    {
501 1
        return $this->preferences()->isSortableByWeightActive($this->tableIdentifier());
502
    }
503
504
    public function getSortableWeightFieldName()
505
    {
506
        return $this->sortableWeightField;
507
    }
508
509
    public function setSortableOrderState(bool $active)
510
    {
511
        $this->preferences()->setSortableOrderState($this->tableIdentifier(), $active);
512
    }
513
514 13
    public function enableSoftDelete(bool $enabled = true)
515
    {
516 13
        $this->softDeleteEnabled = $enabled;
517 13
    }
518
519 3
    public function isSoftDeleteEnabled(): bool
520
    {
521 3
        return $this->softDeleteEnabled;
522
    }
523
524
    private function makeDefaultColumnField($column)
525
    {
526
        return Text::make($column);
527
    }
528
}