Store.php 20.5 KB
Newer Older
1
2
3
4
5
6
7
8
<?php
/**
 * Created by PhpStorm.
 * User: crose
 * Date: 1/1/16
 * Time: 6:51 PM
 */

9
namespace qfq;
10

11
use qfq\CodeException;
12
13
use qfq\keyValueStringParser;
use qfq\OnArray;
14
use qfq;
15

16
require_once(__DIR__ . '/../../qfq/helper/KeyValueStringParser.php');
Carsten  Rose's avatar
Carsten Rose committed
17
require_once(__DIR__ . '/../../qfq/helper/Sanitize.php');
18
require_once(__DIR__ . '/../../qfq/Constants.php');
19
require_once(__DIR__ . '/../../qfq/store/Sip.php');
20
//require_once(__DIR__ . '/../../qfq/store/Session.php');
21
require_once(__DIR__ . '/../../qfq/Database.php');
22
23
24
25
26
27
28
29
30
31
32


/*
 * Stores:
 * - SIP
 * - webVar
 * - record
 * - form
 * - formElement
 */

Carsten  Rose's avatar
Carsten Rose committed
33
34
/**
 * Class Store
35
 * @package qfq
Carsten  Rose's avatar
Carsten Rose committed
36
 */
37
38
class Store {

Carsten  Rose's avatar
Carsten Rose committed
39
40
41
    /**
     * @var Store Instance of class Store. There should only be one class 'Store' at a time.
     */
42
43
    private static $instance = null;

Carsten  Rose's avatar
Carsten Rose committed
44
45
46
    /**
     * @var Sip Instance of class SIP
     */
47
48
    private static $sip = null;

49
50
51
    /**
     * @var Session Instance of class Session
     */
52
//    private static $session = null;
53

Carsten  Rose's avatar
Carsten Rose committed
54
55
56
57
58
59
60
61
62
63
    /**
     * @var array Stores all indiviudal stores with the variable raw values
     *
     * $raw['D']['id'] = 0  - Defaultvalues from Tabledefinition
     * ...
     * $raw['S']['r'] = 1234 - record ID from current SIP identifier
     * ...
     * $raw['C']['HTTP_SERVER'] = 'qfq' - Servername
     * $raw['C']['s'] = 'badcaffee1234' - recent SIP
     */
64
    private static $raw = array();
Carsten  Rose's avatar
Carsten Rose committed
65
66

    /**
Carsten  Rose's avatar
Carsten Rose committed
67
     * @var array Default sanitize classes.
Carsten  Rose's avatar
Carsten Rose committed
68
     */
Carsten  Rose's avatar
Carsten Rose committed
69
    private static $sanitizeClass = array();
Carsten  Rose's avatar
Carsten Rose committed
70
71

