Config.php 22.6 KB
Newer Older
1
2
3
4
5
6
7
8
<?php
/**
 * Created by PhpStorm.
 * User: crose
 * Date: 3/6/17
 * Time: 8:47 PM
 */

Marc Egger's avatar
Marc Egger committed
9
namespace IMATHUZH\Qfq\Core\Store;
10

11
use IMATHUZH\Qfq\Core\Exception\Thrower;
12
use IMATHUZH\Qfq\Core\Helper\HelperFile;
Marc Egger's avatar
Marc Egger committed
13
use IMATHUZH\Qfq\Core\Helper\Logger;
14
use IMATHUZH\Qfq\Core\Helper\OnArray;
15
use IMATHUZH\Qfq\Core\Helper\OnString;
16
use IMATHUZH\Qfq\Core\Helper\Path;
Marc Egger's avatar
Marc Egger committed
17
use IMATHUZH\Qfq\Core\Helper\Support;
18

19
20
21
22
/**
 * Class Config
 * @package qfq
 */
23
24
class Config {

25
26
    private static $config = null;

Marc Egger's avatar
Marc Egger committed
27
28
29
30
    const CONFIG_REQUIRED_TEMPLATE = [
        SYSTEM_DB_1_USER => null,
        SYSTEM_DB_1_PASSWORD => null,
        SYSTEM_DB_1_SERVER => "localhost",
31
        SYSTEM_DB_1_NAME => null,
Marc Egger's avatar
Marc Egger committed
32
    ];
33

34
35
36
37
38
    /**
     * Get config value with given key. Throws exception if config has not been read.
     *
     * @param string $key
     * @return mixed
39
     * @throws \CodeException
40
     * @throws \UserFormException
41
     * @throws \UserReportException
42
     */
43
    public static function get(string $key) {
44
        self::readConfig(); // only reads once
45
        return self::$config[$key] ?? null;
46
47
48
49
50
    }

    /**
     * Returns a copy of the config array. Throws exception if config has not been read.
     *
51
     * @param string $PhpUnitOverloadAbsoluteConfigFilePath
52
     * @return array
53
     * @throws \CodeException
54
     * @throws \UserFormException
55
     * @throws \UserReportException
56
     */
57
58
    public static function getConfigArray($PhpUnitOverloadAbsoluteConfigFilePath = ''): array {
        self::readConfig($PhpUnitOverloadAbsoluteConfigFilePath); // only reads once, except if argument !=''
59
60
61
62
        return self::$config;
    }

