Completed
Push — master ( 99b8e2...31ec46 )
by Philip
02:37
created

EntityDefinition::getFieldLabel()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.2
c 0
b 0
f 0
cc 4
eloc 7
nc 4
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 whether the given field names are declared and existing.
120
     *
121
     * @param string $reference
122
     * a hint towards the source of an invalid field name
123
     * @param array $fieldNames
124
     * the field names to check
125
     * @throws \InvalidArgumentException
126
     * thrown with all invalid field names
127
     */
128
    protected function checkFieldNames($reference, $fieldNames) {
129
        $validFieldNames   = $this->getPublicFieldNames();
130
        $invalidFieldNames = [];
131
        foreach ($fieldNames as $fieldName) {
132
            if (!in_array($fieldName, $validFieldNames)) {
133
                $invalidFieldNames[] = $fieldName;
134
            }
135
        }
136
        if (!empty($invalidFieldNames)) {
137
            throw new \InvalidArgumentException('Invalid fields ('.join(', ', $invalidFieldNames).') in '.$reference.', valid ones are: '.join(', ', $validFieldNames));
138
        }
139
    }
140
141
    /**
142
     * Constructor.
143
     *
144
     * @param string $table
145
     * the table of the entity
146
     * @param array $fields
147
     * the field structure just like the CRUD YAML
148
     * @param string $label
149
     * the label of the entity
150
     * @param array $localeLabels
151
     * the labels  of the entity in the locales
152
     * @param array $standardFieldLabels
153
     * labels for the fields "id", "created_at" and "updated_at"
154
     * @param ServiceProvider $serviceProvider
155
     * The current service provider
156
     */
157
    public function __construct($table, array $fields, $label, $localeLabels, array $standardFieldLabels, ServiceProvider $serviceProvider) {
158
        $this->table               = $table;
159
        $this->fields              = $fields;
160
        $this->label               = $label;
161
        $this->localeLabels        = $localeLabels;
162
        $this->standardFieldLabels = $standardFieldLabels;
163
        $this->serviceProvider     = $serviceProvider;
164
165
        $this->children             = [];
166
        $this->listFields           = [];
167
        $this->childrenLabelFields  = [];
168
        $this->filter               = [];
169
        $this->deleteCascade        = false;
170
        $this->pageSize             = 25;
171
        $this->locale               = null;
172
        $this->initialSortField     = 'created_at';
173
        $this->initialSortAscending = true;
174
    }
175
176
    /**
177
     * Gets all field names, including the implicit ones like "id" or
178
     * "created_at".
179
     *
180
     * @param boolean $includeMany
181
     * whether to include the many fields as well
182
     *
183
     * @return string[]
184
     * the field names
185
     */
186
    public function getFieldNames($includeMany = false) {
187
        $fieldNames = $this->getReadOnlyFields();
188
        foreach ($this->fields as $field => $value) {
189
            if ($includeMany || $this->getType($field) !== 'many') {
190
                $fieldNames[] = $field;
191
            }
192
        }
193
        return $fieldNames;
194
    }
195
196
    /**
197
     * Sets the field names to be used in the listview.
198
     *
199
     * @param array $listFields
200
     * the field names to be used in the listview
201
     */
202
    public function setListFields(array $listFields) {
203
        $this->checkFieldNames('listFields', $listFields);
204
        $this->listFields = $listFields;
205
    }
206
207
    /**
208
     * Gets the field names to be used in the listview. If they were not specified,
209
     * all public field names are returned.
210
     *
211
     * @return array
212
     * the field names to be used in the listview
213
     */
214
    public function getListFields() {
215
        if (!empty($this->listFields)) {
216
            return $this->listFields;
217
        }
218
        return $this->getPublicFieldNames();
219
    }
220
221
    /**
222
     * Gets the fields used to display the children on the details page of an
223
     * entity. The keys are the entity names as in the CRUD YAML and the values
224
     * are the field names.
225
     *
226
     * @return array
227
     * the fields used to display the children on the details page
228
     */
229
    public function getChildrenLabelFields() {
230
        return $this->childrenLabelFields;
231
    }
232
233
    /**
234
     * Sets the fields used to display the children on the details page of an
235
     * entity. The keys are the entity names as in the CRUD YAML and the values
236
     * are the field names.
237
     *
238
     * @param array $childrenLabelFields
239
     * the fields used to display the children on the details page
240
     */
241
    public function setChildrenLabelFields(array $childrenLabelFields) {
242
        $this->childrenLabelFields = $childrenLabelFields;
243
    }
244
245
    /**
246
     * Gets whether to delete its children when an instance is deleted.
247
     *
248
     * @return boolean
249
     * true if so
250
     */
251
    public function isDeleteCascade() {
252
        return $this->deleteCascade;
253
    }