    /**
Carsten  Rose's avatar
Carsten Rose committed
72
73
     * $sanitizeClass['S'] = false
     * $sanitizeClass['C'] = true
Carsten  Rose's avatar
Carsten Rose committed
74
75
     * ...
     *
Carsten  Rose's avatar
Carsten Rose committed
76
     * @var array each entry with true/false - depending if store needs to be sanitized.
Carsten  Rose's avatar
Carsten Rose committed
77
     */
Carsten  Rose's avatar
Carsten Rose committed
78
    private static $sanitizeStore = array();
79

Carsten  Rose's avatar
Carsten Rose committed
80
    private static $phpUnit = false;
81

82

83
    /**
84
     * @param string $bodytext
85
     */
86
    private function __construct($bodytext = '') {
87

88
//        self::$session = Session::getInstance(self::$phpUnit);
89

Carsten  Rose's avatar
Carsten Rose committed
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
        self::$sanitizeClass = [
//            TYPO3_DEBUG_LOAD => SANITIZE_ALLOW_DIGIT,
//            TYPO3_DEBUG_SAVE => SANITIZE_ALLOW_DIGIT,
//            TYPO3_FORM => SANITIZE_ALLOW_ALNUMX,
//            TYPO3_FE_USER => SANITIZE_ALLOW_ALNUMX,
//            TYPO3_FE_USER_UID => SANITIZE_ALLOW_DIGIT,
//            TYPO3_FE_USER_GROUP => SANITIZE_ALLOW_ALNUMX,

            CLIENT_SIP => SANITIZE_ALLOW_ALNUMX,
            CLIENT_RECORD_ID => SANITIZE_ALLOW_DIGIT,
            CLIENT_KEY_SEM_ID => SANITIZE_ALLOW_DIGIT,
            CLIENT_KEY_SEM_ID_USER => SANITIZE_ALLOW_DIGIT,
            CLIENT_PAGE_ID => SANITIZE_ALLOW_DIGIT,
            CLIENT_PAGE_TYPE => SANITIZE_ALLOW_DIGIT,
            CLIENT_PAGE_LANGUAGE => SANITIZE_ALLOW_DIGIT,
            CLIENT_FORM => SANITIZE_ALLOW_ALNUMX,

            // Part of $_SERVER. Missing vars must be requested individual with the needed sanitize class.
            CLIENT_SCRIPT_URL => SANITIZE_ALLOW_ALNUMX,
            CLIENT_SCRIPT_URI => SANITIZE_ALLOW_ALNUMX,
            CLIENT_HTTP_HOST => SANITIZE_ALLOW_ALNUMX,
            CLIENT_HTTP_USER_AGENT => SANITIZE_ALLOW_ALNUMX,
            CLIENT_SERVER_NAME => SANITIZE_ALLOW_ALNUMX,
            CLIENT_SERVER_ADDRESS => SANITIZE_ALLOW_ALNUMX,
            CLIENT_SERVER_PORT => SANITIZE_ALLOW_DIGIT,
            CLIENT_REMOTE_ADDRESS => SANITIZE_ALLOW_ALNUMX,
            CLIENT_REQUEST_SCHEME => SANITIZE_ALLOW_ALNUMX,
            CLIENT_SCRIPT_FILENAME => SANITIZE_ALLOW_ALNUMX,
            CLIENT_QUERY_STRING => SANITIZE_ALLOW_ALL,
            CLIENT_REQUEST_URI => SANITIZE_ALLOW_ALL,
            CLIENT_SCRIPT_NAME => SANITIZE_ALLOW_ALNUMX,
            CLIENT_PHP_SELF => SANITIZE_ALLOW_ALNUMX,
122
            CLIENT_UPLOAD_FILENAME => SANITIZE_ALLOW_ALLBUT,
Carsten  Rose's avatar
Carsten Rose committed
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

//            SYSTEM_DBUSER => SANITIZE_ALLOW_ALNUMX,
//            SYSTEM_DBSERVER => SANITIZE_ALLOW_ALNUMX,
//            SYSTEM_DBPW => SANITIZE_ALLOW_ALL,
//            SYSTEM_DB => SANITIZE_ALLOW_ALNUMX,
//            SYSTEM_TESTDB => SANITIZE_ALLOW_ALNUMX,
//            SYSTEM_SESSIONNAME => SANITIZE_ALLOW_ALNUMX,
//            SYSTEM_DBH => SANITIZE_ALLOW_ALL,

//            SYSTEM_SQL_RAW => SANITIZE_ALLOW_ALL,
//            SYSTEM_SQL_FINAL => SANITIZE_ALLOW_ALL,
//            SYSTEM_SQL_COUNT => SANITIZE_ALLOW_DIGIT,
//            SYSTEM_SQL_PARAM_ARRAY => SANITIZE_ALLOW_ALL,

//            SIP_SIP => SANITIZE_ALLOW_ALNUMX,
//            SIP_RECORD_ID => SANITIZE_ALLOW_DIGIT,
//            SIP_FORM => SANITIZE_ALLOW_ALNUMX,
//            SIP_URLPARAM => SANITIZE_ALLOW_ALL
141

142
143
        ];

Carsten  Rose's avatar
Carsten Rose committed
144
        self::$sanitizeStore = [
145
146
147
148
            STORE_FORM => true,
            STORE_SIP => false,
            STORE_RECORD => false,
            STORE_PARENT_RECORD => false,
149
150
            STORE_TABLE_DEFAULT => false,
            STORE_TABLE_COLUMN_TYPES => false,
151
152
            STORE_CLIENT => true,
            STORE_TYPO3 => false,
153
            STORE_VAR => false,
154
            STORE_ZERO => false,
155
            STORE_EMPTY => false,
156
            STORE_SYSTEM => false,
157
            STORE_EXTRA => false
158
159
        ];

160
        self::fillSystemStore();
161
        self::fillStoreTypo3($bodytext);
162
        self::fillStoreClient();
163
        self::fillStoreSip();
Carsten  Rose's avatar
Carsten Rose committed
164
        self::fillStoreExtra();
165
166


167
    }
168

169
170
    /**
     * @throws CodeException
171
     * @throws qfq\UserFormException
172
     */
173
    private static function fillSystemStore() {
174
        try {
175
176
            //TODO: Vernuenftige Fehlermeldung falls nicht auf qfq.ini zugegriffen werden kann.
            //TODO: sinnvollen Platz fuer qfq.ini bestimmen. In der Installationsdoku erwaehnen.
177
            $config = parse_ini_file(__DIR__ . '/../../../' . CONFIG_INI, false);
178

179
180
            //TODO: auskommentiert weil dann die Unittests nicht mehr laufen. Sollte eigentlich wieder aktiviert werden.
//            $config['SQLLOG'] = Support::ifRelativePathPrependExtensionPath($config['SQLLOG']);
181

182
        } catch (\Exception $e) {
183
            throw new qfq\UserFormException ("Error read file " . CONFIG_INI . ": " . $e->getMessage(), ERROR_IO_READ_FILE);
184
        }
185

186
        // Adjust config
187
        if (!isset($config['SHOW_DEBUG_INFO']) || $config['SHOW_DEBUG_INFO'] === 'auto') {
188
189
190
            $config['SHOW_DEBUG_INFO'] = (isset($GLOBALS["TSFE"]->beUserLogin) && $GLOBALS["TSFE"]->beUserLogin === true) ? 'yes' : 'no';
        }

191
192
193
194
195
196
197
        // SYSTEM_PATH_EXT: compute only if not already defined.
        if (!isset($config[SYSTEM_PATH_EXT]) || $config[SYSTEM_PATH_EXT] === '' || $config[SYSTEM_PATH_EXT][0] !== '/') {
            $relExtDir = '/typo3conf/ext/' . EXT_KEY;

            // If we are called through AJAX API (e.g. api/save.php), there is no TYPO3 environment.
            if (isset($_SERVER['SCRIPT_FILENAME'])) {
                $pos = strpos($_SERVER['SCRIPT_FILENAME'], $relExtDir);
198
199
                if ($pos === false && isset($GLOBALS['TYPO3_LOADED_EXT'][EXT_KEY]['ext_localconf.php'])) {

200
                    // Typo3 extension: probably index.php
201
                    $config[SYSTEM_PATH_EXT] = dirname($GLOBALS['TYPO3_LOADED_EXT'][EXT_KEY]['ext_localconf.php']);
202
                    $config[SYSTEM_SITE_PATH] = dirname($_SERVER['SCRIPT_FILENAME']);
203
                } else {
204
                    // API
205
                    $config[SYSTEM_PATH_EXT] = substr($_SERVER['SCRIPT_FILENAME'], 0, $pos + strlen($relExtDir));
206
                    $config[SYSTEM_SITE_PATH] = substr($_SERVER['SCRIPT_FILENAME'], 0, $pos);
207
                }
208
209
210
211
            } else {
                // No $_SERVER >>this means phpUnit.
                $config[SYSTEM_SITE_PATH] = getcwd();
                $config[SYSTEM_PATH_EXT] = getcwd();
212
213
214
            }
        }

215
216
217
        // Defaults
        Support::setIfNotSet($config, SYSTEM_DATE_FORMAT, 'yyyy-mm-dd');

218
219
220
221
222
        // make SQL PATH absolute. This is necessary to work in different directories correctly.
        if (isset($config[SYSTEM_SQL_LOG]) && $config[SYSTEM_SQL_LOG][0] !== '/') {
            $config[SYSTEM_SQL_LOG] = $config[SYSTEM_PATH_EXT] . '/' . $config[SYSTEM_SQL_LOG];
        }

223
224
225
226
227
228
229
        // Verify existence
        $names = array('DB_USER', 'DB_SERVER', 'DB_PASSWORD', 'DB_NAME', 'SQL_LOG', 'SQL_LOG_MODE');
        foreach ($names as $name) {
            if (!isset($config[$name])) {
                throw new qfq\UserFormException ("Missing configuration in `config.ini`: $name", ERROR_MISSING_CONFIG_INI_VALUE);
            }
        }
230

231
        self::setVarArray($config, STORE_SYSTEM, true);
232
233
    }

234
235
236
    /**
     * @param array $dataArray
     * @param $store
237
     * @param bool|false $flagOverwrite
238
     * @throws UserFormException
239
     * @throws \qfq\CodeException
240
     */
241
    public static function setVarArray(array $dataArray, $store, $flagOverwrite = false) {
242

Carsten  Rose's avatar
Carsten Rose committed
243
        // Check valid Storename
Carsten  Rose's avatar
Carsten Rose committed
244
        if (!isset(self::$sanitizeStore))
245
            throw new UserFormException("Unknown Store: $store", ERROR_UNNOWN_STORE);
Carsten  Rose's avatar
Carsten Rose committed
246

247
        if ($store === STORE_ZERO)
Carsten  Rose's avatar
Carsten Rose committed
248
            throw new CodeException("setVarArray() for STORE_ZERO is impossible - there are no values.", ERROR_SET_STORE_ZERO);
249

Carsten  Rose's avatar
Carsten Rose committed
250
        if (!$flagOverwrite && isset(self::$raw[$store]) && count(self::$raw[$store]) > 0) {
251
            throw new CodeException("Raw values already been copied to store '$store'. Do this only one time.", ERROR_STORE_VALUE_ALREADY_CODPIED);
252
        }
253

254
255
        self::$raw[$store] = $dataArray;
    }
256

257
    /**
258
259
260
     * Copy the BodyText as well as some T3 specific vars to STORE_TYPO3.
     * Attention: if called through API, there is no T3 environment. The only values which are available are fe_user and fe_user_uid.
     *
261
262
263
     * @param $bodytext
     * @throws CodeException
     */
264
    private static function fillStoreTypo3($bodytext) {
265

266
        // form=, showDebugBodyText=, 10.20..
267
        $arr = KeyValueStringParser::parse($bodytext, "=", "\n");
268

269
        if (isset($GLOBALS["TSFE"])) {
270

271
272
273
            if (isset($GLOBALS["TSFE"]->fe_user->user["username"])) {
                $arr[TYPO3_FE_USER] = $GLOBALS["TSFE"]->fe_user->user["username"];
            }
274

275
276
277
278
            if (isset($GLOBALS["TSFE"]->fe_user->user["uid"])) {
                $feUid = $GLOBALS["TSFE"]->fe_user->user["uid"];
                $arr[TYPO3_FE_USER_UID] = $GLOBALS["TSFE"]->fe_user->user["uid"];
            }
279

280
281
282
            if (isset($GLOBALS["TSFE"]->fe_user->user["usergroup"])) {
                $arr[TYPO3_FE_USER_GROUP] = $GLOBALS["TSFE"]->fe_user->user["usergroup"];
            }
Carsten  Rose's avatar
Carsten Rose committed
283

284
285
286
            if (isset($GLOBALS["TSFE"]->page["uid"])) {
                $arr[TYPO3_TT_CONTENT_UID] = $GLOBALS["TSFE"]->page["uid"];
            }
287

288
289
290
291
292
293
294
            if (isset($GLOBALS["TSFE"]->id)) {
                $arr[TYPO3_PAGE_ID] = $GLOBALS["TSFE"]->id;
            }

            if (isset($GLOBALS["TSFE"]->type)) {
                $arr[TYPO3_PAGE_TYPE] = $GLOBALS["TSFE"]->type;
            }
Carsten  Rose's avatar
Carsten Rose committed
295

296
297
298
            if (isset($GLOBALS["TSFE"]->sys_language_uid)) {
                $arr[TYPO3_PAGE_LANGUAGE] = $GLOBALS["TSFE"]->sys_language_uid;
            }
299

300
        } else {
301

302
            // NO T3 environment (called by API): restore from SESSION
303
304
305
306
            foreach([ SESSION_FE_USER, SESSION_FE_USER_UID, SESSION_FE_USER_GROUP ] as $key) {
                if (isset($_SESSION[SESSION_NAME][$key])) {
                    $arr[$key] = $_SESSION[SESSION_NAME][$key];
                }
307
308
            }
        }
309

310
        self::setVarArray($arr, STORE_TYPO3, true);
311
    }
312

313
314
315
    /**
     * @throws CodeException
     */
316
    private static function fillStoreClient() {
317
        // copy GET and POST and SERVER Parameter. Priority: SERVER, POST, GET
318
319
320
321
322
323
324
325
326
        $arr = array();
        if (isset($_GET))
            $arr = array_merge($arr, $_GET);

        if (isset($_POST))
            $arr = array_merge($arr, $_POST);

        if (isset($_SERVER))
            $arr = array_merge($arr, $_SERVER);
327

328
        self::setVarArray($arr, STORE_CLIENT, true);
329
    }
330

Carsten  Rose's avatar
Carsten Rose committed
331
332
    /**
     * @throws CodeException
333
     * @throws UserFormException
Carsten  Rose's avatar
Carsten Rose committed
334
     */
335
    private static function fillStoreSip() {
Carsten  Rose's avatar
Carsten Rose committed
336

337
        self::$sip = new Sip(self::$phpUnit);
338

339
340
341
342
        $s = self::getVar(CLIENT_SIP, STORE_CLIENT);
        if ($s !== false) {
            // if session is given, copy values to store
            $param = self::$sip->getVarsFromSip($s);
343
344
            $param[SIP_SIP] = $s;
            $param[SIP_URLPARAM] = self::$sip->getQueryStringFromSip($s);
345

346
//            self::setVarArray(KeyValueStringParser::parse($param, "=", "&"), STORE_SIP);
347
            self::setVarArray($param, STORE_SIP, true);
348
349
350
        }
    }

351
    /**
352
     * Cycles through all stores in $useStore.
353
     * First match will return the found value.
Carsten  Rose's avatar
Carsten Rose committed
354
     * During cycling: fill cache with requestet value and sanitize raw value.
355
     *
356
     * @param string $key
357
     * @param string $useStores f.e.: 'FSRD'
Carsten  Rose's avatar
Carsten Rose committed
358
     * @param string $sanitizeClass
Carsten  Rose's avatar
Carsten Rose committed
359
     * @param string $foundInStore Returns the name of the store where $key has been found. If $key is not found, return ''.
360
     * @return string a) if found: value, b) false
Carsten  Rose's avatar
Carsten Rose committed
361
     * @throws \qfq\CodeException
362
     */
Carsten  Rose's avatar
Carsten Rose committed
363
    public static function getVar($key, $useStores = STORE_USE_DEFAULT, $sanitizeClass = '', &$foundInStore = '') {
364
365

        // no store specifed?
366
        if ($useStores === "" || $useStores === null) {
367
            $useStores = STORE_USE_DEFAULT;
368
369
        }

370
        // no sanitizeClass specified: take predefined (if exist) or default.
371
        if ($sanitizeClass === '' || $sanitizeClass === null) {
Carsten  Rose's avatar
Carsten Rose committed
372
            $sanitizeClass = isset(self::$sanitizeClass[$key]) ? self::$sanitizeClass[$key] : SANITIZE_DEFAULT;
373
374
        }

375
376
377
        while ($useStores !== false) {

            $store = substr($useStores, 0, 1); // next store
Carsten  Rose's avatar
Carsten Rose committed
378
            $foundInStore = $store;
379
380
            $useStores = substr($useStores, 1); // shift left remaining stores

381
            if (!isset(self::$raw[$store][$key])) {
382
383
384
                switch ($store) {
                    case STORE_ZERO:
                        return 0;
385
386
                    case STORE_EMPTY:
                        return '';
387
388
                    case STORE_VAR:
                        if ($key === VAR_RANDOM) {
389
                            return Support::randomAlphaNum(RANDOM_LENGTH);
390
391
392
393
394
395
396
                        } else {
                            continue 2;  // no value provided, continue with while loop
                        }
                        break;
                    default:
                        continue 2; // no value provided, continue with while loop
                        break;
Carsten  Rose's avatar
Carsten Rose committed
397
                }
398
399
            }

400
            $rawVal = isset(self::$raw[$store][$key]) ? self::$raw[$store][$key] : null;
Carsten  Rose's avatar
Carsten Rose committed
401
            if (self::$sanitizeStore[$store] && $sanitizeClass != '') {
402
403
404
405
406
                if ($sanitizeClass == SANITIZE_ALLOW_PATTERN || $sanitizeClass == SANITIZE_ALLOW_MIN_MAX || $sanitizeClass == SANITIZE_ALLOW_MIN_MAX_DATE) {
                    // We do not have any pattern or min|max values at this point. For those who be affected, they already checked earlier. So set 'no check'
                    $sanitizeClass = SANITIZE_ALLOW_ALL;
                }
                return \qfq\Sanitize::sanitize($rawVal, $sanitizeClass, '', SANATIZE_EMPTY_STRING);
407
408
            } else {
                return $rawVal;
409
            }
410
        }
Carsten  Rose's avatar
Carsten Rose committed
411
        $foundInStore = '';
412
        return false;
413
    }
414

Carsten  Rose's avatar
Carsten Rose committed
415
416
417
418
419
    /**
     * @throws UserFormException
     * @throws \qfq\CodeException
     */
    private static function fillStoreExtra() {
420

421
        $value = Session::get(STORE_EXTRA);
422

423
        if (!isset($_SESSION[SESSION_NAME][STORE_EXTRA]) || $_SESSION[SESSION_NAME][STORE_EXTRA] === null) {
424
425
426
427
            $value = false;
        }

        if ($value === false) {
Carsten  Rose's avatar
Carsten Rose committed
428
            self::setVarArray(array(), STORE_EXTRA, true);
429
        } else {
430
            self::setVarArray($_SESSION[SESSION_NAME][STORE_EXTRA], STORE_EXTRA, true);
431
        }
Carsten  Rose's avatar
Carsten Rose committed
432
433
    }

434
435
    /**
     * @param string $bodytext
436
     * @param bool|false $phpUnit
437
     * @return null|\qfq\Store
438
     */
439
    public static function getInstance($bodytext = '', $phpUnit = false) {
440

441
        if ($phpUnit) {
442
            if (self::$instance !== null) {
443
                // fake to have a clean environment for the next test.
444
445
446
447
448
                self::unsetStore(STORE_TYPO3);
                self::fillStoreTypo3($bodytext);

                self::unsetStore(STORE_CLIENT);
                self::fillStoreClient();
449
450
451
452
453
            }
        }

        // Design Pattern: Singleton
        if (self::$instance === null) {
454
455
456
            self::$phpUnit = $phpUnit;

            self::$instance = new self($bodytext);
Carsten  Rose's avatar
Carsten Rose committed
457
458
459
460
        } else {
            // Class Store seems to be presistent over multiple QFQ instantiation. Set bodytext again, with every new request (if bodytext is given).
            if ($bodytext !== '')
                self::fillStoreTypo3($bodytext);
461
462
        }

463
464
465
466
467
468
469
        // Disable TYPO3_DEBUG_SHOW_BODY_TEXT=1 if SYSTEM_SHOW_DEBUG_INFO!='yes'
        if (self::getVar(TYPO3_DEBUG_SHOW_BODY_TEXT, STORE_TYPO3) === '1' &&
            self::getVar(SYSTEM_SHOW_DEBUG_INFO, STORE_SYSTEM) !== 'yes'
        ) {
            self::setVar(TYPO3_DEBUG_SHOW_BODY_TEXT, '0', STORE_TYPO3);
        }

470
        return self::$instance;
471
    }
472

473
474
    /**
     * @param $store
475
476
     * @throws UserFormException
     * @throws \qfq\CodeException
477
478
     */
    public static function unsetStore($store) {
Carsten  Rose's avatar
Carsten Rose committed
479
        // Check valid Storename
Carsten  Rose's avatar
Carsten Rose committed
480
        if (!isset(self::$sanitizeStore))
481
            throw new UserFormException("Unknown Store: $store", ERROR_UNNOWN_STORE);
Carsten  Rose's avatar
Carsten Rose committed
482

483
        if ($store === STORE_ZERO)
Carsten  Rose's avatar
Carsten Rose committed
484
485
            throw new CodeException("unsetStore() for STORE_ZERO is impossible - there are no values.", ERROR_SET_STORE_ZERO);

486
487
488
        if (isset(self::$raw[$store])) {
            self::$raw[$store] = array();
        }
Carsten  Rose's avatar
Carsten Rose committed
489

490
491
    }

492
    /**
Carsten  Rose's avatar
Carsten Rose committed
493
494
495
     * @param string $key
     * @param string|array $value
     * @param string $store
496
497
498
499
500
501
502
503
504
505
506
507
508
     * @param bool|true $overWrite
     * @throws UserFormException
     * @throws \qfq\CodeException
     */
    public static function setVar($key, $value, $store, $overWrite = true) {
        // Check valid Storename
        if (!isset(self::$sanitizeStore))
            throw new UserFormException("Unknown Store: $store", ERROR_UNNOWN_STORE);

        if ($store === STORE_ZERO)
            throw new CodeException("setVar() for STORE_ZERO is impossible - there are no values.", ERROR_SET_STORE_ZERO);

        if ($overWrite === false && isset(self::$raw[$store][$key])) {
509
            throw new UserFormException("Value of '$key' already set in store '$store'.", ERROR_STORE_KEY_EXIST);
510
511
512
        }

        self::$raw[$store][$key] = $value;
Carsten  Rose's avatar
Carsten Rose committed
513
514
515

        // The STORE_EXTRA saves arrays and is persistent
        if ($store === STORE_EXTRA) {
516

517
            $store = Session::get(STORE_EXTRA);
518
519

            if ($store === false) {
520
                $store = array();
521
522
            }

523
524
            $store[$key] = $value;
            Session::set(STORE_EXTRA, $store);
525

Carsten  Rose's avatar
Carsten Rose committed
526
        }
527
528
    }

529
530
531
532
    /**
     * @param $formName
     * @throws CodeException
     */
533
    public static function createSipAfterFormLoad($formName) {
534

535
        $recordId = self::getVar(CLIENT_RECORD_ID, STORE_TYPO3 . STORE_CLIENT);
536
537
538
539
540
541
542
        if ($recordId === false) {
            $recordId = 0;
        }

        $tmpParam = [SIP_RECORD_ID => $recordId, SIP_FORM => $formName];

        // Construct fake urlparam
543
        $tmpUrlparam = OnArray::toString($tmpParam);
544
545

        // Create a fake SIP which has never been passed by URL - further processing might expect this to exist.
546
        $sip = self::getSipInstance()->queryStringToSip($tmpUrlparam, RETURN_SIP);
547
        self::setVar(CLIENT_SIP, $sip, STORE_CLIENT);
548
549
550

        // Store in SIP Store (cause it's empty until now).
        $tmpParam[SIP_SIP] = $sip;
551
        self::setVarArray($tmpParam, STORE_SIP, true);
552

553
554
555
    }

