Passed
Push — master ( 295f25...8b0a88 )
by
unknown
36:25 queued 21:17
created

TypoScriptTemplateObjectBrowserModuleFunctionController   D

Complexity

Total Complexity 59

Size/Duplication

Total Lines 396
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 59
eloc 220
c 2
b 0
f 0
dl 0
loc 396
rs 4.08

8 Methods

Rating   Name   Duplication   Size   Complexity  
A modMenu() 0 42 5
A initialize_editor() 0 14 1
A init() 0 10 1
A getLanguageService() 0 3 1
A getBackendUserAuthentication() 0 3 1
A addFlashMessage() 0 5 1
A getPageRenderer() 0 3 1
F main() 0 235 48

How to fix   Complexity   

Complex Class

Complex classes like TypoScriptTemplateObjectBrowserModuleFunctionController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TypoScriptTemplateObjectBrowserModuleFunctionController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Tstemplate\Controller;
17
18
use Psr\Http\Message\ServerRequestInterface;
19
use TYPO3\CMS\Backend\Routing\UriBuilder;
20
use TYPO3\CMS\Backend\Utility\BackendUtility;
21
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
22
use TYPO3\CMS\Core\DataHandling\DataHandler;
23
use TYPO3\CMS\Core\Exception;
24
use TYPO3\CMS\Core\Localization\LanguageService;
25
use TYPO3\CMS\Core\Messaging\FlashMessage;
26
use TYPO3\CMS\Core\Messaging\FlashMessageService;
27
use TYPO3\CMS\Core\Page\PageRenderer;
28
use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
29
use TYPO3\CMS\Core\Utility\GeneralUtility;
30
use TYPO3\CMS\Core\Utility\RootlineUtility;
31
use TYPO3\CMS\Fluid\View\StandaloneView;
32
33
/**
34
 * This class displays the submodule "TypoScript Object Browser" inside the Web > Template module
35
 * @internal This is a specific Backend Controller implementation and is not considered part of the Public TYPO3 API.
36
 */
37
class TypoScriptTemplateObjectBrowserModuleFunctionController
38
{
39
    /**
40
     * @var TypoScriptTemplateModuleController
41
     */
42
    protected $pObj;
43
44
    /**
45
     * The currently selected sys_template record
46
     * @var array|null
47
     */
48
    protected $templateRow;
49
50
    /**
51
     * @var ExtendedTemplateService
52
     */
53
    protected $templateService;
54
55
    /**
56
     * @var int GET/POST var 'id'
57
     */
58
    protected $id;
59
60
    /**
61
     * @var ServerRequestInterface
62
     */
63
    protected $request;
64
65
    /**
66
     * Init, called from parent object
67
     *
68
     * @param TypoScriptTemplateModuleController $pObj
69
     * @param ServerRequestInterface $request
70
     */
71
    public function init($pObj, ServerRequestInterface $request)
72
    {
73
        $this->pObj = $pObj;
74
        $this->request = $request;
75
76
        // Setting MOD_MENU items as we need them for logging:
77
        $this->pObj->MOD_MENU = array_merge($this->pObj->MOD_MENU, $this->modMenu());
78
        $this->pObj->modMenu_dontValidateList .= ',ts_browser_toplevel_setup,ts_browser_toplevel_const,ts_browser_TLKeys_setup,ts_browser_TLKeys_const';
79
        $this->pObj->modMenu_setDefaultList .= ',ts_browser_showComments';
80
        $this->id = (int)($request->getParsedBody()['id'] ?? $request->getQueryParams()['id'] ?? 0);
81
    }
82
83
    /**
84
     * Mod menu
85
     *
86
     * @return array
87
     */
88
    protected function modMenu()
89
    {
90
        $lang = $this->getLanguageService();
91
        $lang->includeLLFile('EXT:tstemplate/Resources/Private/Language/locallang_objbrowser.xlf');
92
        $modMenu = [
93
            'ts_browser_type' => [
94
                'const' => $lang->getLL('constants'),
95
                'setup' => $lang->getLL('setup')
96
            ],
97
            'ts_browser_toplevel_setup' => [
98
                '0' => mb_strtolower($lang->getLL('all'), 'utf-8')
99
            ],
100
            'ts_browser_toplevel_const' => [
101
                '0' => mb_strtolower($lang->getLL('all'), 'utf-8')
102
            ],
103
            'ts_browser_const' => [
104
                '0' => $lang->getLL('plainSubstitution'),
105
                'subst' => $lang->getLL('substitutedGreen'),
106
                'const' => $lang->getLL('unsubstitutedGreen')
107
            ],
108
            'ts_browser_regexsearch' => '1',
109
            'ts_browser_showComments' => '1',
110
            'ts_browser_alphaSort' => '1'
111
        ];
112
        foreach (['setup', 'const'] as $bType) {
113
            $addKey = $this->request->getQueryParams()['addKey'] ?? null;
114
            // If any plus-signs were clicked, it's registered.
115
            if (is_array($addKey)) {
116
                reset($addKey);
117
                if (current($addKey)) {
118
                    $this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][key($addKey)] = key($addKey);
119
                } else {
120
                    unset($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][key($addKey)]);
121
                }
122
                $this->getBackendUserAuthentication()->pushModuleData('web_ts', $this->pObj->MOD_SETTINGS);
123
            }
124
            if (!empty($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType])) {
125
                $modMenu['ts_browser_toplevel_' . $bType]['-'] = '---';
126
                $modMenu['ts_browser_toplevel_' . $bType] = $modMenu['ts_browser_toplevel_' . $bType] + $this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType];
