Completed
Push — master ( da4c0c...3e5ac4 )
by Philip
02:40
created

EntityDefinition::getLabel()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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