    /**
556
     * @return null|Sip
557
     */
558
    public static function getSipInstance() {
559
560
        return self::$sip;
    }
561

562
563
    /**
     * @param $store
564
565
566
     * @return array
     * @throws UserFormException
     * @throws \qfq\CodeException
567
568
     */
    public static function getStore($store) {
Carsten  Rose's avatar
Carsten Rose committed
569
        // Check valid Storename
Carsten  Rose's avatar
Carsten Rose committed
570
        if (!isset(self::$sanitizeStore[$store]))
571
            throw new UserFormException("Unknown Store: $store", ERROR_UNNOWN_STORE);
Carsten  Rose's avatar
Carsten Rose committed
572

573
        if ($store === STORE_ZERO)
Carsten  Rose's avatar
Carsten Rose committed
574
575
            throw new CodeException("getStore() for STORE_ZERO is impossible - there are no values saved.", ERROR_GET_STORE_ZERO);

576
577
578
        if (isset(self::$raw[$store])) {
            return self::$raw[$store];
        }
579

580
581
        return array();
    }
582

Carsten  Rose's avatar
Carsten Rose committed
583

584
    /**
Carsten  Rose's avatar
Carsten Rose committed
585
586
     * Fills STORE_TABLE_DEFAULT and STORE_TABLE_COLUMN_TYPES
     *
587
588
589
     * @param $tableName
     * @throws CodeException
     */
590
    public static function fillStoreTableDefaultColumnType($tableName) {
591
592
593
594
        $db = new qfq\Database();

        $tableDefinition = $db->getTableDefinition($tableName);

Carsten  Rose's avatar
Carsten Rose committed
595
596
        self::setVarArray(array_column($tableDefinition, 'Default', 'Field'), STORE_TABLE_DEFAULT, true);
        self::setVarArray(array_column($tableDefinition, 'Type', 'Field'), STORE_TABLE_COLUMN_TYPES, true);
597
    }
598
599
600
601
602
}