    /**
Marc Egger's avatar
Marc Egger committed
63
     * Read qfq.json (merge with Typo3-qfq config if exists).
64
     * Note: Deprecated config file typo3conf/config.qfq.php is translated to JSON in PATH:findAppToProject(..)
65
     *
66
     * @param string $PhpUnitOverloadAbsoluteConfigFilePath
67
68
69
70
     * @throws \CodeException
     * @throws \UserFormException
     * @throws \UserReportException
     */
71
    private static function readConfig($PhpUnitOverloadAbsoluteConfigFilePath = '') {
72

73
        if (self::$config !== null && $PhpUnitOverloadAbsoluteConfigFilePath === '') {
74
            // only read once, except phpUnit
75
76
77
78
            return;
        }

        // read and parse config. Throw exception if not exists.
79
80
81
82
83
        $absoluteConfigFilePath = $PhpUnitOverloadAbsoluteConfigFilePath === '' ? Path::absoluteConf(CONFIG_QFQ_JSON) : $PhpUnitOverloadAbsoluteConfigFilePath;
        if (!file_exists($absoluteConfigFilePath)) {
            HelperFile::createPathRecursive(Path::absoluteConf());
            HelperFile::file_put_contents(Path::absoluteConf(CONFIG_QFQ_JSON_EXAMPLE), json_encode(self::CONFIG_REQUIRED_TEMPLATE, JSON_PRETTY_PRINT));
            Thrower::userFormException("Please create qfq config file '" . CONFIG_QFQ_JSON . "' in the conf directory which is inside the project directory. Example config file '" . CONFIG_QFQ_JSON_EXAMPLE . "' was created in conf directory.", "Project directory: " . Path::absoluteProject());
84
        }
85
        $config = HelperFile::json_decode(HelperFile::file_get_contents($absoluteConfigFilePath));
86
87
88
89

        // check required keys
        foreach (self::CONFIG_REQUIRED_TEMPLATE as $key => $value) {
            if (!array_key_exists($key, $config) || is_null($config[$key]) || $config[$key] === '') {
90
                Thrower::userFormException("Required key '$key' missing in config file " . CONFIG_QFQ_JSON, "Config file: $absoluteConfigFilePath");
91
92
93
            }
        }

94
        if ($PhpUnitOverloadAbsoluteConfigFilePath === '') {
Marc Egger's avatar
Marc Egger committed
95
            $configT3qfq = self::readTypo3QfqConfig();
96
97
98
99
100
101
102
103
104
105
106
107
108

            // Settings in qfq.json overwrite T3 settings
            $config = array_merge($configT3qfq, $config);
        }

        $config = self::renameConfigElements($config);
        $config = self::setDefaults($config);
        self::checkDeprecated($config);
        self::checkForAttack($config);

        // Copy values to detect custom settings later
        $config[F_FE_DATA_PATTERN_ERROR_SYSTEM] = $config[F_FE_DATA_PATTERN_ERROR];

109
110
111
112
113
        $config = self::adjustConfig($config);
        $config = self::setAutoConfigValue($config);

        self::checkMandatoryParameter($config);

114
115
116
117
118
119
        self::$config = $config;

        // Set log paths
        Path::overrideLogPathsFromConfig();
    }

120
121
122
123
124
    /**
     * Iterates over all 30 custom vars, explode them to split between key and value, append to $config.
     *
     * @param array $config
     * @return array
Marc Egger's avatar
Marc Egger committed
125
     * @throws \UserReportException
126
     */
127
    private static function getCustomVariable(array $config) {
128
129
130
131
132
133

        for ($i = 1; $i <= 30; $i++) {
            if (isset($config['custom' . $i])) {
                $arr = explode('=', $config['custom' . $i], 2);
                if (!empty($arr[0]) && !empty($arr[1])) {

134
                    $arr[0] = trim($arr[0]);
135
                    $arr[1] = OnString::trimQuote(trim($arr[1]));
136
137

                    if (isset($config[$arr[0]])) {
Marc Egger's avatar
Marc Egger committed
138
                        throw new \UserReportException("Variable '$arr[0]' already defined", ERROR_INVALID_OR_MISSING_PARAMETER);
139
140
141
142
143
144
145
146
147
148
                    }

                    $config[$arr[0]] = $arr[1];
                }
            }
        }

        return $config;
    }

149
    /**
150
     * Overwrite the qfq config file with data from given array.
151
152
153
     *
     * @param array $config
     * @throws \UserFormException
154
     * @throws \CodeException
155
     */
156
    private static function writeConfig(array $config) {
157
158
159
        $absoluteConf = Path::absoluteConf();
        HelperFile::createPathRecursive($absoluteConf);
        HelperFile::file_put_contents(Path::join($absoluteConf, CONFIG_QFQ_JSON), json_encode($config, JSON_PRETTY_PRINT));
160
161
    }

162
    /**
163
164
165
166
167
     * Replace typo3conf/config.qfq.php with fileadmin/protected/qfqProject/qfq.json
     *
     * @throws \CodeException
     * @throws \UserFormException
     */
168
    public static function migrateConfigPhpToJson(): void {
169
        // read old config.qfq.php
170
171
        $absoluteOldConfigFilePath = Path::absoluteApp(Path::APP_TO_TYPO3_CONF, CONFIG_QFQ_PHP);
        if (!is_writeable($absoluteOldConfigFilePath)) {
172
173
            throw new \UserFormException(json_encode([
                ERROR_MESSAGE_TO_USER => "Can't migrate to new config: Legacy config file `config.qfq.php` not writable.",
174
                ERROR_MESSAGE_TO_DEVELOPER => "Can't write to file/directory '$absoluteOldConfigFilePath'"]));
175
        }
176
        $config = include($absoluteOldConfigFilePath);
177

178
179
180
181
182
183
        // In case the database credentials are given in the old style: rename the keys
        $config = OnArray::renameKeys([
            SYSTEM_DB_USER => SYSTEM_DB_1_USER,
            SYSTEM_DB_SERVER => SYSTEM_DB_1_SERVER,
            SYSTEM_DB_PASSWORD => SYSTEM_DB_1_PASSWORD,
            SYSTEM_DB_NAME => SYSTEM_DB_1_NAME
184
        ], $config);
185

186
187
188
189
        // write new qfq.config.json
        self::writeConfig($config);

        // remove old
190
        HelperFile::unlink($absoluteOldConfigFilePath);
191
192
    }

193
194
195
196
197
198
199
200
    /**
     * Read Typo3-QFQ config first from global variable, then from typo3conf/Localconfig.php.
     * If both not exist, return empty array.
     *
     * @return array Empty if config not found.
     * @throws \UserFormException
     * @throws \UserReportException
     */
201
    private static function readTypo3QfqConfig(): array {
202
        $configT3qfq = array();
Marc Egger's avatar
Marc Egger committed
203
        if (isset($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS'][EXT_KEY])) {
204
            // Typo3 version >=9
Marc Egger's avatar
Marc Egger committed
205
206
207
208
209
            $configT3qfq = $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS'][EXT_KEY];
            $configT3qfq[SYSTEM_DB_NAME_T3] = self::getDbName($GLOBALS['TYPO3_CONF_VARS']['DB']);

        } elseif (isset($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][EXT_KEY])) {
            // Typo3 version <=8
210
211
212
            $configT3qfq = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][EXT_KEY]);
            $configT3qfq[SYSTEM_DB_NAME_T3] = self::getDbName($GLOBALS['TYPO3_CONF_VARS']['DB']);

213
214
215
        } elseif (is_readable(Path::absoluteApp(Path::APP_TO_TYPO3_CONF, CONFIG_T3))) {
            $absoluteTypo3ConfigFile = Path::absoluteApp(Path::APP_TO_TYPO3_CONF, CONFIG_T3);
            $configT3 = HelperFile::include($absoluteTypo3ConfigFile);
Marc Egger's avatar
Marc Egger committed
216
            if (isset($configT3['EXTENSIONS'][EXT_KEY])) {
217
                // Typo3 version >=9
Marc Egger's avatar
Marc Egger committed
218
219
220
221
222
                $configT3qfq = $configT3['EXTENSIONS'][EXT_KEY];
            } else {
                // Typo3 version <=8
                $configT3qfq = unserialize($configT3['EXT']['extConf'][EXT_KEY]);
            }
223
            if (!is_array($configT3qfq)) {
224
                Thrower::userFormException('Error read file', "Error while reading qfq config from: $absoluteTypo3ConfigFile");
225
226
227
228
229
230
231
232
            }
            $configT3qfq[SYSTEM_DB_NAME_T3] = self::getDbName($configT3['DB']);
            unset($configT3);
        }
        $configT3qfq = self::getCustomVariable($configT3qfq);
        return $configT3qfq;
    }

