Store.php 12.9 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
17
require_once(__DIR__ . '/../../qfq/helper/KeyValueStringParser.php');
require_once(__DIR__ . '/../../qfq/helper/Sanatize.php');
18
require_once(__DIR__ . '/../../qfq/Constants.php');
19
require_once(__DIR__ . '/../../qfq/store/Sip.php');
20
require_once(__DIR__ . '/../../qfq/Database.php');
21
22
23
24
25
26
27
28
29
30
31


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

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

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

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

Carsten  Rose's avatar
Carsten Rose committed
48
49
50
51
52
53
54
55
56
57
    /**
     * @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
     */
58
    private static $raw = array();
Carsten  Rose's avatar
Carsten Rose committed
59
60
61
62

    /**
     * @var array Default sanatize classes.
     */
63
    private static $sanatizeClass = array();
Carsten  Rose's avatar
Carsten Rose committed
64
65
66
67
68
69
70
71

    /**
     * $sanatizeClass['S'] = false
     * $sanatizeClass['C'] = true
     * ...
     *
     * @var array each entry with true/false - depending if store needs to be sanatized.
     */
72
    private static $sanatizeStore = array();
73
74

    /**
75
     * @param string $bodytext
76
     */
77
78
    private function __construct($bodytext = '') {

79
80
81
82
83
84
85
        self::$sanatizeClass = [
//            TYPO3_DEBUG_LOAD => SANATIZE_ALLOW_DIGIT,
//            TYPO3_DEBUG_SAVE => SANATIZE_ALLOW_DIGIT,
//            TYPO3_FORM => SANATIZE_ALLOW_ALNUMX,
//            TYPO3_FE_USER => SANATIZE_ALLOW_ALNUMX,
//            TYPO3_FE_USER_UID => SANATIZE_ALLOW_DIGIT,
//            TYPO3_FE_USER_GROUP => SANATIZE_ALLOW_ALNUMX,
86
87
88
89
90
91
92
93
94
95

            CLIENT_SIP => SANATIZE_ALLOW_ALNUMX,
            CLIENT_RECORD_ID => SANATIZE_ALLOW_DIGIT,
            CLIENT_KEY_SEM_ID => SANATIZE_ALLOW_DIGIT,
            CLIENT_KEY_SEM_ID_USER => SANATIZE_ALLOW_DIGIT,
            CLIENT_PAGE_ID => SANATIZE_ALLOW_DIGIT,
            CLIENT_PAGE_TYPE => SANATIZE_ALLOW_DIGIT,
            CLIENT_PAGE_LANGUAGE => SANATIZE_ALLOW_DIGIT,
            CLIENT_FORM => SANATIZE_ALLOW_ALNUMX,

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
            // Part of $_SERVER. Missing vars must be requested individual with the needed sanatize class.
            CLIENT_SCRIPT_URL => SANATIZE_ALLOW_ALNUMX,
            CLIENT_SCRIPT_URI => SANATIZE_ALLOW_ALNUMX,
            CLIENT_HTTP_HOST => SANATIZE_ALLOW_ALNUMX,
            CLIENT_HTTP_USER_AGENT => SANATIZE_ALLOW_ALNUMX,
            CLIENT_SERVER_NAME => SANATIZE_ALLOW_ALNUMX,
            CLIENT_SERVER_ADDRESS => SANATIZE_ALLOW_ALNUMX,
            CLIENT_SERVER_PORT => SANATIZE_ALLOW_DIGIT,
            CLIENT_REMOTE_ADDRESS => SANATIZE_ALLOW_ALNUMX,
            CLIENT_REQUEST_SCHEME => SANATIZE_ALLOW_ALNUMX,
            CLIENT_SCRIPT_FILENAME => SANATIZE_ALLOW_ALNUMX,
            CLIENT_QUERY_STRING => SANATIZE_ALLOW_ALL,
            CLIENT_REQUEST_URI => SANATIZE_ALLOW_ALL,
            CLIENT_SCRIPT_NAME => SANATIZE_ALLOW_ALNUMX,
            CLIENT_PHP_SELF => SANATIZE_ALLOW_ALNUMX,

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//            SYSTEM_DBUSER => SANATIZE_ALLOW_ALNUMX,
//            SYSTEM_DBSERVER => SANATIZE_ALLOW_ALNUMX,
//            SYSTEM_DBPW => SANATIZE_ALLOW_ALL,
//            SYSTEM_DB => SANATIZE_ALLOW_ALNUMX,
//            SYSTEM_TESTDB => SANATIZE_ALLOW_ALNUMX,
//            SYSTEM_SESSIONNAME => SANATIZE_ALLOW_ALNUMX,
//            SYSTEM_DBH => SANATIZE_ALLOW_ALL,

//            SYSTEM_SQL_RAW => SANATIZE_ALLOW_ALL,
//            SYSTEM_SQL_FINAL => SANATIZE_ALLOW_ALL,
//            SYSTEM_SQL_COUNT => SANATIZE_ALLOW_DIGIT,
//            SYSTEM_SQL_PARAM_ARRAY => SANATIZE_ALLOW_ALL,

//            SIP_SIP => SANATIZE_ALLOW_ALNUMX,
//            SIP_RECORD_ID => SANATIZE_ALLOW_DIGIT,
//            SIP_FORM => SANATIZE_ALLOW_ALNUMX,
//            SIP_URLPARAM => SANATIZE_ALLOW_ALL
129

130
131
        ];

132
133
134
135
136
        self::$sanatizeStore = [
            STORE_FORM => true,
            STORE_SIP => false,
            STORE_RECORD => false,
            STORE_PARENT_RECORD => false,
137
138
            STORE_TABLE_DEFAULT => false,
            STORE_TABLE_COLUMN_TYPES => false,
139
140
            STORE_CLIENT => true,
            STORE_TYPO3 => false,
141
            STORE_ZERO => false,
142
143
144
            STORE_SYSTEM => false
        ];

145
        self::fillSystemStore();
146
        self::fillStoreTypo3($bodytext);
147
        self::fillStoreClient();
148
        self::fillStoreSip();
149
    }
