Completed
Push — master ( 77bb54...da52cb )
by Philip
06:44
created

EntityDefinition::hasOptimisticLocking()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the CRUDlex package.
5
 *
6
 * (c) Philip Lehmann-Böhm <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace CRUDlex;
13
14
/**
15
 * The class for defining a single entity.
16
 */
17
class EntityDefinition {
18
19
    /**
20
     * The table where the data is stored.
21
     */
22
    protected $table;
23
24
    /**
25
     * Holds all fields in the same structure as in the CRUD YAML file.
26
     */
27
    protected $fields;
28
29
    /**
30
     * The label for the entity.
31
     */
32
    protected $label;
33
34
    /**
35
     * The labels  of the entity in the locales.
36
     */
37
    protected $localeLabels;
38
39
    /**
40
     * An array with the children referencing the entity. All entries are
41
     * arrays with three referencing elements: table, fieldName, entity
42
     */
43
    protected $children;
44
45
    /**
46
     * Labels for the fields "id", "created_at" and "updated_at".
47
     */
48
    protected $standardFieldLabels;
49
50
    /**
51
     * An array containing the fields which should appear in the list view
52
     * of the entity.
53
     */
54
    protected $listFields;
55
56
    /**
57
     * The fields used to display the children on the details page of an entity.
58
     * The keys are the entity names as in the CRUD YAML and the values are the
59
     * field names.
60
     */
61
    protected $childrenLabelFields;
62
63
    /**
64
     * Whether to delete its children when an instance is deleted.
65
     */
66
    protected $deleteCascade;
67
68
    /**
69
     * The amount of items to display per page on the listview.
70
     */
71
    protected $pageSize;
72
73
    /**
74
     * The fields offering to be filtered.
75
     */
76
    protected $filter;
77
78
    /**
79
     * Holds the {@see ServiceProvider}.
80
     */
81
    protected $serviceProvider;
82
83
    /**
84
     * Holds the locale.
85
     */
86
    protected $locale;
87
88
    /**
89
     * Holds the initial sort field.
90
     */
91
    protected $initialSortField;
92
93
    /**
94
     * Holds the initial sort order.
95
     */
96
    protected $initialSortAscending;
97
98
    /**
99
     * Holds if the entity must be displayed grouped in the nav bar.
100
     */
101
    protected $navBarGroup;
102
103
    /**
104
     * Holds whether optimistic locking is switched on.
105
     */
106
    protected $optimisticLocking;
107
108
    /**
109
     * Gets the field names exluding the given ones.
110
     *
111
     * @param string[] $exclude
112
     * the field names to exclude
113
     *
114
     * @return array
115
     * all field names excluding the given ones
116
     */
117 78
    protected function getFilteredFieldNames(array $exclude) {
118 78
        $fieldNames = $this->getFieldNames(true);
119 78
        $result     = [];
120 78
        foreach ($fieldNames as $fieldName) {
121 78
            if (!in_array($fieldName, $exclude)) {
122 78
                $result[] = $fieldName;
123
            }
124
        }
125 78
        return $result;
126
    }
127
128
    /**
129
     * Checks whether the given field names are declared and existing.
130
     *
131
     * @param string $reference
132
     * a hint towards the source of an invalid field name
133
     * @param array $fieldNames
134
     * the field names to check
135
     * @throws \InvalidArgumentException
136
     * thrown with all invalid field names
137
     */
138 78
    protected function checkFieldNames($reference, $fieldNames) {
139 78
        $validFieldNames   = $this->getPublicFieldNames();
140 78
        $invalidFieldNames = [];
141 78
        foreach ($fieldNames as $fieldName) {
142 78
            if (!in_array($fieldName, $validFieldNames)) {
143 1
                $invalidFieldNames[] = $fieldName;
144
            }
145
        }
146 78
        if (!empty($invalidFieldNames)) {
147 1
            throw new \InvalidArgumentException('Invalid fields ('.join(', ', $invalidFieldNames).') in '.$reference.', valid ones are: '.join(', ', $validFieldNames));
148
        }
149 78
    }
150
151
    /**
152
     * Constructor.
153
     *
154
     * @param string $table
155
     * the table of the entity
156
     * @param array $fields
157
     * the field structure just like the CRUD YAML
158
     * @param string $label
159
     * the label of the entity
160
     * @param array $localeLabels
161
     * the labels  of the entity in the locales
162
     * @param array $standardFieldLabels
163
     * labels for the fields "id", "created_at" and "updated_at"
164
     * @param ServiceProvider $serviceProvider
165
     * The current service provider
166
     */
167 79
    public function __construct($table, array $fields, $label, $localeLabels, array $standardFieldLabels, ServiceProvider $serviceProvider) {
168 79
        $this->table               = $table;
169 79
        $this->fields              = $fields;
170 79
        $this->label               = $label;
171 79
        $this->localeLabels        = $localeLabels;
172 79
        $this->standardFieldLabels = $standardFieldLabels;
173 79
        $this->serviceProvider     = $serviceProvider;
174
175 79
        $this->children             = [];
176 79
        $this->listFields           = [];
177 79
        $this->childrenLabelFields  = [];
178 79
        $this->filter               = [];
179 79
        $this->deleteCascade        = false;
180 79
        $this->pageSize             = 25;
181 79
        $this->locale               = null;
182 79
        $this->initialSortField     = 'created_at';
183 79
        $this->initialSortAscending = true;
184 79
        $this->navBarGroup          = 'main';
185 79
        $this->optimisticLocking    = true;
186 79
    }
187
188
    /**
189
     * Gets all field names, including the implicit ones like "id" or
190
     * "created_at".
191
     *
192
     * @param boolean $includeMany
193
     * whether to include the many fields as well
194
     *
195
     * @return string[]
196
     * the field names
197
     */
198 78
    public function getFieldNames($includeMany = false) {
199 78
        $fieldNames = $this->getReadOnlyFields();
200 78
        foreach ($this->fields as $field => $value) {
201 78
            if ($includeMany || $this->getType($field) !== 'many') {
202 78
                $fieldNames[] = $field;
203
            }
204
        }
205 78
        return $fieldNames;
206
    }
207
208
    /**
209
     * Sets the field names to be used in the listview.
210
     *
211
     * @param array $listFields
212
     * the field names to be used in the listview
213
     */
214 78
    public function setListFields(array $listFields) {
215 78
        $this->checkFieldNames('listFields', $listFields);
216 78
        $this->listFields = $listFields;
217 78
    }
218
219
    /**
220
     * Gets the field names to be used in the listview. If they were not specified,
221
     * all public field names are returned.
222
     *
223
     * @return array
224
     * the field names to be used in the listview
225
     */
226 5
    public function getListFields() {
227 5
        if (!empty($this->listFields)) {
228 5
            return $this->listFields;
229
        }
230 3
        return $this->getPublicFieldNames();
231
    }
232
233
    /**
234
     * Gets the fields used to display the children on the details page of an
235
     * entity. The keys are the entity names as in the CRUD YAML and the values
236
     * are the field names.
237
     *
238
     * @return array
239
     * the fields used to display the children on the details page
240
     */
241 7
    public function getChildrenLabelFields() {
242 7
        return $this->childrenLabelFields;
243
    }
244
245
    /**
246
     * Sets the fields used to display the children on the details page of an
247
     * entity. The keys are the entity names as in the CRUD YAML and the values
248
     * are the field names.
249
     *
250
     * @param array $childrenLabelFields
251
     * the fields used to display the children on the details page
252
     */
253 78
    public function setChildrenLabelFields(array $childrenLabelFields) {
254 78
        $this->childrenLabelFields = $childrenLabelFields;
255 78
    }
256
257
    /**
258
     * Gets whether to delete its children when an instance is deleted.
259
     *
260
     * @return boolean
261
     * true if so
262
     */
263 5
    public function isDeleteCascade() {
264 5
        return $this->deleteCascade;
265
    }
266
267
    /**
268
     * Sets whether to delete its children when an instance is deleted.
269
     *
270
     * @param boolean $deleteCascade
271
     * whether to delete its children when an instance is deleted
272
     */
273 78
    public function setDeleteCascade($deleteCascade) {
274 78
        $this->deleteCascade = $deleteCascade;
275 78
    }
276
277
    /**
278
     * Gets the amount of items to display per page on the listview.
279
     *
280
     * @return integer
281
     * the amount of items to display per page on the listview
282
     */
283 5
    public function getPageSize() {
284 5
        return $this->pageSize;
285
    }
286
287
    /**
288
     * Sets the amount of items to display per page on the listview.
289
     *
290
     * @param integer $pageSize
291
     * the amount of items to display per page on the listview
292
     */
293 78
    public function setPageSize($pageSize) {
294 78
        $this->pageSize = $pageSize;
295 78
    }
296
297
    /**
298
     * Gets the fields offering a filter.
299
     *
300
     * @return array
301
     * the fields to filter
302
     */
303 5
    public function getFilter() {
304 5
        return $this->filter;
305
    }
306
307
    /**
308
     * Sets the fields offering a filter.
309
     *
310
     * @param array $filter
311
     * the fields to filter
312
     */
313 78
    public function setFilter(array $filter) {
314 78
        $this->checkFieldNames('filter', $filter);
315 78
        $this->filter = $filter;
316 78
    }
317
318
    /**
319
     * Gets the service provider.
320
     *
321
     * @return ServiceProvider
322
     * the service provider
323
     */
324 40
    public function getServiceProvider() {
325 40
        return $this->serviceProvider;
326
    }
327
328
    /**
329
     * Sets the service provider.
330
     *
331
     * @param ServiceProvider $serviceProvider
332
     * the new service provider
333
     */
334 1
    public function setServiceProvider(ServiceProvider $serviceProvider) {
335 1
        $this->serviceProvider = $serviceProvider;
336 1
    }
337
338
    /**
339
     * Gets the public field names. The internal fields "version" and
340
     * "deleted_at" are filtered.
341
     *
342
     * @return array
343
     * the public field names
344
     */
345 78
    public function getPublicFieldNames() {
346 78
        $exclude = ['version', 'deleted_at'];
347 78
        $result  = $this->getFilteredFieldNames($exclude);
348 78
        return $result;
349
    }
350
351
    /**
352
     * Gets the field names which are editable. Not editable are fields like the
353
     * id or the created_at.
354
     *
355
     * @return array
356
     * the editable field names
357
     */
358 42
    public function getEditableFieldNames() {
359 42
        $result = $this->getFilteredFieldNames($this->getReadOnlyFields());
360 42
        return $result;
361
    }
362
363
    /**
364
     * Gets the read only field names like the id or the created_at.
365
     *
366
     * @return string[]
367
     * the read only field names
368
     */
369 78
    public function getReadOnlyFields() {
370 78
        $result = ['id', 'created_at', 'updated_at', 'deleted_at'];
371 78
        if ($this->optimisticLocking) {
372 78
            $result[] = 'version';
373
        }
374 78
        return $result;
375
    }
376
377
    /**
378
     * Gets the type of a field.
379
     *
380
     * @param string $fieldName
381
     * the field name
382
     *
383
     * @return string
384
     * the type or null on invalid field name
385
     */
386 78
    public function getType($fieldName) {
387 78
        if ($fieldName === 'id') {
388 78
            return 'string';
389
        }
390 78
        if ($fieldName === 'version') {
391 77
            return 'integer';
392
        }
393 78
        if (in_array($fieldName, ['created_at', 'updated_at', 'deleted_at'])) {
394 78
            return 'datetime';
395
        }
396 78
        return $this->getField($fieldName, 'type');
397
    }
398
399
    /**
400
     * Sets the type of a field.
401
     *
402
     * @param string $fieldName
403
     * the field name
404
     * @param string $value
405
     * the new field type
406
     */
407 1
    public function setType($fieldName, $value) {
408 1
        $this->setField($fieldName, 'type', $value);
409 1
    }
410
411
    /**
412
     * Gets the label of a field.
413
     *
414
     * @param string $fieldName
415
     * the field name
416
     *
417
     * @return string
418
     * the label of the field or the field name if no label is set in the CRUD
419
     * YAML
420
     */
421 9
    public function getFieldLabel($fieldName) {
422
423 9
        $result = $this->getField($fieldName, 'label_'.$this->locale, $this->getField($fieldName, 'label'));
424
425 9
        if ($result === null && array_key_exists($fieldName, $this->standardFieldLabels)) {
426 8
            $result = $this->standardFieldLabels[$fieldName];
427
        }
428
429 9
        if ($result === null) {
430 1
            $result = $fieldName;
431
        }
432
433 9
        return $result;
434
    }
435
436
    /**
437
     * Gets the label of a field.
438
     *
439
     * @param string $fieldName
440
     * the field name
441
     * @param string $value
442
     * the new label of the field
443
     */
444 1
    public function setFieldLabel($fieldName, $value) {
445 1
        $this->setField($fieldName, 'label', $value);
446 1
    }
447
448
    /**
449
     * Gets the table where the data is stored.
450
     *
451
     * @return string
452
     * the table where the data is stored
453
     */
454 77
    public function getTable() {
455 77
        return $this->table;
456
    }
457
458
    /**
459
     * Sets the table where the data is stored.
460
     *
461
     * @param string $table
462
     * the new table where the data is stored
463
     */
464 1
    public function setTable($table) {
465 1
        $this->table = $table;
466 1
    }
467
468
    /**
469
     * Gets the label for the entity.
470
     *
471
     * @return string
472
     * the label for the entity
473
     */
474 11
    public function getLabel() {
475 11
        if ($this->locale && array_key_exists($this->locale, $this->localeLabels)) {
476 2
            return $this->localeLabels[$this->locale];
477
        }
478 11
        return $this->label;
479
    }
480
481
    /**
482
     * Sets the label for the entity.
483
     *
484
     * @param string $label
485
     * the new label for the entity
486
     */
487 1
    public function setLabel($label) {
488 1
        $this->label = $label;
489 1
    }
490
491
    /**
492
     * Adds a child to this definition in case the other
493
     * definition has a reference to this one.
494
     *
495
     * @param string $table
496
     * the table of the referencing definition
497
     * @param string $fieldName
498
     * the field name of the referencing definition
499
     * @param string $entity
500
     * the entity of the referencing definition
501
     */
502 77
    public function addChild($table, $fieldName, $entity) {
503 77
        $this->children[] = [$table, $fieldName, $entity];
504 77
    }
505
506
    /**
507
     * Gets the referencing children to this definition.
508
     *
509
     * @return array
510
     * an array with the children referencing the entity. All entries are arrays
511
     * with three referencing elements: table, fieldName, entity
512
     */
513 7
    public function getChildren() {
514 7
        return $this->children;
515
    }
516
517
    /**
518
     * Sets the locale to be used.
519
     *
520
     * @param string $locale
521
     * the locale to be used.
522
     */
523 13
    public function setLocale($locale) {
524 13
        $this->locale = $locale;
525 13
    }
526
527
    /**
528
     * Gets the locale to be used.
529
     *
530
     * @return null|string
531
     * the locale to be used.
532
     */
533 2
    public function getLocale() {
534 2
        return $this->locale;
535
    }
536
537
    /**
538
     * Sets the initial sort field.
539
     *
540
     * @param string $initialSortField
541
     * the new initial sort field
542
     */
543 78
    public function setInitialSortField($initialSortField) {
544 78
        $this->initialSortField = $initialSortField;
545 78
    }
546
547
    /**
548
     * Gets the initial sort field.
549
     *
550
     * @return string
551
     * the initial sort field
552
     */
553 6
    public function getInitialSortField() {
554 6
        return $this->initialSortField;
555
    }
556
557
    /**
558
     * Sets the initial sort order.
559
     *
560
     * @param boolean $initialSortAscending
561
     * the initial sort order, true if ascending
562
     */
563 78
    public function setInitialSortAscending($initialSortAscending) {
564 78
        $this->initialSortAscending = $initialSortAscending;
565 78
    }
566
567
    /**
568
     * Gets the initial sort order.
569
     *
570
     * @return boolean
571
     * the initial sort order, true if ascending
572
     */
573 6
    public function isInitialSortAscending() {
574 6
        return $this->initialSortAscending;
575
    }
576
577
    /**
578
     * Gets the navigation bar group where the entity belongs.
579
     *
580
     * @return string
581
     * the navigation bar group where the entity belongs
582
     */
583 11
    public function getNavBarGroup() {
584 11
        return $this->navBarGroup;
585
    }
586
587
    /**
588
     * Sets the navigation bar group where the entity belongs.
589
     *
590
     * @param string $navBarGroup
591
     * the navigation bar group where the entity belongs
592
     */
593 78
    public function setNavBarGroup($navBarGroup) {
594 78
        $this->navBarGroup = $navBarGroup;
595 78
    }
596
597
    /**
598
     * Returns whether optimistic locking via the version field is activated.
599
     * @return boolean
600
     * true if optimistic locking is activated
601
     */
602 39
    public function hasOptimisticLocking() {
603 39
        return $this->optimisticLocking;
604
    }
605
606
607
    /**
608
     * Sets whether optimistic locking via the version field is activated.
609
     * @param boolean $optimisticLocking
610
     * true if optimistic locking is activated
611
     */
612 78
    public function setOptimisticLocking($optimisticLocking) {
613 78
        $this->optimisticLocking = $optimisticLocking;
614 78
    }
615
616
    /**
617
     * Gets a sub field of an field.
618
     *
619
     * @param string $fieldName
620
     * the field name of the sub type
621
     * @param string $subType
622
     * the sub type like "reference" or "many"
623
     * @param string $key
624
     * the key of the value
625
     *
626
     * @return string
627
     * the value of the sub field
628
     */
629 77
    public function getSubTypeField($fieldName, $subType, $key) {
630
631 77
        if (!isset($this->fields[$fieldName][$subType][$key])) {
632 26
            return null;
633
        }
634
635 77
        return $this->fields[$fieldName][$subType][$key];
636
    }
637
638
    /**
639
     * Gets the value of a field key.
640
     *
641
     * @param string $name
642
     * the name of the field
643
     * @param string $key
644
     * the value of the key
645
     * @param mixed $default
646
     * the default value to return if nothing is found
647
     *
648
     * @return mixed
649
     * the value of the field key or null if not existing
650
     */
651 78
    public function getField($name, $key, $default = null) {
652 78
        if (array_key_exists($name, $this->fields) && array_key_exists($key, $this->fields[$name])) {
653 77
            return $this->fields[$name][$key];
654
        }
655 45
        return $default;
656
    }
657
658
    /**
659
     * Sets the value of a field key. If the field or the key in the field
660
     * don't exist, they get created.
661
     *
662
     * @param string $name
663
     * the name of the field
664
     * @param string $key
665
     * the value of the key
666
     * @param mixed $value
667
     * the new value
668
     */
669 6
    public function setField($name, $key, $value) {
670 6
        if (!array_key_exists($name, $this->fields)) {
671 1
            $this->fields[$name] = [];
672
        }
673 6
        $this->fields[$name][$key] = $value;
674 6
    }
675
676
}
677