233
234
235
236
237
238
    /**
     * Returns T3 DB-Name, depending on T3 version
     *
     * @param array $db
     * @return mixed
     */
Carsten  Rose's avatar
Carsten Rose committed
239
    private static function getDbName(array $db) {
240
241
242
243
244

        // T3 7.x: $GLOBALS['TYPO3_CONF_VARS']['DB']['database'],  T3 8.x: $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['dbname']
        return isset($db['database']) ? $db['database'] : $db['Connections']['Default']['dbname'];
    }

245
246
    /**
     * Checks for deprecated options.
247
     *
248
     * @param array $config
Marc Egger's avatar
Marc Egger committed
249
     * @throws \UserFormException
250
251
252
253
254
255
256
257
258
     */
    private static function checkDeprecated(array $config) {

        foreach ([SYSTEM_VAR_ADD_BY_SQL] as $key) {

            if (isset($config[$key])) {
                $msg = '';
                switch ($key) {
                    case SYSTEM_VAR_ADD_BY_SQL:
259
                        $msg = 'Replaced by: ' . SYSTEM_FILL_STORE_SYSTEM_BY_SQL . '1|2|3';
260
                }
Marc Egger's avatar
Marc Egger committed
261
                throw new \UserFormException ("Deprecated option in " . CONFIG_QFQ_PHP . ": " . SYSTEM_VAR_ADD_BY_SQL . " - " . $msg);
262
263
264
265
            }
        }
    }