150

151
152
    /**
     * @throws CodeException
153
     * @throws qfq\UserException
154
155
     */
    private function fillSystemStore() {
156
157
        try {
            $config = parse_ini_file(QFQ_INI, false);
158
        } catch (\Exception $e) {
159
            throw new qfq\UserException ("Error read file " . QFQ_INI . ": " . $e->getMessage(), ERROR_READ_FILE);
160
        }
161
        self::setVarArray($config, STORE_SYSTEM,true);
162
163
    }

164
165
166
167
168
    /**
     * @param array $dataArray
     * @param $store
     * @throws CodeException
     */
169
    public function setVarArray(array $dataArray, $store, $flagOverwrite = false) {
Carsten  Rose's avatar
Carsten Rose committed
170
171
172
173
174
        // Check valid Storename
        if (!isset(self::$sanatizeStore))
            throw new UserException("Unknown Store: $store", ERROR_UNNOWN_STORE);


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

178
        if ($flagOverwrite && isset(self::$raw[$store]) && count(self::$raw[$store]) > 0) {
179
180
            throw new CodeException("Raw values already been copied to store '$store'. Do this only one time.", ERROR_VALUE_ALREADY_CODPIED);
        }
181

182
183
        self::$raw[$store] = $dataArray;
    }
184

185
186
187
188
    /**
     * @param $bodytext
     * @throws CodeException
     */
