Completed
Branch master (6d30bf)
by Philip
13:30
created

EntityDefinition::getChildrenLabelFields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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