Completed
Push — master ( 3860b0...3001cf )
by Philip
02:28
created

EntityDefinition::getDescription()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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