Passed
Pull Request — master (#54)
by Romain
03:56
created

EntityTcaWriter::getDefaultCtrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 17
nc 1
nop 0
dl 0
loc 22
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * Copyright (C) 2018
5
 * Nathan Boiron <[email protected]>
6
 * Romain Canon <[email protected]>
7
 *
8
 * This file is part of the TYPO3 NotiZ project.
9
 * It is free software; you can redistribute it and/or modify it
10
 * under the terms of the GNU General Public License, either
11
 * version 3 of the License, or any later version.
12
 *
13
 * For the full copyright and license information, see:
14
 * http://www.gnu.org/licenses/gpl-3.0.html
15
 */
16
17
namespace CuyZ\Notiz\Core\Notification\TCA;
18
19
use CuyZ\Notiz\Core\Notification\Service\LegacyNotificationTcaService;
20
use CuyZ\Notiz\Core\Notification\Service\NotificationTcaService;
21
use CuyZ\Notiz\Service\Traits\SelfInstantiateTrait;
22
use TYPO3\CMS\Core\SingletonInterface;
23
use TYPO3\CMS\Core\Utility\ArrayUtility;
24
use TYPO3\CMS\Core\Utility\GeneralUtility;
25
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
26
27
abstract class EntityTcaWriter implements SingletonInterface
28
{
29
    use SelfInstantiateTrait;
30
31
    const LLL_FIELDS = 'LLL:EXT:notiz/Resources/Private/Language/Notification/Entity/Fields.xlf';
32
    const LLL_TABS = 'LLL:EXT:notiz/Resources/Private/Language/Notification/Entity/Tabs.xlf';
33
34
    /**
35
     * Contains the name of the TCA table.
36
     *
37
     * @var string
38
     */
39
    protected $tableName;
40
41
    /**
42
     * @var NotificationTcaService
43
     */
44
    protected $service;
45
46
    /**
47
     * @var array
48
     */
49
    private $data = [];
50
51
    /**
52
     * Manual injection for the TCA service depending on the entity type.
53
     */
54
    public function __construct()
55
    {
56
        $this->service = GeneralUtility::makeInstance($this->getNotificationTcaServiceClass());
57
    }
58
59
    /**
60
     * This method must create the basic TCA configuration. It must fill at
61
     * least the `ctrl` and `columns` sections.
62
     *
63
     * Default TYPO3 columns are added automatically, so no need to add them.
64
     * Common notifications columns are also added automatically.
65
     *
66
     * @return array
67
     */
68
    abstract protected function buildTcaArray();
69
70
    /**
71
     * This method builds a TCA array and returns it to be used in a
72
     * configuration file.
73
     *
74
     * @param string $tableName
75
     * @return array
76
     */
77
    final public function getTcaArray($tableName)
78
    {
79
        $this->tableName = $tableName;
80
81
        if ($this->service->definitionHasErrors()) {
82
            // If the definition contains errors, we only show a message.
83
            $this->data = $this->getDefinitionErrorTca();
84
        } else {
85
            // Each sub-class starts to fill the array.
86
            $this->data = $this->buildTcaArray();
87
88
            // Some columns are common for all notification types
89
            $this->addCommonColumns();
90
91
            // The default columns are always the same.
92
            $this->addDefaultTypo3Columns();
93
        }
94
95
        // This hides all fields if the definition has any error.
96
        $this->addDisplayConditionToFields();
97
98
        return $this->data;
99
    }
100
101
    /**
102
     * This method returns the TCA service class for the current entity type.
103
     * You can override it to return a class extending `NotificationTcaService`.
104
     *
105
     * @return string
106
     */
107
    abstract protected function getNotificationTcaServiceClass();
108
109
    /**
110
     * This method returns the LLL string to use for the `channel` column.
111
     *
112
     * @return string
113
     */
114
    protected function getChannelLabel()
115
    {
116
        return self::LLL_FIELDS . ':field.channel';
117
    }
118
119
    /**
120
     * Returns the TCA array for the event configuration. It is a FlexForm field
121
     * with as many definitions as there are events using FlexForm.
122
     *
123
     * @return array
124
     */
125
    private function getEventConfiguration()
126
    {
127
        if ($this->service->definitionHasErrors()) {
128
            return [];
129
        }
130
131
        $configuration = [];
132
        $displayConditions = [];
133
134
        foreach ($this->service->getDefinition()->getEvents() as $event) {
135
            $provider = $event->getConfiguration()->getFlexFormProvider();
136
137
            if ($provider->hasFlexForm()) {
138
                $identifier = $event->getFullIdentifier();
139
140
                $configuration[$identifier] = $provider->getFlexFormValue();
141
                $displayConditions[] = $identifier;
142
            }
143
        }
144
145
        if (empty($configuration)) {
146
            return ['config' => ['type' => 'passthrough']];
147
        }
148
149
        $configuration['default'] = 'FILE:EXT:notiz/Configuration/FlexForm/Event/DefaultEventFlexForm.xml';
150
151
        return [
152
            'label' => self::LLL_FIELDS . ':field.event_configuration',
153
            'displayCond' => version_compare(VersionNumberUtility::getCurrentTypo3Version(), '8.0.0', '<')
154
                ? 'USER:' . LegacyNotificationTcaService::class . '->displayEventFlexForm:' . $this->tableName . ':' . implode(',', $displayConditions)
155
                : 'FIELD:event:IN:' . implode(',', $displayConditions),
156
            'config' => [
157
                'type' => 'flex',
158
                'ds_pointerField' => 'event',
159
                'ds' => $configuration,
160
                'behaviour' => [
161
                    'allowLanguageSynchronization' => true,
162
                ],
163
            ],
164
        ];
165
    }
166
167
    /**
168
     * This will add display condition to all fields in the TCA array: if there
169
     * exists at least one error in the definition tree, the fields are hidden
170
     * and an error message is shown.
171
     */
172
    private function addDisplayConditionToFields()
173
    {
174
        $condition = 'USER:' . NotificationTcaService::class . '->definitionContainsErrors';
175
176
        foreach ($this->data['columns'] as $key => $column) {
177
            if ($key === 'error_message') {
178
                continue;
179
            }
180
181
            if (isset($column['displayCond'])) {
182
                if (isset($column['displayCond']['AND'])) {
183
                    $this->data['columns'][$key]['displayCond']['AND'][] = $condition;
184
                } else {
185
                    $this->data['columns'][$key]['displayCond'] = [
186
                        'AND' => [
187
                            $condition,
188
                            $column['displayCond'],
189
                        ]
190
                    ];
191
                }
192
            } else {
193
                $this->data['columns'][$key]['displayCond'] = $condition;
194
            }
195
        }
196
    }
197
198
    /**
199
     * @return array
200
     */
201
    protected function getDefaultCtrl()
202
    {
203
        return [
204
            'label' => 'title',
205
            'tstamp' => 'tstamp',
206
            'crdate' => 'crdate',
207
            'cruser_id' => 'cruser_id',
208
            'dividers2tabs' => true,
209
210
            'requestUpdate' => 'event',
211
212
            'languageField' => 'sys_language_uid',
213
            'transOrigPointerField' => 'l10n_parent',
214
            'transOrigDiffSourceField' => 'l10n_diffsource',
215
            'delete' => 'deleted',
216
            'enablecolumns' => [
217
                'disabled' => 'hidden',
218
                'starttime' => 'starttime',
219
                'endtime' => 'endtime',
220
            ],
221
            'searchFields' => 'title,event',
222
            'iconfile' => $this->service->getNotificationIconPath()
223
        ];
224
    }
225
226
    /**
227
     * Returns the default TYPO3 columns to include in the final TCA array.
228
     */
229
    private function addDefaultTypo3Columns()
230
    {
231
        $defaultColumns = [
232
            'sys_language_uid' => [
233
                'exclude' => 1,
234
                'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.language',
235
                'config' => [
236
                    'type' => 'select',
237
                    'foreign_table' => 'sys_language',
238
                    'foreign_table_where' => 'ORDER BY sys_language.title',
239
                    'items' => [
240
                        ['LLL:EXT:lang/locallang_general.xlf:LGL.allLanguages', -1],
241
                        ['LLL:EXT:lang/locallang_general.xlf:LGL.default_value', 0]
242
                    ]
243
                ]
244
            ],
245
            'l10n_parent' => [
246
                'displayCond' => 'FIELD:sys_language_uid:>:0',
247
                'exclude' => 1,
248
                'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.l18n_parent',
249
                'l10n_display' => 'defaultAsReadonly',
250
                'config' => [
251
                    'type' => 'select',
252
                    'foreign_table' => $this->tableName,
253
                    'foreign_table_where' => "AND {$this->tableName}.pid=###CURRENT_PID### AND {$this->tableName}.sys_language_uid IN (-1,0)",
254
                    'items' => [
255
                        ['', 0]
256
                    ]
257
                ]
258
            ],
259
            'l10n_diffsource' => [
260
                'config' => [
261
                    'type' => 'passthrough'
262
                ]
263
            ],
264
            't3ver_label' => [
265
                'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.versionLabel',
266
                'config' => [
267
                    'type' => 'input',
268
                    'size' => 30,
269
                    'max' => 255
270
                ]
271
            ],
272
            'hidden' => [
273
                'exclude' => 1,
274
                'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.hidden',
275
                'config' => [
276
                    'type' => 'check'
277
                ]
278
            ],
279
            'starttime' => [
280
                'exclude' => 1,
281
                'l10n_mode' => 'mergeIfNotBlank',
282
                'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.starttime',
283
                'config' => [
284
                    'type' => 'input',
285
                    'size' => 13,
286
                    'max' => 20,
287
                    'eval' => 'datetime',
288
                    'checkbox' => 0,
289
                    'default' => 0,
290
                    'range' => [
291
                        'lower' => mktime(0, 0, 0, (int)date('m'), (int)date('d'), (int)date('Y'))
292
                    ]
293
                ]
294
            ],
295
            'endtime' => [
296
                'exclude' => 1,
297
                'l10n_mode' => 'mergeIfNotBlank',
298
                'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.endtime',
299
                'config' => [
300
                    'type' => 'input',
301
                    'size' => 13,
302
                    'max' => 20,
303
                    'eval' => 'datetime',
304
                    'checkbox' => 0,
305
                    'default' => 0,
306
                    'range' => [
307
                        'lower' => mktime(0, 0, 0, (int)date('m'), (int)date('d'), (int)date('Y'))
308
                    ]
309
                ]
310
            ],
311
        ];
312
313
        ArrayUtility::mergeRecursiveWithOverrule(
314
            $this->data['columns'],
315
            $defaultColumns
316
        );
317
    }
318
319
    /**
320
     * This method adds the common columns used by all Entity Notifications.
321
     */
322
    private function addCommonColumns()
323
    {
324
        $commonColumns = [
325
            'error_message' => $this->getErrorMessageColumn(),
326
327
            'title' => [
328
                'exclude' => 1,
329
                'label' => self::LLL_FIELDS . ":field.title",
330
                'config' => [
331
                    'type' => 'input',
332
                    'size' => 30,
333
                    'eval' => 'trim,required',
334
                ],
335
            ],
336
337
            // Event configuration
338
339
            'event' => [
340
                'exclude' => 1,
341
                'label' => self::LLL_FIELDS . ":field.event",
342
                'l10n_mode' => 'exclude',
343
                'l10n_display' => 'defaultAsReadonly',
344
                'config' => [
345
                    'type' => 'select',
346
                    'renderType' => 'selectSingle',
347
                    'size' => 8,
348
                    'itemsProcFunc' => NotificationTcaService::class . '->getEventsList',
349
                    'eval' => 'required',
350
                ],
351
            ],
352
353
            'event_configuration_flex' => $this->getEventConfiguration(),
354
355
            // Channel configuration
356
357
            'channel' => [
358
                'exclude' => 1,
359
                'label' => $this->getChannelLabel(),
360
                'l10n_mode' => 'exclude',
361
                'l10n_display' => 'defaultAsReadonly',
362
                'config' => [
363
                    'type' => 'select',
364
                    'renderType' => 'selectSingle',
365
                    'itemsProcFunc' => $this->getNotificationTcaServiceClass() . '->getChannelsList',
366
                    'eval' => 'required',
367
                ],
368
            ],
369
370
            // Markers configuration
371
372
            'markers' => [
373
                'exclude' => 1,
374
                'label' => self::LLL_FIELDS . ":field.markers",
375
                'l10n_display' => 'defaultAsReadonly',
376
                'config' => [
377
                    'type' => 'user',
378
                    'userFunc' => NotificationTcaService::class . '->getMarkersLabel',
379
                ]
380
            ],
381
        ];
382
383
        ArrayUtility::mergeRecursiveWithOverrule(
384
            $this->data['columns'],
385
            $commonColumns
386
        );
387
    }
388
389
    /**
390
     * @return array
391
     */
392
    private function getDefinitionErrorTca()
393
    {
394
        return [
395
            'ctrl' => $this->getDefaultCtrl(),
396
            'types' => [
397
                '0' => [
398
                    'showitem' => 'error_message'
399
                ]
400
            ],
401
            'columns' => [
402
                'error_message' => $this->getErrorMessageColumn(),
403
                'title' => [
404
                    'config' => [
405
                        'type' => 'passthrough',
406
                    ],
407
                ],
408
            ]
409
        ];
410
    }
411
412
    /**
413
     * @return array
414
     */
415
    private function getErrorMessageColumn()
416
    {
417
        return [
418
            'displayCond' => 'USER:' . NotificationTcaService::class . '->definitionContainsErrors:inverted',
419
            'config' => [
420
                'type' => 'user',
421
                'userFunc' => NotificationTcaService::class . '->getErrorMessage',
422
            ],
423
        ];
424
    }
425
}
426