QuickFormQuery.php 10.5 KB
Newer Older
1
2
3
4
5
6
7
8
<?php
/**
 * Created by PhpStorm.
 * User: ep
 * Date: 12/23/15
 * Time: 6:33 PM
 */

Carsten  Rose's avatar
Carsten Rose committed
9

10
11
namespace qfq;

Carsten  Rose's avatar
Carsten Rose committed
12
use qfq;
13
14
15
16
17
18
19
20
21

//use qfq\Report;

//use qfq\BuildFormPlain;
//use qfq\BuildFormTable;
//use qfq\BuildFormBootstrap;
//use qfq\UserException;
//use qfq\CodeException;
//use qfq\DbException;
22
//use qfq\helper;
23
//use qfq\Store;
Carsten  Rose's avatar
Carsten Rose committed
24

Carsten  Rose's avatar
Carsten Rose committed
25

26
require_once(__DIR__ . '/../qfq/store/Store.php');
Carsten  Rose's avatar
Carsten Rose committed
27
require_once(__DIR__ . '/../qfq/Constants.php');
28
require_once(__DIR__ . '/../qfq/Save.php');
Carsten  Rose's avatar
Carsten Rose committed
29
require_once(__DIR__ . '/../qfq/helper/KeyValueStringParser.php');
30
require_once(__DIR__ . '/../qfq/helper/HelperFormElement.php');
Carsten  Rose's avatar
Carsten Rose committed
31
require_once(__DIR__ . '/../qfq/exceptions/UserException.php');
32
33
require_once(__DIR__ . '/../qfq/exceptions/CodeException.php');
require_once(__DIR__ . '/../qfq/exceptions/DbException.php');
34
require_once(__DIR__ . '/../qfq/Database.php');
Carsten  Rose's avatar
Carsten Rose committed
35
require_once(__DIR__ . '/../qfq/Evaluate.php');
36
37
38
require_once(__DIR__ . '/../qfq/BuildFormPlain.php');
require_once(__DIR__ . '/../qfq/BuildFormTable.php');
require_once(__DIR__ . '/../qfq/BuildFormBootstrap.php');
39
require_once(__DIR__ . '/../qfq/report/Report.php');
40

41
42
43
44
45
46
47
48
49
50
51
52
/*
 * Form will be called
 * a) with a SIP identifier, or
 * b) without a SIP identifier (form setting has to allow this) and will create on the fly a new SIP.
 *
 * The SIP-Store stores:
 *  form=<formname>
 *  r=<record id>  (table.id for a single record form)
 *  keySemId,keySemIduser
 *  <further individual variables>
 */

Carsten  Rose's avatar
Carsten Rose committed
53
/**
54
 * Class Qfq
Carsten  Rose's avatar
Carsten Rose committed
55
56
 * @package qfq
 */
57
class QuickFormQuery {
Carsten  Rose's avatar
Carsten Rose committed
58

59
    /**
60
     * @var \qfq\Store instantiated class
61
     */
Carsten  Rose's avatar
Carsten Rose committed
62
    protected $store = null;
63
64
65
    /**
     * @var Database instantiated class
     */
66
    protected $db = null;
67
68
69
70
71
    /**
     * @var Evaluate instantiated class
     */
    protected $eval = null;

72
73
74
    protected $formSpec = array();  // Form Definition: copy of the loaded form
    protected $feSpecAction = array(); // FormEelement Definition: all formElement.class='action' of the loaded form
    protected $feSpecNative = array(); // FormEelement Definition: all formElement.class='native' of the loaded form
75
76
77
78
79
80
81
82
83
84
85
86