127
            }
128
        }
129
        return $modMenu;
130
    }
131
132
    /**
133
     * Initialize editor
134
     *
135
     * Initializes the module. Done in this function because we may need to re-initialize if data is submitted!
136
     *
137
     * @param int $pageId
138
     * @param int $template_uid
139
     * @return bool
140
     */
141
    protected function initialize_editor($pageId, $template_uid = 0)
142
    {
143
        // Defined global here!
144
        $this->templateService = GeneralUtility::makeInstance(ExtendedTemplateService::class);
145
146
        // Gets the rootLine
147
        $rootlineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $pageId);
148
        $rootLine = $rootlineUtility->get();
149
        // This generates the constants/config + hierarchy info for the template.
150
        $this->templateService->runThroughTemplates($rootLine, $template_uid);
151
152
        // Get the row of the first VISIBLE template of the page. whereclause like the frontend.
153
        $this->templateRow = $this->templateService->ext_getFirstTemplate($pageId, $template_uid);
154
        return is_array($this->templateRow);
155
    }
156
157
    /**
158
     * Main, called from parent object
159
     *
160
     * @return string
161
     */
162
    public function main()
163
    {
164
        $lang = $this->getLanguageService();
165
        $POST = $this->request->getParsedBody();
166
        // Checking for more than one template an if, set a menu...
167
        $manyTemplatesMenu = $this->pObj->templateMenu($this->request);
168
        $template_uid = 0;
169
        if ($manyTemplatesMenu) {
170
            $template_uid = $this->pObj->MOD_SETTINGS['templatesOnPage'];
171
        }
172
        $bType = $this->pObj->MOD_SETTINGS['ts_browser_type'];
173
        $existTemplate = $this->initialize_editor($this->id, $template_uid);
174
        // initialize
175
        $assigns = [];
176
        $assigns['existTemplate'] = $existTemplate;
177
        $assigns['tsBrowserType'] = $this->pObj->MOD_SETTINGS['ts_browser_type'];
178
        if ($existTemplate) {
179
            $assigns['templateRecord'] = $this->templateRow;
180
            $assigns['linkWrapTemplateTitle'] = $this->pObj->linkWrapTemplateTitle($this->templateRow['title'], ($bType === 'setup' ? 'config' : 'constants'));
181
            $assigns['manyTemplatesMenu'] = $manyTemplatesMenu;
182
183
            if (($POST['add_property'] ?? false) || ($POST['update_value'] ?? false) || ($POST['clear_object'] ?? false)) {
184
                // add property
185
                $line = '';
186
                if (is_array($POST['data'])) {
187
                    $name = key($POST['data']);
188
                    if (($POST['data'][$name]['name'] ?? null) !== '') {
189
                        // Workaround for this special case: User adds a key and submits by pressing the return key. The form however will use "add_property" which is the name of the first submit button in this form.
190
                        unset($POST['update_value']);
191
                        $POST['add_property'] = 'Add';
192
                    }
193
                    if ($POST['add_property'] ?? false) {
194
                        $property = trim($POST['data'][$name]['name']);
195
                        if (preg_replace('/[^a-zA-Z0-9_\\.]*/', '', $property) != $property) {
196
                            $badPropertyMessage = GeneralUtility::makeInstance(FlashMessage::class, $lang->getLL('noSpaces') . $lang->getLL('nothingUpdated'), $lang->getLL('badProperty'), FlashMessage::ERROR);
197
                            $this->addFlashMessage($badPropertyMessage);
198
                        } else {
199
                            $pline = $name . '.' . $property . ' = ' . trim($POST['data'][$name]['propertyValue']);
200
                            $propertyAddedMessage = GeneralUtility::makeInstance(FlashMessage::class, $pline, $lang->getLL('propertyAdded'));
201
                            $this->addFlashMessage($propertyAddedMessage);
202
                            $line .= LF . $pline;
203
                        }
204
                    } elseif ($POST['update_value'] ?? false) {
205
                        $pline = $name . ' = ' . trim($POST['data'][$name]['value']);
206
                        $updatedMessage = GeneralUtility::makeInstance(FlashMessage::class, $pline, $lang->getLL('valueUpdated'));
207
                        $this->addFlashMessage($updatedMessage);
208
                        $line .= LF . $pline;
209
                    } elseif ($POST['clear_object'] ?? false) {
210
                        if ($POST['data'][$name]['clearValue'] ?? false) {
211
                            $pline = $name . ' >';
212
                            $objectClearedMessage = GeneralUtility::makeInstance(FlashMessage::class, $pline, $lang->getLL('objectCleared'));
213
                            $this->addFlashMessage($objectClearedMessage);
214
                            $line .= LF . $pline;
215
                        }
216
                    }
217
                }
218
                if ($line) {
219
                    $saveId = ($this->templateRow['_ORIG_uid'] ?? false) ?: $this->templateRow['uid'] ?? 0;
220
                    // Set the data to be saved
221
                    $recData = [];
222
                    $field = $bType === 'setup' ? 'config' : 'constants';
223
                    $recData['sys_template'][$saveId][$field] = $this->templateRow[$field] . $line;
224
                    // Create new  tce-object
225
                    $tce = GeneralUtility::makeInstance(DataHandler::class);
226
                    // Initialize
227
                    $tce->start($recData, []);
228
                    // Saved the stuff
229
                    $tce->process_datamap();
230
                    // re-read the template ...
231
                    $this->initialize_editor($this->id, $template_uid);
232
                }
233
            }
234
        }
235
        $tsbr = $this->request->getQueryParams()['tsbr'] ?? null;
236
        $update = 0;
237
        if (is_array($tsbr)) {
238
            // If any plus-signs were clicked, it's registered.
239
            $this->pObj->MOD_SETTINGS['tsbrowser_depthKeys_' . $bType] = $this->templateService->ext_depthKeys($tsbr, $this->pObj->MOD_SETTINGS['tsbrowser_depthKeys_' . $bType] ?? []);
240
            $update = 1;
241
        }
242
        if ($POST['Submit'] ?? false) {
243
            // If any POST-vars are send, update the condition array
244
            $this->pObj->MOD_SETTINGS['tsbrowser_conditions'] = $POST['conditions'];
245
            $update = 1;
246
        }
247
        if ($update) {
248
            $this->getBackendUserAuthentication()->pushModuleData('web_ts', $this->pObj->MOD_SETTINGS);
249
        }
250
        $this->templateService->matchAlternative = $this->pObj->MOD_SETTINGS['tsbrowser_conditions'] ?? [];
251
        $this->templateService->matchAlternative[] = 'dummydummydummydummydummydummydummydummydummydummydummy';
252
        // This is just here to make sure that at least one element is in the array so that the tsparser actually uses this array to match.
253
        $this->templateService->constantMode = $this->pObj->MOD_SETTINGS['ts_browser_const'];
254
        // "sObj" is set by ExtendedTemplateService to edit single keys
255
        $sObj = $this->request->getParsedBody()['sObj'] ?? $this->request->getQueryParams()['sObj'] ?? null;
256
        if (!empty($sObj) && $this->templateService->constantMode) {
257
            $this->templateService->constantMode = 'untouched';
258
        }
259
        $this->templateService->regexMode = $this->pObj->MOD_SETTINGS['ts_browser_regexsearch'] ?? '';
260
        $this->templateService->linkObjects = true;
261
        $this->templateService->ext_regLinenumbers = true;
262
        $this->templateService->ext_regComments = $this->pObj->MOD_SETTINGS['ts_browser_showComments'];
263
        $this->templateService->bType = $bType;
264
        $this->templateService->generateConfig();
265
        if ($bType === 'setup') {
266
            $theSetup = $this->templateService->setup;
267
        } else {
268
            $theSetup = $this->templateService->setup_constants;
269
        }
270
        // EDIT A VALUE:
271
        $assigns['typoScriptPath'] = $sObj;
272
        if (!empty($sObj)) {
273
            [$theSetup, $theSetupValue] = $this->templateService->ext_getSetup($theSetup, $sObj);
274
            $assigns['theSetupValue'] = $theSetupValue;
275
            if ($existTemplate === false) {
276
                $noTemplateMessage = GeneralUtility::makeInstance(FlashMessage::class, $lang->getLL('noCurrentTemplate'), $lang->getLL('edit'), FlashMessage::ERROR);
277
                $this->addFlashMessage($noTemplateMessage);
278
            }
279
            // Links:
280
            $urlParameters = [
281
                'id' => $this->id
282
            ];
283
            /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
284
            $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
285
            $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
286
            $assigns['moduleUrl'] = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
287
            $assigns['isNotInTopLevelKeyList'] = !isset($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$sObj]);
288
            $assigns['hasProperties'] = !empty($theSetup);
289
            if ($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$sObj] ?? false) {
290
                $assigns['moduleUrlObjectListAction'] = $aHref . '&addKey[' . rawurlencode($sObj) . ']=0&SET[ts_browser_toplevel_' . $bType . ']=0';
291
            } else {
292
                if (!empty($theSetup)) {
293
                    $assigns['moduleUrlObjectListAction'] = $aHref . '&addKey[' . rawurlencode($sObj) . ']=1&SET[ts_browser_toplevel_' . $bType . ']=' . rawurlencode($sObj);
294
                }
295
            }
