Completed
Push — master ( 88dc63...f1a41d )
by Philip
03:05
created

EntityDefinition::getItems()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
nc 1
cc 1
eloc 3
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 label of a field.
516
     *
517
     * @param string $fieldName
518
     * the field name
519
     *
520
     * @return string
521
     * the label of the field or the field name if no label is set in the CRUD
522
     * YAML
523
     */
524
    public function getFieldLabel($fieldName) {
525
526
        $result = $this->getField($fieldName, 'label_'.$this->locale);
527
528
        if ($result === null) {
529
            $result = $this->getField($fieldName, 'label');
530
        }
531
532
        if ($result === null && array_key_exists($fieldName, $this->standardFieldLabels)) {
533
            $result = $this->standardFieldLabels[$fieldName];
534
        }
535
536
        if ($result === null) {
537
            $result = $fieldName;
538
        }
539
540
        return $result;
541
    }
542
543
    /**
544
     * Gets the label of a field.
545
     *
546
     * @param string $fieldName
547
     * the field name
548
     * @param string $value
549
     * the new label of the field
550
     */
551
    public function setFieldLabel($fieldName, $value) {
552
        $this->setField($fieldName, 'label', $value);
553
    }
554
555
    /**
556
     * Gets the table where the data is stored.
557
     *
558
     * @return string
559
     * the table where the data is stored
560
     */
561
    public function getTable() {
562
        return $this->table;
563
    }
564
565
    /**
566
     * Sets the table where the data is stored.
567
     *
568
     * @param string $table
569
     * the new table where the data is stored
570
     */
571
    public function setTable($table) {
572
        $this->table = $table;
573
    }
574
575
    /**
576
     * Gets the label for the entity.
577
     *
578
     * @return string
579
     * the label for the entity
580
     */
581
    public function getLabel() {
582
        if ($this->locale && array_key_exists($this->locale, $this->localeLabels)) {
583
            return $this->localeLabels[$this->locale];
584
        }
585
        return $this->label;
586
    }
587
588
    /**
589
     * Sets the label for the entity.
590
     *
591
     * @param string $label
592
     * the new label for the entity
593
     */
594
    public function setLabel($label) {
595
        $this->label = $label;
596
    }
597
598
    /**
599
     * Adds a child to this definition in case the other
600
     * definition has a reference to this one.
601
     *
602
     * @param string $table
603
     * the table of the referencing definition
604
     * @param string $fieldName
605
     * the field name of the referencing definition
606
     * @param string $entity
607
     * the entity of the referencing definition
608
     */
609
    public function addChild($table, $fieldName, $entity) {
610
        $this->children[] = [$table, $fieldName, $entity];
611
    }
612
613
    /**
614
     * Gets the referencing children to this definition.
615
     *
616
     * @return array
617
     * an array with the children referencing the entity. All entries are arrays
618
     * with three referencing elements: table, fieldName, entity
619
     */
620
    public function getChildren() {
621
        return $this->children;
622
    }
623
624
    /**
625
     * Sets the locale to be used.
626
     *
627
     * @param string $locale
628
     * the locale to be used.
629
     */
630
    public function setLocale($locale) {
631
        $this->locale = $locale;
632
    }
633
634
    /**
635
     * Gets the locale to be used.
636
     *
637
     * @return null|string
638
     * the locale to be used.
639
     */
640
    public function getLocale() {
641
        return $this->locale;
642
    }
643
644
    /**
645
     * Sets the initial sort field.
646
     *
647
     * @param string $initialSortField
648
     * the new initial sort field
649
     */
650
    public function setInitialSortField($initialSortField) {
651
        $this->initialSortField = $initialSortField;
652
    }
653
654
    /**
655
     * Gets the initial sort field.
656
     *
657
     * @return string
658
     * the initial sort field
659
     */
660
    public function getInitialSortField() {
661
        return $this->initialSortField;
662
    }
663
664
    /**
665
     * Sets the initial sort order.
666
     *
667
     * @param boolean $initialSortAscending
668
     * the initial sort order, true if ascending
669
     */
670
    public function setInitialSortAscending($initialSortAscending) {
671
        $this->initialSortAscending = $initialSortAscending;
672
    }
673
674
    /**
675
     * Gets the initial sort order.
676
     *
677
     * @return boolean
678
     * the initial sort order, true if ascending
679
     */
680
    public function isInitialSortAscending() {
681
        return $this->initialSortAscending;
682
    }
683
684
    /**
685
     * Gets a sub field of an field.
686
     *
687
     * @param string $fieldName
688
     * the field name of the sub type
689
     * @param string $subType
690
     * the sub type like "reference" or "many"
691
     * @param string $key
692
     * the key of the value
693
     *
694
     * @return string
695
     * the value of the sub field
696
     */
697
    public function getSubTypeField($fieldName, $subType, $key) {
698
699
        if (!isset($this->fields[$fieldName][$subType][$key])) {
700
            return null;
701
        }
702
703
        return $this->fields[$fieldName][$subType][$key];
704
    }
705
706
    /**
707
     * Gets the value of a field key.
708
     *
709
     * @param string $name
710
     * the name of the field
711
     * @param string $key
712
     * the value of the key
713
     * @param mixed $default
714
     * the default value to return if nothing is found
715
     *
716
     * @return mixed
717
     * the value of the field key or null if not existing
718
     */
719
    public function getField($name, $key, $default = null) {
720
        if (array_key_exists($name, $this->fields) && array_key_exists($key, $this->fields[$name])) {
721
            return $this->fields[$name][$key];
722
        }
723
        return $default;
724
    }
725
726
    /**
727
     * Sets the value of a field key. If the field or the key in the field
728
     * don't exist, they get created.
729
     *
730
     * @param string $name
731
     * the name of the field
732
     * @param string $key
733
     * the value of the key
734
     * @param mixed $value
735
     * the new value
736
     */
737
    public function setField($name, $key, $value) {
738
        if (!array_key_exists($name, $this->fields)) {
739
            $this->fields[$name] = [];
740
        }
741
        $this->fields[$name][$key] = $value;
742
    }
743
744
}
745