Completed
Push — master ( d8b95b...caeb59 )
by Axel
09:34 queued 04:32
created

ConfigController::configAction()   F

Complexity

Conditions 31
Paths > 20000

Size

Total Lines 193
Code Lines 118

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 31
eloc 118
c 0
b 0
f 0
nc 61443
nop 7
dl 0
loc 193
rs 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula - https://ziku.la/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Zikula\SecurityCenterModule\Controller;
15
16
use HTMLPurifier;
17
use HTMLPurifier_Config;
18
use HTMLPurifier_VarParser;
19
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
20
use Symfony\Component\Filesystem\Filesystem;
21
use Symfony\Component\HttpFoundation\RedirectResponse;
22
use Symfony\Component\HttpFoundation\Request;
23
use Symfony\Component\Routing\Annotation\Route;
24
use Symfony\Component\Routing\RouterInterface;
25
use Zikula\Bundle\CoreBundle\CacheClearer;
26
use Zikula\Bundle\CoreBundle\Configurator;
27
use Zikula\Bundle\CoreBundle\Controller\AbstractController;
28
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaKernel;
29
use Zikula\ExtensionsModule\Api\ApiInterface\VariableApiInterface;
30
use Zikula\ExtensionsModule\Api\VariableApi;
31
use Zikula\PermissionsModule\Annotation\PermissionCheck;
32
use Zikula\SecurityCenterModule\Constant;
33
use Zikula\SecurityCenterModule\Form\Type\ConfigType;
34
use Zikula\SecurityCenterModule\Helper\HtmlTagsHelper;
35
use Zikula\SecurityCenterModule\Helper\PurifierHelper;
36
use Zikula\SecurityCenterModule\ZikulaSecurityCenterModule;
37
use Zikula\ThemeModule\Engine\Annotation\Theme;
38
use Zikula\UsersModule\Helper\AccessHelper;
39
40
/**
41
 * Class ConfigController
42
 *
43
 * @Route("/config")
44
 * @PermissionCheck("admin")
45
 */