254
255
    /**
256
     * Sets whether to delete its children when an instance is deleted.
257
     *
258
     * @param boolean $deleteCascade
259
     * whether to delete its children when an instance is deleted
260
     */
261
    public function setDeleteCascade($deleteCascade) {
262
        $this->deleteCascade = $deleteCascade;
263
    }
264
265
    /**
266
     * Gets the amount of items to display per page on the listview.
267
     *
268
     * @return integer
269
     * the amount of items to display per page on the listview
270
     */
271
    public function getPageSize() {
272
        return $this->pageSize;
273
    }
274
275
    /**
276
     * Sets the amount of items to display per page on the listview.
277
     *
278
     * @param integer $pageSize
279
     * the amount of items to display per page on the listview
280
     */
281
    public function setPageSize($pageSize) {
282
        $this->pageSize = $pageSize;
283
    }
284
285
    /**
286
     * Gets the fields offering a filter.
287
     *
288
     * @return array
289
     * the fields to filter
290
     */
291
    public function getFilter() {
292
        return $this->filter;
293
    }
294
295
    /**
296
     * Sets the fields offering a filter.
297
     *
298
     * @param array $filter
299
     * the fields to filter
300
     */
301
    public function setFilter(array $filter) {
302
        $this->checkFieldNames('filter', $filter);
303
        $this->filter = $filter;
304
    }
305
306
    /**
307
     * Gets the service provider.
308
     *
309
     * @return ServiceProvider
310
     * the service provider
311
     */
312
    public function getServiceProvider() {
313
        return $this->serviceProvider;
314
    }
315
316
    /**
317
     * Sets the service provider.
318
     *
319
     * @param ServiceProvider $serviceProvider
320
     * the new service provider
321
     */
322
    public function setServiceProvider(ServiceProvider $serviceProvider) {
323
        $this->serviceProvider = $serviceProvider;
324
    }
325
326
    /**
327
     * Gets the public field names. The internal fields "version" and
328
     * "deleted_at" are filtered.
329
     *
330
     * @return array
331
     * the public field names
332
     */
333
    public function getPublicFieldNames() {
334
        $exclude = ['version', 'deleted_at'];
335
        $result  = $this->getFilteredFieldNames($exclude);
336
        return $result;
337
    }
338
339
    /**
340
     * Gets the field names which are editable. Not editable are fields like the
341
     * id or the created_at.
342
     *
343
     * @return array
344
     * the editable field names
345
     */
346
    public function getEditableFieldNames() {
347
        $result = $this->getFilteredFieldNames($this->getReadOnlyFields());
348
        return $result;
349
    }
350
351
    /**
352
     * Gets the read only field names like the id or the created_at.
353
     *
354
     * @return string[]
355
     * the read only field names
356
     */
357
    public function getReadOnlyFields() {
358
        return ['id', 'created_at', 'updated_at', 'version', 'deleted_at'];
359
    }
360
361
    /**
362
     * Gets the type of a field.
363
     *
364
     * @param string $fieldName
365
     * the field name
366
     *
367
     * @return string
368
     * the type or null on invalid field name
369
     */
370
    public function getType($fieldName) {
371
        if ($fieldName === 'id') {
372
            return 'string';
373
        }
374
        if ($fieldName === 'version') {
375
            return 'integer';
376
        }
377
        if (in_array($fieldName, ['created_at', 'updated_at', 'deleted_at'])) {
378
            return 'datetime';
379
        }
380
        return $this->getField($fieldName, 'type');
381
    }
382
383
    /**
384
     * Sets the type of a field.
385
     *
386
     * @param string $fieldName
387
     * the field name
388
     * @param string $value
389
     * the new field type
390
     */
391
    public function setType($fieldName, $value) {
392
        $this->setField($fieldName, 'type', $value);
393
    }
394
395
    /**
396
     * Gets the label of a field.
397
     *
398
     * @param string $fieldName
399
     * the field name
400
     *
401
     * @return string
402
     * the label of the field or the field name if no label is set in the CRUD
403
     * YAML
404
     */
405
    public function getFieldLabel($fieldName) {
406
407
        $result = $this->getField($fieldName, 'label_'.$this->locale, $this->getField($fieldName, 'label'));
408
409
        if ($result === null && array_key_exists($fieldName, $this->standardFieldLabels)) {
410
            $result = $this->standardFieldLabels[$fieldName];
411
        }
412
413
        if ($result === null) {
414
            $result = $fieldName;
415
        }
416
417
        return $result;
418
    }
419
420
    /**
421
     * Gets the label of a field.
422
     *
423
     * @param string $fieldName
424
     * the field name
425
     * @param string $value
426
     * the new label of the field
427
     */
428
    public function setFieldLabel($fieldName, $value) {
429
        $this->setField($fieldName, 'label', $value);
430
    }
431
432
    /**
433
     * Gets the table where the data is stored.
434
     *
435
     * @return string
436
     * the table where the data is stored
437
     */