266
    /**
267
268
     * Check for attack
     *
269
     * @param array $config
Marc Egger's avatar
Marc Egger committed
270
271
272
     * @throws \CodeException
     * @throws \UserFormException
     * @throws \UserReportException
273
     */
274
    public static function checkForAttack(array $config) {
275
        $attack = false;
276
        $key = '';
277
        $reason = 'Problem: ';
278
279
280
281

        // Iterate over all fake vars
        $arr = explode(',', $config[SYSTEM_SECURITY_VARS_HONEYPOT]);
        foreach ($arr as $key) {
282

283
284
285
286
            $key = trim($key);
            if ($key === '') {
                continue;
            }
287
288

            if (!empty($_POST[$key])) {
289
                $attack = true;
290
                $reason .= "Post/Get Honeypot variable '$key' detected: " . htmlentities($_POST[$key]) . PHP_EOL;
291
292
293
294
295
            }
        }

        // Limit length of all get vars: protect against SQL injection based on long ...%34%34%24%34...
        $maxLength = $config[SYSTEM_SECURITY_GET_MAX_LENGTH];
296
        if ($maxLength > 0 && $attack === false) {
297
            foreach ($_GET as $key => $value) {
Carsten  Rose's avatar
Carsten Rose committed
298
299
300
301
302

                if (!is_string($value)) {
                    continue;
                }

303
304
                // Check if the variable is something like 'my_name_100' - if the part after the last '_' is numerical, this means a valid, non standard length.
                $arr = explode(GET_EXTRA_LENGTH_TOKEN, $key);
305

306
307
                $cnt = count($arr);
                if ($cnt > 1 && is_numeric($arr[$cnt - 1])) {
308
309
310
311
312
                    $maxLength = $arr[$cnt - 1];
                } else {
                    $maxLength = $config[SYSTEM_SECURITY_GET_MAX_LENGTH]; // might change again.
                }

313
314
                $len = strlen($value);
                if ($len > $maxLength) {
315
                    $attack = true;
316
                    $reason .= "Value of GET variable '$key' too long. Allowed: $maxLength, Length: $len. Value: '" . htmlentities($_GET[$key]) . "'" . PHP_EOL;
317
                }
318
319
320
321
            }
        }

        // Nothing found?
322
        if ($attack === false) {
323
324
325
            return;
        }

326
        self::attackDetectedExitNow($config, $reason);
327
328
329
    }

    /**
330
     * @param array $config
331
     * @param string $reason
Marc Egger's avatar
Marc Egger committed
332
333
334
     * @throws \CodeException
     * @throws \UserFormException
     * @throws \UserReportException
335
     */