296
        } else {
297
            $this->templateService->tsbrowser_depthKeys = $this->pObj->MOD_SETTINGS['tsbrowser_depthKeys_' . $bType] ?? null;
298
            if ($this->request->getParsedBody()['search_field'] ?? false) {
299
                // If any POST-vars are send, update the condition array
300
                $searchString = $this->request->getParsedBody()['search_field'];
301
                try {
302
                    $this->templateService->tsbrowser_depthKeys =
303
                        $this->templateService->ext_getSearchKeys(
304
                            $theSetup,
305
                            '',
306
                            $searchString,
307
                            []
308
                        );
309
                } catch (Exception $e) {
310
                    $this->addFlashMessage(
311
                        GeneralUtility::makeInstance(FlashMessage::class, sprintf($lang->getLL('error.' . $e->getCode()), $searchString), '', FlashMessage::ERROR)
312
                    );
313
                }
314
            }
315
            $assigns['hasTsBrowserTypes'] = is_array($this->pObj->MOD_MENU['ts_browser_type'] ?? false) && count($this->pObj->MOD_MENU['ts_browser_type']) > 1;
316
            if (is_array($this->pObj->MOD_MENU['ts_browser_type']) && count($this->pObj->MOD_MENU['ts_browser_type']) > 1) {
317
                $assigns['browserTypeDropdownMenu'] = BackendUtility::getDropdownMenu($this->id, 'SET[ts_browser_type]', $bType, $this->pObj->MOD_MENU['ts_browser_type']);
318
            }
319
            $assigns['hasTopLevelInObjectList'] = is_array($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType] ?? false) && count($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) > 1;