189
190
    private function fillStoreTypo3($bodytext) {

191
        $arr = KeyValueStringParser::parse($bodytext, "=", "\n");
192
193
194
195
196
197
198
199
200

        if (isset($GLOBALS["TSFE"]->fe_user->user["username"]))
            $arr[TYPO3_FE_USER] = $GLOBALS["TSFE"]->fe_user->user["username"];

        if (isset($GLOBALS["TSFE"]->fe_user->user["uid"]))
            $arr[TYPO3_FE_USER_UID] = $GLOBALS["TSFE"]->fe_user->user["uid"];

        if (isset($GLOBALS["TSFE"]->fe_user->user["usergroup"]))
            $arr[TYPO3_FE_USER_GROUP] = $GLOBALS["TSFE"]->fe_user->user["usergroup"];
201

202
        self::setVarArray($arr, STORE_TYPO3, true);
203
    }
204

205
206
207
208
    /*
     *
     */

209
210
211
212
    /**
     * @throws CodeException
     */
    private function fillStoreClient() {
213
214
        // copy GET and POST and SERVER Parameter. Priority: SERVER, POST, GET
        $arr = array_merge($_GET, $_POST, $_SERVER);
215

216
        self::setVarArray($arr, STORE_CLIENT, true);
217
    }
218

Carsten  Rose's avatar
Carsten Rose committed
219
220
    /**
     * @throws CodeException
221
     * @throws UserException
Carsten  Rose's avatar
Carsten Rose committed
222
     */
223
    private function fillStoreSip() {
Carsten  Rose's avatar
Carsten Rose committed
224

225
        $sessionName = self::getVar(SYSTEM_SESSIONNAME, STORE_SYSTEM);
226
        self::$sip = new Sip($sessionName);
227

228
229
230
231
        $s = self::getVar(CLIENT_SIP, STORE_CLIENT);
        if ($s !== false) {
            // if session is given, copy values to store
            $param = self::$sip->getVarsFromSip($s);
232
233
            $param[SIP_SIP] = $s;
            $param[SIP_URLPARAM] = self::$sip->getQueryStringFromSip($s);
234

235
//            self::setVarArray(KeyValueStringParser::parse($param, "=", "&"), STORE_SIP);
236
            self::setVarArray($param, STORE_SIP, true);
237
238
239
        }
    }

240
    /**
241
     * Cycles through all stores in $useStore.
242
     * First match will return the found value.
243
     * During cycling: fill cache with requestet value and sanatize raw value.
244
     *
245
     * @param string $key
246
     * @param string $useStores f.e.: 'FSRD'
247
248
249
     * @param string $sanatizeClass
     * @return string a) if found: value, b) false
     */
250
    public static function getVar($key, $useStores = USE_STORE_DEFAULT, $sanatizeClass = '') {
251
252

        // no store specifed?
253
254
        if ($useStores === "" || $useStores === null) {
            $useStores = USE_STORE_DEFAULT;
255
256
        }

257
258
259
260
261
        // no sanatizeClass specified: take last/default
        if ($sanatizeClass === '') {
            $sanatizeClass = isset(self::$sanatizeClass[$key]) ? self::$sanatizeClass[$key] : SANATIZE_DEFAULT;
        }

262
263
264
265
266
        while ($useStores !== false) {

            $store = substr($useStores, 0, 1); // next store
            $useStores = substr($useStores, 1); // shift left remaining stores

267
            if (!isset(self::$raw[$store][$key])) {
268
                if ($store === STORE_ZERO) {
Carsten  Rose's avatar
Carsten Rose committed
269
270
271
272
                    return 0;
                } else {
                    continue; // no value provided
                }
273
274
            }

275
            $rawVal = isset(self::$raw[$store][$key]) ? self::$raw[$store][$key] : null;
276

277
278
279
280
            if (self::$sanatizeStore[$store] && $sanatizeClass != '') {
                return \qfq\Sanatize::sanatize($rawVal, $sanatizeClass);
            } else {
                return $rawVal;
281
            }
282
        }
283

284
        return false;
285
    }
286

