Store.php 20.2 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
223
        // 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];
        }


224
        self::setVarArray($config, STORE_SYSTEM, true);
225
226
    }

227
228
229
    /**
     * @param array $dataArray
     * @param $store
230
     * @param bool|false $flagOverwrite
231
     * @throws UserFormException
232
     * @throws \qfq\CodeException
233
     */
234
    public static function setVarArray(array $dataArray, $store, $flagOverwrite = false) {
235

Carsten  Rose's avatar
Carsten Rose committed
236
        // Check valid Storename
Carsten  Rose's avatar
Carsten Rose committed
237
        if (!isset(self::$sanitizeStore))
238
            throw new UserFormException("Unknown Store: $store", ERROR_UNNOWN_STORE);
Carsten  Rose's avatar
Carsten Rose committed
239

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

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

247
248
        self::$raw[$store] = $dataArray;
    }
249

250
    /**
251
252
253
     * 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.
     *
254
255
256
     * @param $bodytext
     * @throws CodeException
     */
257
    private static function fillStoreTypo3($bodytext) {
258

259
        // form=, showDebugBodyText=, 10.20..
260
        $arr = KeyValueStringParser::parse($bodytext, "=", "\n");
261

262
        if (isset($GLOBALS["TSFE"])) {
263

264
265
266
            if (isset($GLOBALS["TSFE"]->fe_user->user["username"])) {
                $arr[TYPO3_FE_USER] = $GLOBALS["TSFE"]->fe_user->user["username"];
            }
267

268
269
270
271
            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"];
            }
272

273
274
275
            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
276

277
278
279
            if (isset($GLOBALS["TSFE"]->page["uid"])) {
                $arr[TYPO3_TT_CONTENT_UID] = $GLOBALS["TSFE"]->page["uid"];
            }
280

281
282
283
284
285
286
287
            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
288

289
290
291
            if (isset($GLOBALS["TSFE"]->sys_language_uid)) {
                $arr[TYPO3_PAGE_LANGUAGE] = $GLOBALS["TSFE"]->sys_language_uid;
            }
292

293
        } else {
294

295
            // NO T3 environment (called by API): restore from SESSION
296
297
298
299
            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];
                }
300
301
            }
        }
302

303
        self::setVarArray($arr, STORE_TYPO3, true);
304
    }
305

306
307
308
    /**
     * @throws CodeException
     */
309
    private static function fillStoreClient() {
310
        // copy GET and POST and SERVER Parameter. Priority: SERVER, POST, GET
311
312
313
314
315
316
317
318
319
        $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);
320

321
        self::setVarArray($arr, STORE_CLIENT, true);
322
    }
323

Carsten  Rose's avatar
Carsten Rose committed
324
325
    /**
     * @throws CodeException
326
     * @throws UserFormException
Carsten  Rose's avatar
Carsten Rose committed
327
     */
328
    private static function fillStoreSip() {
Carsten  Rose's avatar
Carsten Rose committed
329

330
        self::$sip = new Sip(self::$phpUnit);
331

332
333
334
335
        $s = self::getVar(CLIENT_SIP, STORE_CLIENT);
        if ($s !== false) {
            // if session is given, copy values to store
            $param = self::$sip->getVarsFromSip($s);
336
337
            $param[SIP_SIP] = $s;
            $param[SIP_URLPARAM] = self::$sip->getQueryStringFromSip($s);
338

339
//            self::setVarArray(KeyValueStringParser::parse($param, "=", "&"), STORE_SIP);
340
            self::setVarArray($param, STORE_SIP, true);
341
342
343
        }
    }

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

        // no store specifed?
359
        if ($useStores === "" || $useStores === null) {
360
            $useStores = STORE_USE_DEFAULT;
361
362
        }

363
        // no sanitizeClass specified: take predefined (if exist) or default.
364
        if ($sanitizeClass === '' || $sanitizeClass === null) {
Carsten  Rose's avatar
Carsten Rose committed
365
            $sanitizeClass = isset(self::$sanitizeClass[$key]) ? self::$sanitizeClass[$key] : SANITIZE_DEFAULT;
366
367
        }

368
369
370
        while ($useStores !== false) {

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

374
            if (!isset(self::$raw[$store][$key])) {
375
376
377
                switch ($store) {
                    case STORE_ZERO:
                        return 0;
378
379
                    case STORE_EMPTY:
                        return '';
380
381
                    case STORE_VAR:
                        if ($key === VAR_RANDOM) {
382
                            return Support::randomAlphaNum(RANDOM_LENGTH);
383
384
385
386
387
388
389
                        } 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
390
                }
391
392
            }

393
            $rawVal = isset(self::$raw[$store][$key]) ? self::$raw[$store][$key] : null;
Carsten  Rose's avatar
Carsten Rose committed
394
            if (self::$sanitizeStore[$store] && $sanitizeClass != '') {
395
396
397
398
399
                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);
400
401
            } else {
                return $rawVal;
402
            }
403
        }
Carsten  Rose's avatar
Carsten Rose committed
404
        $foundInStore = '';
405
        return false;
406
    }
407

