Completed
Push — master ( d053aa...4e433e )
by Philip
02:38
created

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