    /*
     * TODO:
     *  Preparation: setup logging, database access, record locking
     *  fill stores
     *  Check permission_create / permission_update
     *  Multi: iterate over all records, Single: activate record
     *      Check mode: Load | Save
     *      doActions 'Before'
     *      Do all FormElements
     *      doActions 'After'
     */
87
88


89
90
    //TODO: remove this as soon as Report use STORE_TYPO3 to transfer the bodytext.
    private $bodytext = '';
91

92
93
94
95
96
    /**
     * Construct the Form Class and Store too. This is the base initialization moment.
     *
     * As a result of instantiating of Form, the class Store will initially called the first time and therefore instantiated automatically.
     * Store might throw an exception, in case the URL-passed SIP is invalid.
97
     *
98
     * @param string $bodytext
99
     */
100
    public function __construct($bodytext = '', $phpUnit = false) {
101

102
        try {
103
104
105
            //TODO: remove this as soon as Report use STORE_TYPO3 to transfer the bodytext.
            $this->bodytext = $bodytext;

106
            $this->store = Store::getInstance($bodytext, $phpUnit);
107
108
            $this->db = new Database();
            $this->eval = new Evaluate($this->store, $this->db);
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
        } catch (UserException $e) {
            echo $e->formatMessage();
            exit;
        } catch (CodeException $e) {
            echo $e->formatMessage();
            exit;
        } catch (DbException $e) {
            echo $e->formatMessage();
            exit;
        } catch (\Exception $e) {
            echo "Generic Exception: " . $e->getMessage();
            exit;
        }


Carsten  Rose's avatar
Carsten Rose committed
125
126
    }

127
128
    /**
     * @return string
Carsten  Rose's avatar
Carsten Rose committed
129
     */
130
    public function process() {
131
132
        $html = '';
        $build = null;
133
        $master = null;
134

Carsten  Rose's avatar
Carsten Rose committed
135
136
        mb_internal_encoding("UTF-8");

137
138
        try {

139
140
            $html .= $this->doForm();
//            $html .= $this->doReport();
141
142
143
144
145
146
147
148
149
150

        } catch (UserException $e) {
            echo $e->formatMessage();
        } catch (CodeException $e) {
            echo $e->formatMessage();
        } catch (DbException $e) {
            echo $e->formatMessage();
        } catch (\Exception $e) {
            echo "Generic Exception: " . $e->getMessage();
        }
Carsten  Rose's avatar
Carsten Rose committed
151

152
        return $html;
153
154
    }

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
    /**
     * Process form (load or save) if a formname is found.
     * @return string
     * @throws CodeException
     * @throws UserException
     */
    private function doForm() {
        $html = '';

        // Form action: load or save?
        $mode = isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' ? FORM_SAVE : FORM_LOAD;

        $formName = $this->loadFormSpecification($mode);
        if ($formName === false)
            return '';

        $sipFound = $this->validateForm();
        if (!$sipFound) {
            $this->store->createSipAfterFormLoad($formName);
        }
        $this->store->fillStoreTableDefaultColumnType($this->formSpec['tableName']);

        switch ($this->formSpec['render']) {
            case 'plain':
                $build = new BuildFormPlain($this->formSpec, $this->feSpecAction, $this->feSpecNative);
                break;
            case 'table':
                $build = new BuildFormTable($this->formSpec, $this->feSpecAction, $this->feSpecNative);
                break;
            case 'bootstrap':
                $build = new BuildFormBootstrap($this->formSpec, $this->feSpecAction, $this->feSpecNative);
                break;
            default:
                throw new CodeException("This statement should never be reached", ERROR_CODE_SHOULD_NOT_HAPPEN);
        }

        switch ($mode) {
            case FORM_LOAD:
                $html .= $build->process();
                break;
            case FORM_SAVE:
                $save = new Save($this->formSpec, $this->feSpecAction, $this->feSpecNative);
                $save->process();
                break;
            default:
                throw new CodeException("This statement should never be reached", ERROR_CODE_SHOULD_NOT_HAPPEN);
        }
        return $html;

    }

206
    /**
207
208
209
210
211
212
213
     * Loads specification of recent form.
     * Evaluates Form and all FormElements.
     *
     * Loaded Form is in  $this->formSpec
     * Loaded 'action' FormElements are in $this->feSpecAction
     * Loaded 'native' FormElements are in $this->feSpecNative
     *
214
     * @param string $mode FORM_LOAD|FORM_SAVE
215
     * @return string|bool if found the formName, else 'false'.
216
     * @throws DbException
217
     * @throws UserException
218
     */
219
    private function loadFormSpecification($mode) {
Carsten  Rose's avatar
Carsten Rose committed
220

221
222
223
        if (false === $formName = $this->getFormName()) {
            return false;
        }
224
        $this->store->setVar(SYSTEM_FORM, $formName, STORE_SYSTEM);
Carsten  Rose's avatar
Carsten Rose committed
225

226
227
228
        $form = $this->db->sql("SELECT * FROM Form AS f WHERE f.name LIKE ? AND f.deleted='no'", ROW_EXACT_1, [$formName], 'Form not found or multiple forms with the same name.');

        $this->formSpec = $this->eval->parseArray($form);
229
        HelperFormElement::explodeFieldParameter($this->formSpec);
230

Carsten  Rose's avatar
Carsten Rose committed
231
        // Clear
232
233
        $this->store->setVar(SYSTEM_FORM_ELEMENT, '', STORE_SYSTEM);

234
        // FE: Action
235
        $this->feSpecAction = $this->eval->parseArray($this->db->sql(SQL_FORM_ELEMENT_ALL_CONTAINER, ROW_REGULAR, ['no', $this->formSpec["id"], 'action']));
236
        HelperFormElement::explodeFieldParameter($this->feSpecAction);
237
238

        // FE: Native & Container
239
240
241
242
243
244
245
246
247
248
249
250
251
        // "SELECT *, ? AS 'nestedInFieldSet' FROM FormElement AS fe WHERE fe.formId = ? AND fe.deleted = 'no' AND FIND_IN_SET(fe.class, ? ) AND fe.feIdContainer = ? AND fe.enabled='yes' ORDER BY fe.ord, fe.id";
        switch ($mode) {
            case FORM_LOAD:
                $this->feSpecNative = $this->db->sql(SQL_FORM_ELEMENT_SPECIFIC_CONTAINER, ROW_REGULAR, ['no', $this->formSpec["id"], 'native,container', 0]);
                break;

            case FORM_SAVE:
                $this->feSpecNative = $this->db->sql(SQL_FORM_ELEMENT_ALL_CONTAINER, ROW_REGULAR, ['no', $this->formSpec["id"], 'native']);
                break;

            default:
        }

252
        HelperFormElement::explodeFieldParameter($this->feSpecNative);
253
254

        return $formName;
Carsten  Rose's avatar
Carsten Rose committed
255
256
    }

Carsten  Rose's avatar
Carsten Rose committed
257
    /**
258
     * @return string|bool     Formname (Form.name) or FALSE if no formname found.
Carsten  Rose's avatar
Carsten Rose committed
259
     * @throws UserException
260
     * @throws CodeException
Carsten  Rose's avatar
Carsten Rose committed
261
262
     */

Carsten  Rose's avatar
Carsten Rose committed
263
264
    private function getFormName() {

265
        $formName = $this->store->getVar(SIP_FORM, STORE_TYPO3 . STORE_SIP . STORE_CLIENT);
266
        return $formName;
267
    }
Carsten  Rose's avatar
Carsten Rose committed
268

269
270
271
272
273
    /**
     * @return bool - 'true' if SIP exists, else 'false'
     * @throws CodeException
     * @throws UserException
     */
Carsten  Rose's avatar
Carsten Rose committed
274
    private function validateForm() {
275
276
277
278
279

        // Retrieve record_id either from SIP (prefered) or via URL
        $r = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_CLIENT);