320
            if (is_array($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) && count($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) > 1) {
321
                $assigns['objectListDropdownMenu'] = BackendUtility::getDropdownMenu($this->id, 'SET[ts_browser_toplevel_' . $bType . ']', $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType], $this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]);
322
            }
323
324
            $assigns['regexSearchCheckbox'] = BackendUtility::getFuncCheck($this->id, 'SET[ts_browser_regexsearch]', $this->pObj->MOD_SETTINGS['ts_browser_regexsearch'] ?? false, '', '', 'id="checkTs_browser_regexsearch"');
325
            $assigns['postSearchField'] = $POST['search_field'] ?? null;
326
            $theKey = $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType] ?? '';
327
            if (!$theKey || !str_replace('-', '', $theKey)) {
328
                $theKey = '';
329
            }
330
            [$theSetup, $theSetupValue] = $this->templateService->ext_getSetup($theSetup, $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType] ?? '');
331
            $tree = $this->templateService->ext_getObjTree($theSetup, $theKey, '', '', $theSetupValue, $this->pObj->MOD_SETTINGS['ts_browser_alphaSort'] ?? '');
332
            $tree = $this->templateService->substituteCMarkers($tree);
333
            $urlParameters = [
334
                'id' => $this->id
335
            ];
336
            /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
337
            $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
338
            $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
339
            // Parser Errors:
340
            $pEkey = $bType === 'setup' ? 'config' : 'constants';
341
            $assigns['hasParseErrors'] = !empty($this->templateService->parserErrors[$pEkey]);
342
            if (!empty($this->templateService->parserErrors[$pEkey])) {
343
                $assigns['showErrorDetailsUri'] = $aHref . '&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\TemplateAnalyzerModuleFunctionController&highlightType=' . $bType . '&highlightLine=';
344
                $assigns['parseErrors'] = $this->templateService->parserErrors[$pEkey];
345
            }
346
347
            if (isset($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$theKey])) {
348
                $assigns['moduleUrlRemoveFromObjectList'] = $aHref . '&addKey[' . $theKey . ']=0&SET[ts_browser_toplevel_' . $bType . ']=0';
349
            }
350
351
            $assigns['hasKeySelected'] = $theKey !== '';
352
353
            if ($theKey) {
354
                $assigns['treeLabel'] = $theKey;
355
            } else {
356
                $assigns['rootLLKey'] = $bType === 'setup' ? 'setupRoot' : 'constantRoot';
357
            }
358
            $assigns['tsTree'] = $tree;
359
360
            // second row options
361
            $assigns['isSetupAndCropLinesDisabled'] = $bType === 'setup';
362
            $assigns['checkBoxShowComments'] = BackendUtility::getFuncCheck($this->id, 'SET[ts_browser_showComments]', $this->pObj->MOD_SETTINGS['ts_browser_showComments'] ?? '', '', '', 'id="checkTs_browser_showComments"');
363
            $assigns['checkBoxAlphaSort'] = BackendUtility::getFuncCheck($this->id, 'SET[ts_browser_alphaSort]', $this->pObj->MOD_SETTINGS['ts_browser_alphaSort'] ?? '', '', '', 'id="checkTs_browser_alphaSort"');
364
            if ($bType === 'setup') {
365
                $assigns['dropdownDisplayConstants'] = BackendUtility::getDropdownMenu($this->id, 'SET[ts_browser_const]', $this->pObj->MOD_SETTINGS['ts_browser_const'] ?? '', $this->pObj->MOD_MENU['ts_browser_const']);
366
            }
367
368
            // Conditions:
369
            $assigns['hasConditions'] = is_array($this->templateService->sections) && !empty($this->templateService->sections);
370
            $activeConditions = 0;
371
            if (is_array($this->templateService->sections) && !empty($this->templateService->sections)) {
372
                $tsConditions = [];
373
                foreach ($this->templateService->sections as $key => $val) {
374
                    $isSet = (bool)($this->pObj->MOD_SETTINGS['tsbrowser_conditions'][$key] ?? false);
375
                    if ($isSet) {
376
                        $activeConditions++;
377
                    }
378
379
                    $tsConditions[] = [
380
                        'key' => $key,
381
                        'value' => $val,
382
                        'label' => $this->templateService->substituteCMarkers(htmlspecialchars($val)),
383
                        'isSet' => $isSet
384
                    ];
385
                }
386
                $assigns['tsConditions'] = $tsConditions;
387
            }
388
            $assigns['activeConditions'] = $activeConditions;
389
            // Ending section displayoptions
390
        }
391
        $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip');
392
        $view = GeneralUtility::makeInstance(StandaloneView::class);
393
        $view->setTemplatePathAndFilename('EXT:tstemplate/Resources/Private/Templates/TemplateObjectBrowserModuleFunction.html');
394
        $view->assignMultiple($assigns);
395
396
        return $view->render();
397
    }
398
399
    /**
400
     * Add flash message to queue
401
     *
402
     * @param FlashMessage $flashMessage
403
     */
404
    protected function addFlashMessage(FlashMessage $flashMessage)
405
    {
406
        $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
407
        $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
408
        $defaultFlashMessageQueue->enqueue($flashMessage);
409
    }
410
411
    /**
412
     * @return LanguageService
413
     */
414
    protected function getLanguageService(): LanguageService
415
    {
416
        return $GLOBALS['LANG'];
417
    }
418
419
    /**
420
     * @return BackendUserAuthentication
421
     */
422
    protected function getBackendUserAuthentication(): BackendUserAuthentication
423
    {
424
        return $GLOBALS['BE_USER'];
425
    }
426
427
    /**
428
     * @return PageRenderer
429
     */
430
    protected function getPageRenderer(): PageRenderer
431
    {
432
        return GeneralUtility::makeInstance(PageRenderer::class);
433
    }
434
}
435