287
288
289
    /**
     * @param string $bodytext
     * @param bool|false $phpunit
290
     * @return null|\qfq\Store
291
292
293
294
     */
    public static function getInstance($bodytext = '', $phpunit = false) {

        if ($phpunit) {
295
296
297
298
299
300
301
            if (self::$instance !== null) {

                self::unsetStore(STORE_TYPO3);
                self::fillStoreTypo3($bodytext);

                self::unsetStore(STORE_CLIENT);
                self::fillStoreClient();
302
303
304
305
306
307
308
309
310
            }
        }

        // Design Pattern: Singleton
        if (self::$instance === null) {
            self::$instance = new self($bodytext);
        }

        return self::$instance;
311
    }
312

313
314
315
316
    /**
     * @param $store
     */
    public static function unsetStore($store) {
Carsten  Rose's avatar
Carsten Rose committed
317
318
319
320
        // Check valid Storename
        if (!isset(self::$sanatizeStore))
            throw new UserException("Unknown Store: $store", ERROR_UNNOWN_STORE);

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

324
325
326
327
328
        if (isset(self::$raw[$store])) {
            self::$raw[$store] = array();
        }
    }

329
330
331
332
    /**
     * @param $formName
     * @throws CodeException
     */
333
334
    public
    static function createSipAfterFormLoad($formName) {
335
        $recordId = self::getVar(CLIENT_RECORD_ID, STORE_TYPO3 . STORE_CLIENT);
336
337
338
339
340
341
342
        if ($recordId === false) {
            $recordId = 0;
        }

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

        // Construct fake urlparam
343
        $tmpUrlparam = OnArray::toString($tmpParam);
344
345

        // Create a fake SIP which has never been passed by URL - further processing might expect this to exist.
346
        $sip = self::getSip()->queryStringToSip($tmpUrlparam, RETURN_SIP);
347
        self::setVar(CLIENT_SIP, $sip, STORE_CLIENT);
348
349
350
351
352

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

353
354
355
    }

    /**
356
     * @return null|Sip
357
358
359
360
     */
    public static function getSip() {
        return self::$sip;
    }
361
362
363
364
365

    /**
     * @param $key
     * @param $value
     * @param $store
Carsten  Rose's avatar
Carsten Rose committed
366
367
     * @param bool|true $overWrite
     * @throws UserException
368
     */
Carsten  Rose's avatar
Carsten Rose committed
369
370
371
372
373
    public static function setVar($key, $value, $store, $overWrite = true) {
        // Check valid Storename
        if (!isset(self::$sanatizeStore))
            throw new UserException("Unknown Store: $store", ERROR_UNNOWN_STORE);

374
        if ($store === STORE_ZERO)
Carsten  Rose's avatar
Carsten Rose committed
375
376
377
378
379
            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])) {
            throw new UserException("Value of '$key' already be set in store '$store'.", ERROR_KEY_EXIST_IN_STORE);
        }
380
381

        self::$raw[$store][$key] = $value;
382
383
384
385
386
387
388
    }

    /**
     * @param $store
     * @return mixed
     */
    public static function getStore($store) {
Carsten  Rose's avatar
Carsten Rose committed
389
390
391
392
        // Check valid Storename
        if (!isset(self::$sanatizeStore))
            throw new UserException("Unknown Store: $store", ERROR_UNNOWN_STORE);

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

396
397
398
399
400
        if (isset(self::$raw[$store])) {
            return self::$raw[$store];
        }
        return array();
    }
401

Carsten  Rose's avatar
Carsten Rose committed
402

403
    /**
Carsten  Rose's avatar
Carsten Rose committed
404
405
     * Fills STORE_TABLE_DEFAULT and STORE_TABLE_COLUMN_TYPES
     *
406
407
408
     * @param $tableName
     * @throws CodeException
     */
409
    public function fillStoreTableDefaultColumnType($tableName) {
410
411
412
413
        $db = new qfq\Database();

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

414
415
416
        self::setVarArray(array_column($tableDefinition, 'Default', 'Field'), STORE_TABLE_DEFAULT);
        self::setVarArray(array_column($tableDefinition, 'Type', 'Field'), STORE_TABLE_COLUMN_TYPES);
    }
417
418
419
420
421
}