Carsten  Rose's avatar
Carsten Rose committed
408
409
410
411
412
    /**
     * @throws UserFormException
     * @throws \qfq\CodeException
     */
    private static function fillStoreExtra() {
413

414
        $value = Session::get(STORE_EXTRA);
415

416
        if (!isset($_SESSION[SESSION_NAME][STORE_EXTRA]) || $_SESSION[SESSION_NAME][STORE_EXTRA] === null) {
417
418
419
420
            $value = false;
        }

        if ($value === false) {
Carsten  Rose's avatar
Carsten Rose committed
421
            self::setVarArray(array(), STORE_EXTRA, true);
422
        } else {
423
            self::setVarArray($_SESSION[SESSION_NAME][STORE_EXTRA], STORE_EXTRA, true);
424
        }
Carsten  Rose's avatar
Carsten Rose committed
425
426
    }

427
428
    /**
     * @param string $bodytext
429
     * @param bool|false $phpUnit
430
     * @return null|\qfq\Store
431
     */
432
    public static function getInstance($bodytext = '', $phpUnit = false) {
433

434
        if ($phpUnit) {
435
            if (self::$instance !== null) {
436
                // fake to have a clean environment for the next test.
437
438
439
440
441
                self::unsetStore(STORE_TYPO3);
                self::fillStoreTypo3($bodytext);

                self::unsetStore(STORE_CLIENT);
                self::fillStoreClient();
442
443
444
445
446
            }
        }

        // Design Pattern: Singleton
        if (self::$instance === null) {
447
448
449
            self::$phpUnit = $phpUnit;

            self::$instance = new self($bodytext);
Carsten  Rose's avatar
Carsten Rose committed
450
451
452
453
        } 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);
454
455
        }

456
457
458
459
460
461
462
        // 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);
        }

463
        return self::$instance;
464
    }
465

466
467
    /**
     * @param $store
468
469
     * @throws UserFormException
     * @throws \qfq\CodeException
470
471
     */
    public static function unsetStore($store) {
Carsten  Rose's avatar
Carsten Rose committed
472
        // Check valid Storename
Carsten  Rose's avatar
Carsten Rose committed
473
        if (!isset(self::$sanitizeStore))
474
            throw new UserFormException("Unknown Store: $store", ERROR_UNNOWN_STORE);
Carsten  Rose's avatar
Carsten Rose committed
475

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

479
480
481
        if (isset(self::$raw[$store])) {
            self::$raw[$store] = array();
        }
Carsten  Rose's avatar
Carsten Rose committed
482

483
484
    }

485
    /**
Carsten  Rose's avatar
Carsten Rose committed
486
487
488
     * @param string $key
     * @param string|array $value
     * @param string $store
489
490
491
492
493
494
495
496
497
498
499
500
501
     * @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])) {
502
            throw new UserFormException("Value of '$key' already set in store '$store'.", ERROR_STORE_KEY_EXIST);
503
504
505
        }

        self::$raw[$store][$key] = $value;
Carsten  Rose's avatar
Carsten Rose committed
506
507
508

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

510
            $store = Session::get(STORE_EXTRA);
511
512

            if ($store === false) {
513
                $store = array();
514
515
            }

516
517
            $store[$key] = $value;
            Session::set(STORE_EXTRA, $store);
518

Carsten  Rose's avatar
Carsten Rose committed
519
        }
520
521
    }

522
523
524
525
    /**
     * @param $formName
     * @throws CodeException
     */
526
    public static function createSipAfterFormLoad($formName) {
527

528
        $recordId = self::getVar(CLIENT_RECORD_ID, STORE_TYPO3 . STORE_CLIENT);
529
530
531
532
533
534
535
        if ($recordId === false) {
            $recordId = 0;
        }

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

        // Construct fake urlparam
536
        $tmpUrlparam = OnArray::toString($tmpParam);
537
538

        // Create a fake SIP which has never been passed by URL - further processing might expect this to exist.
539
        $sip = self::getSipInstance()->queryStringToSip($tmpUrlparam, RETURN_SIP);
540
        self::setVar(CLIENT_SIP, $sip, STORE_CLIENT);
541
542
543

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

546
547
548
    }

    /**
549
     * @return null|Sip
550
     */
551
    public static function getSipInstance() {
552
553
        return self::$sip;
    }
554

555
556
    /**
     * @param $store
557
558
559
     * @return array
     * @throws UserFormException
     * @throws \qfq\CodeException
560
561
     */
    public static function getStore($store) {
Carsten  Rose's avatar
Carsten Rose committed
562
        // Check valid Storename
Carsten  Rose's avatar
Carsten Rose committed
563
        if (!isset(self::$sanitizeStore[$store]))
564
            throw new UserFormException("Unknown Store: $store", ERROR_UNNOWN_STORE);
Carsten  Rose's avatar
Carsten Rose committed
565

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

569
570
571
        if (isset(self::$raw[$store])) {
            return self::$raw[$store];
        }
572

573
574
        return array();
    }
575

Carsten  Rose's avatar
Carsten Rose committed
576

577
    /**
Carsten  Rose's avatar
Carsten Rose committed
578
579
     * Fills STORE_TABLE_DEFAULT and STORE_TABLE_COLUMN_TYPES
     *
580
581
582
     * @param $tableName
     * @throws CodeException
     */
583
    public static function fillStoreTableDefaultColumnType($tableName) {
584
585
586
587
        $db = new qfq\Database();

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

Carsten  Rose's avatar
Carsten Rose committed
588
589
        self::setVarArray(array_column($tableDefinition, 'Default', 'Field'), STORE_TABLE_DEFAULT, true);
        self::setVarArray(array_column($tableDefinition, 'Type', 'Field'), STORE_TABLE_COLUMN_TYPES, true);
590
    }
591
592
593
594
595
}