        // If there is a record_id>0: EDIT else NEW
280
        $mode = ($r > 0) ? $this->formSpec['permitEdit'] : $this->formSpec['permitNew'];
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308

        $feUserLoggedIn = isset($GLOBALS["TSFE"]->fe_user->user["uid"]) && $GLOBALS["TSFE"]->fe_user->user["uid"] > 0;

        $sipFound = $this->store->getVar(SIP_SIP, STORE_SIP) !== false;

        switch ($mode) {
            case  FORM_PERMISSION_SIP:
                if (!$sipFound) {
                    throw new UserException("SIP Parameter needed for this form.", ERROR_SIP_NEEDED_FOR_THIS_FORM);
                }
                break;
            case  FORM_PERMISSION_LOGGED_IN:
                if (!$feUserLoggedIn) {
                    throw new UserException("User not logged in.", ERROR_USER_NOT_LOGGED_IN);
                }
                break;
            case FORM_PERMISSION_LOGGED_OUT:
                if ($feUserLoggedIn) {
                    throw new UserException("User logged in.", ERROR_USER_LOGGED_IN);
                }
                break;
            case FORM_PERMISSION_ALWAYS:
                break;
            case FORM_PERMISSION_NEVER:
                throw new UserException("Loading form forbidden.", ERROR_FORM_FORBIDDEN);
            default:
                throw new CodeException("Unknown permission mode: '" . $mode . "'", ERROR_FORM_UNKNOWN_PERMISSION_MODE);
        }
Carsten  Rose's avatar
Carsten Rose committed
309

Carsten  Rose's avatar
Carsten Rose committed
310
        // Form Definition valid?
311
        if ($this->formSpec['multiMode'] !== 'none' && $this->formSpec['multiSql'] === '') {
Carsten  Rose's avatar
Carsten Rose committed
312
313
314
            throw new UserException("MultiMode selected, but MultiSQL missing", ERROR_MULTI_SQL_MISSING);
        }

315
        return $sipFound;
316
    }
Carsten  Rose's avatar
Carsten Rose committed
317

318
319
320
321
322
323
324
325
326
    private function doReport() {
        $report = new Report();

        $html = $report->process($this->bodytext);

        return $html;

    }

327
}