438
    public function getTable() {
439
        return $this->table;
440
    }
441
442
    /**
443
     * Sets the table where the data is stored.
444
     *
445
     * @param string $table
446
     * the new table where the data is stored
447
     */
448
    public function setTable($table) {
449
        $this->table = $table;
450
    }
451
452
    /**
453
     * Gets the label for the entity.
454
     *
455
     * @return string
456
     * the label for the entity
457
     */
458
    public function getLabel() {
459
        if ($this->locale && array_key_exists($this->locale, $this->localeLabels)) {
460
            return $this->localeLabels[$this->locale];
461
        }
462
        return $this->label;
463
    }
464
465
    /**
466
     * Sets the label for the entity.
467
     *
468
     * @param string $label
469
     * the new label for the entity
470
     */
471
    public function setLabel($label) {
472
        $this->label = $label;
473
    }
474
475
    /**
476
     * Adds a child to this definition in case the other
477
     * definition has a reference to this one.
478
     *
479
     * @param string $table
480
     * the table of the referencing definition
481
     * @param string $fieldName
482
     * the field name of the referencing definition
483
     * @param string $entity
484
     * the entity of the referencing definition
485
     */
486
    public function addChild($table, $fieldName, $entity) {
487
        $this->children[] = [$table, $fieldName, $entity];
488
    }
489
490
    /**
491
     * Gets the referencing children to this definition.
492
     *
493
     * @return array
494
     * an array with the children referencing the entity. All entries are arrays
495
     * with three referencing elements: table, fieldName, entity
496
     */
497
    public function getChildren() {
498
        return $this->children;
499
    }
500
501
    /**
502
     * Sets the locale to be used.
503
     *
504
     * @param string $locale
505
     * the locale to be used.
506
     */
507
    public function setLocale($locale) {
508
        $this->locale = $locale;
509
    }
510
511
    /**
512
     * Gets the locale to be used.
513
     *
514
     * @return null|string
515
     * the locale to be used.
516
     */
517
    public function getLocale() {
518
        return $this->locale;
519
    }
520
521
    /**
522
     * Sets the initial sort field.
523
     *
524
     * @param string $initialSortField
525
     * the new initial sort field
526
     */
527
    public function setInitialSortField($initialSortField) {
528
        $this->initialSortField = $initialSortField;
529
    }
530
531
    /**
532
     * Gets the initial sort field.
533
     *
534
     * @return string
535
     * the initial sort field
536
     */
537
    public function getInitialSortField() {
538
        return $this->initialSortField;
539
    }
540
541
    /**
542
     * Sets the initial sort order.
543
     *
544
     * @param boolean $initialSortAscending
545
     * the initial sort order, true if ascending
546
     */
547
    public function setInitialSortAscending($initialSortAscending) {
548
        $this->initialSortAscending = $initialSortAscending;
549
    }
550
551
    /**
552
     * Gets the initial sort order.
553
     *
554
     * @return boolean
555
     * the initial sort order, true if ascending
556
     */
557
    public function isInitialSortAscending() {
558
        return $this->initialSortAscending;
559
    }
560
561
    /**
562
     * Gets a sub field of an field.
563
     *
564
     * @param string $fieldName
565
     * the field name of the sub type
566
     * @param string $subType
567
     * the sub type like "reference" or "many"
568
     * @param string $key
569
     * the key of the value
570
     *
571
     * @return string
572
     * the value of the sub field
573
     */
574
    public function getSubTypeField($fieldName, $subType, $key) {
575
576
        if (!isset($this->fields[$fieldName][$subType][$key])) {
577
            return null;
578
        }
579
580
        return $this->fields[$fieldName][$subType][$key];
581
    }
582
583
    /**
584
     * Gets the value of a field key.
585
     *
586
     * @param string $name
587
     * the name of the field
588
     * @param string $key
589
     * the value of the key
590
     * @param mixed $default
591
     * the default value to return if nothing is found
592
     *
593
     * @return mixed
594
     * the value of the field key or null if not existing
595
     */
596
    public function getField($name, $key, $default = null) {
597
        if (array_key_exists($name, $this->fields) && array_key_exists($key, $this->fields[$name])) {
598
            return $this->fields[$name][$key];
599
        }
600
        return $default;
601
    }
602
603
    /**
604
     * Sets the value of a field key. If the field or the key in the field
605
     * don't exist, they get created.
606
     *
607
     * @param string $name
608
     * the name of the field
609
     * @param string $key
610
     * the value of the key
611
     * @param mixed $value
612
     * the new value
613
     */
614
    public function setField($name, $key, $value) {
615
        if (!array_key_exists($name, $this->fields)) {
616
            $this->fields[$name] = [];
617
        }
618
        $this->fields[$name][$key] = $value;
619
    }
620
621
}
622