336
    public static function attackDetectedExitNow(array $config = array(), $reason = '') {
337
338

        if (count($config) == 0) {
339
            $config = self::getConfigArray();
340
341
        }

342
        Logger::logMessage(Logger::linePre() . 'Security: attack detected' . PHP_EOL . $reason, Path::absoluteQfqLogFile());
343

344
345
346
        // In case of an attack: log out the current user.
        Session::destroy();

347
348
349
350
        // Sleep
        $penalty = (empty($config[SYSTEM_SECURITY_ATTACK_DELAY]) || !is_numeric($config[SYSTEM_SECURITY_ATTACK_DELAY])) ?
            SYSTEM_SECURITY_ATTACK_DELAY_DEFAULT : $config[SYSTEM_SECURITY_ATTACK_DELAY];

Carsten  Rose's avatar
Carsten Rose committed
351
352
353
        if (!defined('PHPUNIT_QFQ')) {
            sleep($penalty);
        }
354

355
        if ($config[SYSTEM_SECURITY_SHOW_MESSAGE] == 'true' || $config[SYSTEM_SECURITY_SHOW_MESSAGE] == 1) {
356

357
            echo "Attack detected - stop process <p>" . $reason . '</p>';
358
359
360
361
362
363
364
//            $answer[API_STATUS] = API_ANSWER_STATUS_ERROR;
//            $answer[API_MESSAGE] = 'Attack detected - stop process.';
//            if($getParamName!='') {
//                $answer[API_MESSAGE] .= " Attack parameter: $getParamName";
//            }
//            header("Content-Type: application/json");
//            echo json_encode($answer);
365
366
        }

367
        if (defined('PHPUNIT_QFQ')) {
Marc Egger's avatar
Marc Egger committed
368
            throw new \UserFormException('Attack detected', 1);
369
370
        }

371
372
373
374
375
        exit;
    }

    /**
     * @param array $config
Carsten  Rose's avatar
Carsten Rose committed
376
     *
377
378
     * @return array
     */