46
class ConfigController extends AbstractController
47
{
48
    /**
49
     * @Route("/config")
50
     * @Theme("admin")
51
     * @Template("@ZikulaSecurityCenterModule/Config/config.html.twig")
52
     *
53
     * @return array|RedirectResponse
54
     */
55
    public function config(
56
        ZikulaSecurityCenterModule $securityCenterModule,
57
        Request $request,
58
        RouterInterface $router,
59
        VariableApiInterface $variableApi,
60
        CacheClearer $cacheClearer,
61
        AccessHelper $accessHelper,
62
        string $projectDir
63
    ) {
64
        $modVars = $variableApi->getAll(VariableApi::CONFIG);
65
66
        $sessionName = $this->getParameter('zikula.session.name');
67
        $modVars['sessionname'] = $sessionName;
68
        $modVars['idshtmlfields'] = implode(PHP_EOL, $modVars['idshtmlfields']);
69
        $modVars['idsjsonfields'] = implode(PHP_EOL, $modVars['idsjsonfields']);
70
        $modVars['idsexceptions'] = implode(PHP_EOL, $modVars['idsexceptions']);
71
72
        $form = $this->createForm(ConfigType::class, $modVars);
73
        $form->handleRequest($request);
74
        if ($form->isSubmitted() && $form->isValid()) {
75
            if ($form->get('save')->isClicked()) {
0 ignored issues
show
Bug introduced by
The method isClicked() does not exist on Symfony\Component\Form\FormInterface. It seems like you code against a sub-type of Symfony\Component\Form\FormInterface such as Symfony\Component\Form\SubmitButton. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

75
            if ($form->get('save')->/** @scrutinizer ignore-call */ isClicked()) {
Loading history...
76
                $formData = $form->getData();
77
78
                $updateCheck = $formData['updatecheck'] ?? 1;
79
                $variableApi->set(VariableApi::CONFIG, 'updatecheck', $updateCheck);
80
                if (0 === $updateCheck) {
81
                    // if update checks are disabled, reset values to force new update check if re-enabled
82
                    $variableApi->set(VariableApi::CONFIG, 'updateversion', ZikulaKernel::VERSION);
83
                    $variableApi->set(VariableApi::CONFIG, 'updatelastchecked', 0);
84
                }
85
                $variableApi->set(VariableApi::CONFIG, 'updatefrequency', $formData['updatefrequency'] ?? 7);
86
87
                $variableApi->set(VariableApi::CONFIG, 'seclevel', $formData['seclevel'] ?? 'Medium');
88
89
                $secMedDays = $formData['secmeddays'] ?? 7;
90
                if ($secMedDays < 1 || $secMedDays > 365) {
91
                    $secMedDays = 7;
92
                }
93
                $variableApi->set(VariableApi::CONFIG, 'secmeddays', $secMedDays);
94
95
                $secInactiveMinutes = $formData['secinactivemins'] ?? 20;
96
                if ($secInactiveMinutes < 1 || $secInactiveMinutes > 1440) {
97
                    $secInactiveMinutes = 7;
98
                }
99
                $variableApi->set(VariableApi::CONFIG, 'secinactivemins', $secInactiveMinutes);
100
101
                $sessionStoreToFile = $formData['sessionstoretofile'] ?? 0;
102
                $sessionSavePath = $formData['sessionsavepath'] ?? '';
103
104
                // check session path config is writable (if method is being changed to session file storage)
105
                $causeLogout = false;
106
                $storeTypeCanBeWritten = true;
107
                if (1 === $sessionStoreToFile && !empty($sessionSavePath)) {
108
                    // fix path on windows systems
109
                    $sessionSavePath = str_replace('\\', '/', $sessionSavePath);
110
                    // sanitize the path
111
                    $sessionSavePath = trim(stripslashes($sessionSavePath));
112
113
                    // check if sessionsavepath is a dir and if it is writable
114
                    // if yes, we need to logout
115
                    $storeTypeCanBeWritten = is_dir($sessionSavePath) ? is_writable($sessionSavePath) : false;
116
                    $causeLogout = $storeTypeCanBeWritten;
117
118
                    if (false === $storeTypeCanBeWritten) {
119
                        // an error occured - we do not change the way of storing session data
120
                        $this->addFlash('error', 'Error! Session path not writeable!');
121
                        $sessionSavePath = '';
122
                    }
123
                }
124
                if (true === $storeTypeCanBeWritten) {
125
                    $variableApi->set(VariableApi::CONFIG, 'sessionstoretofile', $sessionStoreToFile);
126
                    $variableApi->set(VariableApi::CONFIG, 'sessionsavepath', $sessionSavePath);
127
                }
128
129
                if ((bool)$sessionStoreToFile !== (bool)$variableApi->getSystemVar('sessionstoretofile')) {
130
                    // logout if going from one storage to another one
131
                    $causeLogout = true;
132
                }
133
134
                $newSessionName = $formData['sessionname'] ?? $sessionName;
135
                if (mb_strlen($newSessionName) < 3) {
136
                    $newSessionName = $sessionName;
137
                }
138
139
                // cause logout if we changed session name
140
                if ($newSessionName !== $modVars['sessionname']) {
141
                    $causeLogout = true;
142
                }
143
144
                $configurator = new Configurator($projectDir);
145
                $configurator->loadPackages('zikula_security_center');
146
                $sessionConfig = $configurator->get('zikula_security_center', 'session');
147
                $sessionConfig['name'] = $newSessionName;
148
                $sessionConfig['handler_id'] = Constant::SESSION_STORAGE_FILE === $sessionStoreToFile ? 'session.handler.native_file' : 'zikula_core.bridge.http_foundation.doctrine_session_handler';
149
                $sessionConfig['storage_id'] = Constant::SESSION_STORAGE_FILE === $sessionStoreToFile ? 'zikula_core.bridge.http_foundation.zikula_session_storage_file' : 'zikula_core.bridge.http_foundation.zikula_session_storage_doctrine';
150
                $sessionConfig['save_path'] = empty($sessionSavePath) ? '%kernel.cache_dir%/sessions' : $sessionSavePath;
151
                $configurator->set('zikula_security_center', 'session', $sessionConfig);
152
                $configurator->write();
153
154
                $variableApi->set(VariableApi::CONFIG, 'sessionname', $newSessionName);
155
                $variableApi->set(VariableApi::CONFIG, 'sessionstoretofile', $sessionStoreToFile);
156
157
                $variableApi->set(VariableApi::CONFIG, 'outputfilter', $formData['outputfilter'] ?? 1);
158
159
                $useIds = $formData['useids'] ?? 0;
160
                $variableApi->set(VariableApi::CONFIG, 'useids', $useIds);
161
162
                // create tmp directory for PHPIDS
163
                if (1 === $useIds) {
164
                    $idsTmpDir = $this->getParameter('kernel.cache_dir') . '/idsTmp';
165
                    $fs = new Filesystem();
166
                    if (!$fs->exists($idsTmpDir)) {
167
                        $fs->mkdir($idsTmpDir);
168
                    }
169
                }
170
171
                $variableApi->set(VariableApi::CONFIG, 'idssoftblock', $formData['idssoftblock'] ?? 1);
172
                $variableApi->set(VariableApi::CONFIG, 'idsmail', $formData['idsmail'] ?? 0);
173
                $variableApi->set(VariableApi::CONFIG, 'idsfilter', $formData['idsfilter'] ?? 'xml');
174
175
                $idsRulePath = $formData['idsrulepath'] ?? 'Resources/config/phpids_zikula_default.xml';
176
                if (is_readable($securityCenterModule->getPath() . '/' . $idsRulePath)) {
177
                    $variableApi->set(VariableApi::CONFIG, 'idsrulepath', $idsRulePath);
178
                } else {
179
                    $this->addFlash('error', $this->trans('Error! PHPIDS rule file %filePath% does not exist or is not readable.', ['%filePath%' => $idsRulePath]));
180
                }
181
182
                $variableApi->set(VariableApi::CONFIG, 'idsimpactthresholdone', $formData['idsimpactthresholdone'] ?? 1);
183
                $variableApi->set(VariableApi::CONFIG, 'idsimpactthresholdtwo', $formData['idsimpactthresholdtwo'] ?? 10);
184
                $variableApi->set(VariableApi::CONFIG, 'idsimpactthresholdthree', $formData['idsimpactthresholdthree'] ?? 25);
185
                $variableApi->set(VariableApi::CONFIG, 'idsimpactthresholdfour', $formData['idsimpactthresholdfour'] ?? 75);
186
187
                $variableApi->set(VariableApi::CONFIG, 'idsimpactmode', $formData['idsimpactmode'] ?? 1);
188
189
                $idsHtmlFields = $formData['idshtmlfields'] ?? '';
190
                $idsHtmlFields = explode(PHP_EOL, $idsHtmlFields);
191
                $idsHtmlArray = [];
192
                foreach ($idsHtmlFields as $idsHtmlField) {
193
                    $idsHtmlField = trim($idsHtmlField);
194
                    if (!empty($idsHtmlField)) {
195
                        $idsHtmlArray[] = $idsHtmlField;
196
                    }
197
                }
198
                $variableApi->set(VariableApi::CONFIG, 'idshtmlfields', $idsHtmlArray);
199
200
                $idsJsonFields = $formData['idsjsonfields'] ?? '';
201
                $idsJsonFields = explode(PHP_EOL, $idsJsonFields);
202
                $idsJsonArray = [];
203
                foreach ($idsJsonFields as $idsJsonField) {
204
                    $idsJsonField = trim($idsJsonField);
205
                    if (!empty($idsJsonField)) {
206
                        $idsJsonArray[] = $idsJsonField;
207
                    }
208
                }
209
                $variableApi->set(VariableApi::CONFIG, 'idsjsonfields', $idsJsonArray);
210
211
                $idsExceptions = $formData['idsexceptions'] ?? '';
212
                $idsExceptions = explode(PHP_EOL, $idsExceptions);
213
                $idsExceptionsArray = [];
214
                foreach ($idsExceptions as $idsException) {
215
                    $idsException = trim($idsException);
216
                    if (!empty($idsException)) {
217
                        $idsExceptionsArray[] = $idsException;
218
                    }
219
                }
220
                $variableApi->set(VariableApi::CONFIG, 'idsexceptions', $idsExceptionsArray);
221
222
                $variableApi->set(VariableApi::CONFIG, 'idscachingtype', $formData['idscachingtype'] ?? 'none');
223
                $variableApi->set(VariableApi::CONFIG, 'idscachingexpiration', $formData['idscachingexpiration'] ?? 600);
224
225
                // clear cache
226
                $cacheClearer->clear('symfony');
227
228
                // the module configuration has been updated successfuly
229
                $this->addFlash('status', 'Done! Configuration updated.');
230
231
                // we need to auto logout the user if essential session settings have been changed
232
                if (true === $causeLogout) {
233
                    $accessHelper->logout();
234
                    $this->addFlash('status', 'Session handling variables have changed. You must log in again.');
235
                    $returnPage = urlencode($router->generate('zikulasecuritycentermodule_config_config'));
236
237
                    return $this->redirectToRoute('zikulausersmodule_access_login', ['returnUrl' => $returnPage]);
238
                }
239
            } elseif ($form->get('cancel')->isClicked()) {
240
                $this->addFlash('status', 'Operation cancelled.');
241
            }
242
243
            return $this->redirectToRoute('zikulasecuritycentermodule_config_config');
244
        }
245
246
        return [
247
            'form' => $form->createView()
248
        ];
249
    }
250
251
    /**
252
     * @Route("/purifierconfig/{reset}")
253
     * @Theme("admin")
254
     * @Template("@ZikulaSecurityCenterModule/Config/purifierconfig.html.twig")
255
     *
256
     * HTMLPurifier configuration.
257
     *
258
     * @return array|RedirectResponse
259
     */
260
    public function purifierconfig(
261
        Request $request,
262
        PurifierHelper $purifierHelper,
263
        CacheClearer $cacheClearer,
264
        string $reset = null
265
    ) {
266
        if (Request::METHOD_POST === $request->getMethod()) {
267
            // Load HTMLPurifier Classes
268
            $purifier = $purifierHelper->getPurifier();
269
270
            // Update module variables.
271
            $config = $request->request->get('purifierConfig');
272
            $config = HTMLPurifier_Config::prepareArrayFromForm($config, false, true, true, $purifier->config->def);
273
274
            $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm(true, $purifier->config->def);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type array expected by parameter $allowed of HTMLPurifier_Config::getAllowedDirectivesForForm(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

274
            $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm(/** @scrutinizer ignore-type */ true, $purifier->config->def);
Loading history...
275
            foreach ($allowed as [$namespace, $directive]) {
276
                $directiveKey = $namespace . '.' . $directive;
277
                $def = $purifier->config->def->info[$directiveKey];
278
279
                if (isset($config[$namespace])
280
                        && array_key_exists($directive, $config[$namespace])
281
                        && null === $config[$namespace][$directive]) {
282
                    unset($config[$namespace][$directive]);
283
284
                    if (count($config[$namespace]) <= 0) {
285
                        unset($config[$namespace]);
286
                    }
287
                }
288
289
                if (isset($config[$namespace][$directive])) {
290
                    if (is_int($def)) {
291
                        $directiveType = abs($def);
292
                    } else {
293
                        $directiveType = $def->type ?? 0;
294
                    }
295
296
                    switch ($directiveType) {
297
                        case HTMLPurifier_VarParser::LOOKUP:
298
                            $value = explode(PHP_EOL, $config[$namespace][$directive]);
299
                            $config[$namespace][$directive] = [];
300
                            foreach ($value as $val) {
301
                                $val = trim($val);
302
                                if (!empty($val)) {
303
                                    $config[$namespace][$directive][$val] = true;
304
                                }
305
                            }
306
                            if (empty($config[$namespace][$directive])) {
307
                                unset($config[$namespace][$directive]);
308
                            }
309
                            break;
310
                        case HTMLPurifier_VarParser::ALIST:
311
                            $value = explode(PHP_EOL, $config[$namespace][$directive]);
312
                            $config[$namespace][$directive] = [];
313
                            foreach ($value as $val) {
314
                                $val = trim($val);
315
                                if (!empty($val)) {
316
                                    $config[$namespace][$directive][] = $val;
317
                                }
318
                            }
319
                            if (empty($config[$namespace][$directive])) {
320
                                unset($config[$namespace][$directive]);
321
                            }
322
                            break;
323
                        case HTMLPurifier_VarParser::HASH:
324
                            $value = explode(PHP_EOL, $config[$namespace][$directive]);
325
                            $config[$namespace][$directive] = [];
326
                            foreach ($value as $val) {
327
                                [$i, $v] = explode(':', $val);
328
                                $i = trim($i);
329
                                $v = trim($v);
330
                                if (!empty($i) && !empty($v)) {
331
                                    $config[$namespace][$directive][$i] = $v;
332
                                }
333
                            }
334
                            if (empty($config[$namespace][$directive])) {
335
                                unset($config[$namespace][$directive]);
336
                            }
337
                            break;
338
                    }
339
                }
340
341
                if (isset($config[$namespace])
342
                        && array_key_exists($directive, $config[$namespace])
343
                        && null === $config[$namespace][$directive]) {
344
                    unset($config[$namespace][$directive]);
345
346
                    if (count($config[$namespace]) <= 0) {
347
                        unset($config[$namespace]);
348
                    }
349
                }
350
            }
351
352
            $this->setVar('htmlpurifierConfig', serialize($config));
353
354
            // clear all cache and compile directories
355
            $cacheClearer->clear('symfony');
356
            $cacheClearer->clear('legacy');
357
358
            // the module configuration has been updated successfuly
359
            $this->addFlash('status', 'Done! Saved HTMLPurifier configuration.');
360
361
            return $this->redirectToRoute('zikulasecuritycentermodule_config_purifierconfig');
362
        }
363
364
        // load the configuration page
365
366
        if (isset($reset) && 'default' === $reset) {
367
            $purifierConfig = $purifierHelper->getPurifierConfig(['forcedefault' => true]);
368
            $this->addFlash('status', 'Default values for HTML Purifier were successfully loaded. Please store them using the "Save" button at the bottom of this page');
369
        } else {
370
            $purifierConfig = $purifierHelper->getPurifierConfig(['forcedefault' => false]);
371
        }
372
373
        $purifier = new HTMLPurifier($purifierConfig);
374
375
        $config = $purifier->config;
376
377
        if (is_array($config) && isset($config[0])) {
0 ignored issues
show
introduced by
The condition is_array($config) is always false.
Loading history...
378
            $config = $config[1];
379
        }
380
381
        $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm(true, $config->def);
382
383
        // list of excluded directives, format is $namespace_$directive
384
        $excluded = ['Cache_SerializerPath'];
385
386
        // Editing for only these types is supported
387
        $editableTypes = [
388
            HTMLPurifier_VarParser::C_STRING,
389
            HTMLPurifier_VarParser::ISTRING,
390
            HTMLPurifier_VarParser::TEXT,
391
            HTMLPurifier_VarParser::ITEXT,
392
            HTMLPurifier_VarParser::C_INT,
393
            HTMLPurifier_VarParser::C_FLOAT,
394
            HTMLPurifier_VarParser::C_BOOL,
395
            HTMLPurifier_VarParser::LOOKUP,
396
            HTMLPurifier_VarParser::ALIST,
397
            HTMLPurifier_VarParser::HASH
398
        ];
399
400
        $purifierAllowed = [];
401
        foreach ($allowed as [$namespace, $directive]) {
402
            if (in_array($namespace . '_' . $directive, $excluded, true)) {
403
                continue;
404
            }
405
406
            $directiveRec = [];
407
            $directiveRec['key'] = $namespace . '.' . $directive;
408
            $def = $config->def->info[$directiveRec['key']];
409
            $directiveRec['value'] = $config->get($directiveRec['key']);
410
            if (is_int($def)) {
411
                $directiveRec['allowNull'] = ($def < 0);
412
                $directiveRec['type'] = abs($def);
413
            } else {
414
                $directiveRec['allowNull'] = (isset($def->allow_null) && $def->allow_null);
415
                $directiveRec['type'] = ($def->type ?? 0);
416
                if (isset($def->allowed)) {
417
                    $directiveRec['allowedValues'] = [];
418
                    foreach ($def->allowed as $val => $b) {
419
                        $directiveRec['allowedValues'][] = $val;
420
                    }
421
                }
422
            }
423
            if (is_array($directiveRec['value'])) {
424
                switch ($directiveRec['type']) {
425
                    case HTMLPurifier_VarParser::LOOKUP:
426
                        $value = [];
427
                        foreach ($directiveRec['value'] as $val => $b) {
428
                            $value[] = $val;
429
                        }
430
                        $directiveRec['value'] = implode(PHP_EOL, $value);
431
                        break;
432
                    case HTMLPurifier_VarParser::ALIST:
433
                        $directiveRec['value'] = implode(PHP_EOL, $directiveRec['value']);
434
                        break;
435
                    case HTMLPurifier_VarParser::HASH:
436
                        $directiveRec['value'] = json_encode($directiveRec['value']);
437
                        break;
438
                    default:
439
                        $directiveRec['value'] = '';
440
                }
441
            }
442
443
            $directiveRec['supported'] = in_array($directiveRec['type'], $editableTypes, true);
444
445
            $purifierAllowed[$namespace][$directive] = $directiveRec;
446
        }
447
448
        return [
449
            'purifier' => $purifier,
450
            'purifierTypes' => HTMLPurifier_VarParser::$types,
451
            'purifierAllowed' => $purifierAllowed
452
        ];
453
    }
454
455
    /**
456
     * @Route("/allowedhtml")
457
     * @Theme("admin")
458
     * @Template("@ZikulaSecurityCenterModule/Config/allowedhtml.html.twig")
459
     *
460
     * Display the allowed html form.
461
     *
462
     * @return array|RedirectResponse
463
     */
464
    public function allowedhtml(
465
        Request $request,
466
        RouterInterface $router,
467
        VariableApiInterface $variableApi,
468
        CacheClearer $cacheClearer,
469
        HtmlTagsHelper $htmlTagsHelper
470
    ) {
471
        $htmlTags = $htmlTagsHelper->getTagsWithLinks();
472
473
        if (Request::METHOD_POST === $request->getMethod()) {
474
            $htmlEntities = $request->request->getInt('htmlentities', 0);
475
            $variableApi->set(VariableApi::CONFIG, 'htmlentities', $htmlEntities);
476
477
            // update the allowed html settings
478
            $allowedHtml = [];
479
            foreach ($htmlTags as $htmlTag => $usageTag) {
480
                $tagVal = $request->request->getInt('htmlallow' . $htmlTag . 'tag', 0);
481
                if (1 !== $tagVal && 2 !== $tagVal) {
482
                    $tagVal = 0;
483
                }
484
                $allowedHtml[$htmlTag] = $tagVal;
485
            }
486
487
            $variableApi->set(VariableApi::CONFIG, 'AllowableHTML', $allowedHtml);
488
489
            // clear all cache and compile directories
490
            $cacheClearer->clear('symfony');
491
            $cacheClearer->clear('legacy');
492
493
            $this->addFlash('status', 'Done! Configuration updated.');
494
495
            return $this->redirectToRoute('zikulasecuritycentermodule_config_allowedhtml');
496
        }
497
498
        return [
499
            'htmlEntities' => $variableApi->getSystemVar('htmlentities'),
500
            'htmlPurifier' => 1 === $variableApi->getSystemVar('outputfilter'),
501
            'configUrl' => $router->generate('zikulasecuritycentermodule_config_config'),
502
            'htmlTags' => $htmlTags,
503
            'currentHtmlTags' => $variableApi->getSystemVar('AllowableHTML')
504
        ];
505
    }
506
}
507