Completed
Push — master ( 4e93f3...8a5e52 )
by Philip
03:00
created

EntityDefinition::getDescription()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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