379
    public static function setDefaults(array $config) {
380
381
382

        $default = [

383
            SYSTEM_DB_INIT => 'set names utf8',
384
385
            SYSTEM_DB_INDEX_DATA => DB_INDEX_DEFAULT,
            SYSTEM_DB_INDEX_QFQ => DB_INDEX_DEFAULT,
386

387
            SYSTEM_RENDER => SYSTEM_RENDER_SINGLE,
388
389
            SYSTEM_DATE_FORMAT => 'yyyy-mm-dd',
            SYSTEM_SHOW_DEBUG_INFO => SYSTEM_SHOW_DEBUG_INFO_AUTO,
390
            SYSTEM_REPORT_MIN_PHP_VERSION => SYSTEM_REPORT_MIN_PHP_VERSION_AUTO,
391
392
393
            SYSTEM_MAIL_LOG_PATHFILENAME => '',
            SYSTEM_QFQ_LOG_PATHFILENAME => '',
            SYSTEM_SQL_LOG_PATHFILENAME => '',
394
            SYSTEM_SQL_LOG_MODE => 'modify',
395
            SYSTEM_SQL_LOG_MODE_AUTOCRON => 'error',
396
397
398
399
            F_BS_COLUMNS => 'col-md-12 col-lg-10',
            F_BS_LABEL_COLUMNS => 'col-md-3 col-lg-3',
            F_BS_INPUT_COLUMNS => 'col-md-6 col-lg-6',
            F_BS_NOTE_COLUMNS => 'col-md-3 col-lg-3',
400

401
402
            F_CLASS => 'qfq-notify',

403
404
405
406
            F_CLASS_PILL => 'qfq-color-grey-1',
            F_CLASS_BODY => 'qfq-color-grey-2',

            F_SAVE_BUTTON_TEXT => '',
407
            F_SAVE_BUTTON_TOOLTIP => '',
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
            F_SAVE_BUTTON_CLASS => 'btn btn-default navbar-btn',
            F_SAVE_BUTTON_GLYPH_ICON => GLYPH_ICON_CHECK,

            F_CLOSE_BUTTON_TEXT => '',
            F_CLOSE_BUTTON_TOOLTIP => 'Close',
            F_CLOSE_BUTTON_CLASS => 'btn btn-default navbar-btn',
            F_CLOSE_BUTTON_GLYPH_ICON => GLYPH_ICON_CLOSE,

            F_DELETE_BUTTON_TEXT => '',
            F_DELETE_BUTTON_TOOLTIP => 'Delete',
            F_DELETE_BUTTON_CLASS => 'btn btn-default navbar-btn',
            F_DELETE_BUTTON_GLYPH_ICON => GLYPH_ICON_DELETE,

            F_NEW_BUTTON_TEXT => '',
            F_NEW_BUTTON_TOOLTIP => 'New',
            F_NEW_BUTTON_CLASS => 'btn btn-default navbar-btn',
            F_NEW_BUTTON_GLYPH_ICON => GLYPH_ICON_NEW,

            F_BUTTON_ON_CHANGE_CLASS => 'btn-info alert-info',
            SYSTEM_EDIT_FORM_PAGE => 'form',
428
            SYSTEM_SECURITY_VARS_HONEYPOT => SYSTEM_SECURITY_VARS_HONEYPOT_NAMES,
429
430
431
            SYSTEM_SECURITY_ATTACK_DELAY => SYSTEM_SECURITY_ATTACK_DELAY_DEFAULT,
            SYSTEM_SECURITY_SHOW_MESSAGE => '0',
            SYSTEM_SECURITY_GET_MAX_LENGTH => SYSTEM_SECURITY_GET_MAX_LENGTH_DEFAULT,
432
433
434

            SYSTEM_LABEL_ALIGN => SYSTEM_LABEL_ALIGN_LEFT,

435
            SYSTEM_ESCAPE_TYPE_DEFAULT => TOKEN_ESCAPE_MYSQL,
436
437
            SYSTEM_EXTRA_BUTTON_INFO_INLINE => '<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>',
            SYSTEM_EXTRA_BUTTON_INFO_BELOW => '<span class="glyphicon glyphicon-info-sign text-info" aria-hidden="true"></span>',
438
439
440
441
442
            SYSTEM_EXTRA_BUTTON_INFO_CLASS => '',

            SYSTEM_DB_UPDATE => SYSTEM_DB_UPDATE_AUTO,
            SYSTEM_RECORD_LOCK_TIMEOUT_SECONDS => SYSTEM_RECORD_LOCK_TIMEOUT_SECONDS_DEFAULT,

443
            SYSTEM_SESSION_TIMEOUT_SECONDS => Session::getPhpSessionTimeout(),
444

445
            SYSTEM_DOCUMENTATION_QFQ => SYSTEM_DOCUMENTATION_QFQ_URL,
446
447
            SYSTEM_ENTER_AS_SUBMIT => 1,

448
            SYSTEM_CMD_WKHTMLTOPDF => '/opt/wkhtmltox/bin/wkhtmltopdf',
449
450
            SYSTEM_CMD_INKSCAPE => 'inkscape',
            SYSTEM_CMD_CONVERT => 'convert',
451
452
            SYSTEM_CMD_PDF2SVG => 'pdf2svg',
            SYSTEM_CMD_PDFTOCAIRO => 'pdftocairo',
453
454
455
            SYSTEM_CMD_QPDF => 'qpdf',
            SYSTEM_CMD_GS => 'gs',
            SYSTEM_CMD_PDFUNITE => 'pdfunite',
456
            SYSTEM_CMD_IMG2PDF => 'img2pdf',
457
            SYSTEM_CMD_HEIF_CONVERT => 'heif-convert',
458

459
460
            SYSTEM_THUMBNAIL_DIR_SECURE_REL_TO_APP => Path::APP_TO_SYSTEM_THUMBNAIL_DIR_SECURE_DEFAULT,
            SYSTEM_THUMBNAIL_DIR_PUBLIC_REL_TO_APP => Path::APP_TO_SYSTEM_THUMBNAIL_DIR_PUBLIC_DEFAULT,
461

462
            F_FE_DATA_REQUIRED_ERROR => F_FE_DATA_REQUIRED_ERROR_DEFAULT,
463
            F_FE_DATA_MATCH_ERROR => F_FE_DATA_MATCH_ERROR_DEFAULT,
464
            F_FE_DATA_ERROR => F_FE_DATA_ERROR_DEFAULT,
465
            F_FE_DATA_PATTERN_ERROR => F_FE_DATA_PATTERN_ERROR_DEFAULT,
466
467
468

            SYSTEM_FLAG_PRODUCTION => 'yes',
            SYSTEM_THROW_GENERAL_ERROR => 'auto',
Carsten  Rose's avatar
Carsten Rose committed
469
470

            SYSTEM_SECURITY_FAILED_AUTH_DELAY => '3',
471
472
473

            SYSTEM_FILE_MAX_FILE_SIZE => min(Support::returnBytes(ini_get('post_max_size')), Support::returnBytes(ini_get('upload_max_filesize'))),

474
475
        ];

476
477
478
479
480
481
482
        foreach ($default as $key => $value) {
            if (!isset($config[$key]) || $config[$key] == '') {
                $config[$key] = $value;
            }
        }

        return $config;
483
484
    }

485

486
487
    /**
     * Rename Elements defined in config.qfq.ini to more appropriate in user interaction.
Carsten  Rose's avatar
Carsten Rose committed
488
489
     * E.g.: in config.qfq.ini everything is in upper case and word space is '_'. In Form.parameter it's lowercase and
     * camel hook.
490
491
     *
     * @param array $config
Carsten  Rose's avatar
Carsten Rose committed
492
     *
493
494
495
496
497
498
     * @return array
     */
    private static function renameConfigElements(array $config) {

        // oldname > newname
        $setting = [
499
            [SYSTEM_FORM_BS_COLUMNS, F_BS_COLUMNS],
500
501
502
            [SYSTEM_FORM_BS_LABEL_COLUMNS, F_BS_LABEL_COLUMNS],
            [SYSTEM_FORM_BS_INPUT_COLUMNS, F_BS_INPUT_COLUMNS],
            [SYSTEM_FORM_BS_NOTE_COLUMNS, F_BS_NOTE_COLUMNS],
503

504
505
506
507
            [SYSTEM_FORM_DATA_PATTERN_ERROR, F_FE_DATA_PATTERN_ERROR],
            [SYSTEM_FORM_DATA_REQUIRED_ERROR, F_FE_DATA_REQUIRED_ERROR],
            [SYSTEM_FORM_DATA_MATCH_ERROR, F_FE_DATA_MATCH_ERROR],
            [SYSTEM_FORM_DATA_ERROR, F_FE_DATA_ERROR],
508

509
510
511
            [SYSTEM_CSS_CLASS_QFQ_FORM, F_CLASS],
            [SYSTEM_CSS_CLASS_QFQ_FORM_PILL, F_CLASS_PILL],
            [SYSTEM_CSS_CLASS_QFQ_FORM_BODY, F_CLASS_BODY],
512
            [SYSTEM_SAVE_BUTTON_CLASS_ON_CHANGE, F_BUTTON_ON_CHANGE_CLASS],
513

514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
        ];

        foreach ($setting as $row) {
            $oldName = $row[0];
            $newName = $row[1];

            if (isset($config[$oldName])) {
                $config[$newName] = $config[$oldName];
                if ($oldName != $newName) {
                    unset($config[$oldName]);
                }
            }
        }

        return $config;
    }
530
531
532
533
534
535
536
537
538

    /**
     * Depending on some configuration value, update corresponding values.
     *
     * @param array $config
     * @return array
     */
    private static function adjustConfig(array $config) {

539
        $config[SYSTEM_SHOW_DEBUG_INFO] = self::adjustConfigDebugInfoAuto($config[SYSTEM_SHOW_DEBUG_INFO], T3Info::beUserLoggedIn());
540
541
542
        if ($config[SYSTEM_REPORT_MIN_PHP_VERSION] == SYSTEM_REPORT_MIN_PHP_VERSION_AUTO && T3Info::beUserLoggedIn()) {
            $config[SYSTEM_REPORT_MIN_PHP_VERSION] = SYSTEM_REPORT_MIN_PHP_VERSION_YES;
        }
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604

        // In case the database credentials are given in the old style: copy them to the new style
        if (!isset($config[SYSTEM_DB_1_USER]) && isset($config[SYSTEM_DB_USER])) {
            $config[SYSTEM_DB_1_USER] = $config[SYSTEM_DB_USER];
            $config[SYSTEM_DB_1_SERVER] = $config[SYSTEM_DB_SERVER];
            $config[SYSTEM_DB_1_PASSWORD] = $config[SYSTEM_DB_PASSWORD];
            $config[SYSTEM_DB_1_NAME] = $config[SYSTEM_DB_NAME];
        }

        if ($config[SYSTEM_THROW_GENERAL_ERROR] == 'auto') {
            $config[SYSTEM_THROW_GENERAL_ERROR] = $config[SYSTEM_FLAG_PRODUCTION] == 'yes' ? 'no' : 'yes';
        }

        return $config;
    }

    /**
     * @param string $value
     *
     * @param $flag
     * @return string
     */
    public static function adjustConfigDebugInfoAuto($value, $flag) {

        // Check if SHOW_DEBUG_INFO contains 'auto'. Replace with appropriate.
        if (Support::findInSet(SYSTEM_SHOW_DEBUG_INFO_AUTO, $value) && $flag) {
            $value = str_replace(SYSTEM_SHOW_DEBUG_INFO_AUTO, SYSTEM_SHOW_DEBUG_INFO_YES, $value);
        }

        return $value;
    }

    /**
     * Set automatic filled values
     *
     * @param array $config
     * @return array
     */
    private static function setAutoConfigValue(array $config) {

        $config[SYSTEM_DB_NAME_DATA] = $config['DB_' . $config[SYSTEM_DB_INDEX_DATA] . '_NAME'] ?? '';
        $config[SYSTEM_DB_NAME_QFQ] = $config['DB_' . $config[SYSTEM_DB_INDEX_QFQ] . '_NAME'] ?? '';

        return $config;
    }

    /**
     * Iterate over all Parameter which have to exist in the config. Throw an array if any is missing.
     *
     * @param array $config
     *
     * @throws \UserFormException
     */
    private static function checkMandatoryParameter(array $config) {

        // Check mandatory config vars.
        $names = array_merge([SYSTEM_SQL_LOG_MODE],
            self::dbCredentialName($config[SYSTEM_DB_INDEX_DATA]),
            self::dbCredentialName($config[SYSTEM_DB_INDEX_QFQ]));

        foreach ($names as $name) {
            if (!isset($config[$name])) {
605
                throw new \UserFormException ("Missing configuration in `" . CONFIG_QFQ_JSON . "`: $name", ERROR_MISSING_CONFIG_INI_VALUE);
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
            }
        }
    }

    /**
     * @param $index
     * @return array
     */
    private static function dbCredentialName($index) {
        $names = array();
        $names[] = 'DB_' . $index . '_USER';
        $names[] = 'DB_' . $index . '_SERVER';
        $names[] = 'DB_' . $index . '_PASSWORD';
        $names[] = 'DB_' . $index . '_NAME';

        return $names;
    }
623
}