Issues (55)

src/components/FormComponent.php (1 issue)

Severity
1
<?php
2
3
namespace CloudControl\Cms\components;
4
5
6
use CloudControl\Cms\cc\Application;
7
use CloudControl\Cms\cc\Request;
8
use CloudControl\Cms\storage\Storage;
9
10
class FormComponent Extends BaseComponent
11
{
12
    const GET_PARAMETER_PATH = 'path';
13
14
    const PARAMETER_CMS_PREFIX = 'cmsPrefix';
15
    const PARAMETER_DOCUMENT_TYPE = 'documentType';
16
    const PARAMETER_DOCUMENT_TYPES = 'documentTypes';
17
    const PARAMETER_FORM_ID = 'formId';
18
    const PARAMETER_FORM_PARAMETER_NAME = 'formParameterName';
19
    const PARAMETER_HIDE_TITLE_AND_STATE = 'hideTitleAndState';
20
    const PARAMETER_RESPONSE_FOLDER = 'responseFolder';
21
    const PARAMETER_SMALLEST_IMAGE = 'smallestImage';
22
    const PARAMETER_SUBMIT_ONCE_PER_SESSION = 'submitOncePerSession';
23
    const PARAMETER_SUB_TEMPLATE = 'subTemplate';
24
    const PARAMETER_THANK_YOU_MESSAGE = 'thankYouMessage';
25
26
    const SESSION_PARAMETER_CLOUDCONTROL = 'cloudcontrol';
27
    const SESSION_PARAMETER_FORM_COMPONENT = 'FormComponent';
28
    /**
29
     * @var null|string
30
     */
31
    protected $documentType;
32
    /**
33
     * @var null|string
34
     */
35
    protected $responseFolder;
36
    /**
37
     * @var string
38
     */
39
    protected $subTemplate = 'cms/documents/document-form-form';
40
    /**
41
     * @var string
42
     */
43
    protected $formParameterName = 'form';
44
    /**
45
     * @var string
46
     */
47
    protected $thankYouMessage = 'Thank you for sending us your response.';
48
49
    /**
50
     * @var bool
51
     */
52
    protected $submitOncePerSession = false;
53
54
    /**
55
     * @var string
56
     */
57
    protected $formId;
58
    /**
59
     * @var null|string
60
     */
61
    protected $getPathBackup;
62
63
    /**
64
     * @var null|\stdClass
65
     */
66
    protected $userSessionBackup;
67
68
    /**
69
     * @param Storage $storage
70
     *
71
     * @return void
72
     * @throws \Exception
73
     */
74
    public function run(Storage $storage)
75
    {
76
        parent::run($storage);
77
        $this->checkParameters();
78
        $this->checkRequiredParameters();
79
        $this->setFormId();
80
        $this->initialize($storage);
81
        $this->checkSubmit($storage);
82
    }
83
84
    /**
85
     * @param null|Application $application
86
     *
87
     * @throws \Exception
88
     */
89
    public function render($application = null)
90
    {
91
        $request = $this->setPathBackup();
92
        $form = $this->renderTemplate($this->subTemplate);
93
        $this->resetPathBackup($request);
94
        $this->setFormParameter($form);
95
96
        parent::render($application);
97
    }
98
99
    /**
100
     * Checks if parameters were given in the CMS configuration and
101
     * sets them to their respective fields
102
     */
103
    protected function checkParameters()
104
    {
105
        $this->checkDocumentTypeParameter();
106
        $this->checkResponseFolderParameter();
107
        $this->checkSubTemplateParameter();
108
        $this->checkFormParameterNameParameter();
109
        $this->checkThankYouMessageParameter();
110
        $this->checkSubmitOncePerSessionParameter();
111
    }
112
113
    /**
114
     * Sets variables needed for rendering the form template
115
     *
116
     * @param Storage $storage
117
     */
118
    protected function initialize($storage)
119
    {
120
        $this->parameters[self::PARAMETER_SMALLEST_IMAGE] = $storage->getImageSet()->getSmallestImageSet();
121
        $this->parameters[self::PARAMETER_CMS_PREFIX] = '';
122
123
        $this->parameters[self::PARAMETER_DOCUMENT_TYPE] = $this->storage->getDocumentTypes()->getDocumentTypeBySlug($this->documentType,
124
            true);
125
        $this->parameters[self::PARAMETER_DOCUMENT_TYPES] = $this->storage->getDocumentTypes()->getDocumentTypes();
126
        $this->parameters[self::PARAMETER_HIDE_TITLE_AND_STATE] = true;
127
        $this->parameters[self::PARAMETER_FORM_ID] = $this->formId;
128
    }
129
130
    /**
131
     * If the form has been submitted, save the document
132
     * Calls $this->postSubmit() afterwards
133
     *
134
     * @param Storage $storage
135
     * @throws \Exception
136
     */
137
    protected function checkSubmit($storage)
138
    {
139
        if ($this->isFormSubmitted($this->request) && $this->isSubmitAllowed()) {
140
            $postValues = $this->getPostValues($this->request);
141
            $this->setUserSessionBackup();
142
            $storage->getDocuments()->addDocument($postValues);
143
            $this->restoreUserSessionBackup();
144
            $this->setSubmitToSession();
145
            $this->postSubmit($postValues, $storage);
146
        }
147
    }
148
149
    /**
150
     * Hook for derived classes to take actions after
151
     * submitting the form
152
     *
153
     * @param $postValues
154
     * @param Storage $storage
155
     */
156
    protected function postSubmit(
157
        /** @scrutinizer ignore-unused */
158
        $postValues,
159
        /** @scrutinizer ignore-unused */
160
        $storage
161
    )
162
    {
163
    }
164
165
    /**
166
     * Sets a unique id for this particular form, so it can recognize
167
     * it when a submit occurs
168
     */
169
    protected function setFormId()
170
    {
171
        if (isset($_SESSION[self::SESSION_PARAMETER_FORM_COMPONENT][$this->formParameterName][self::PARAMETER_FORM_ID])) {
172
            $this->formId = $_SESSION[self::SESSION_PARAMETER_FORM_COMPONENT][$this->formParameterName][self::PARAMETER_FORM_ID];
173
        } else {
174
            $_SESSION[self::SESSION_PARAMETER_FORM_COMPONENT][$this->formParameterName][self::PARAMETER_FORM_ID] = (string)microtime(true);
175
            $_SESSION[self::SESSION_PARAMETER_FORM_COMPONENT][$this->formParameterName]['submitted'] = false;
176
            $this->formId = $_SESSION[self::SESSION_PARAMETER_FORM_COMPONENT][$this->formParameterName][self::PARAMETER_FORM_ID];
177
        }
178
    }
179
180
    /**
181
     * @param Request $request
182
     * @return array
183
     */
184
    protected function getPostValues($request)
185
    {
186
        $postValues = $request::$post;
187
        $postValues[self::PARAMETER_DOCUMENT_TYPE] = $this->documentType;
188
        $postValues[self::GET_PARAMETER_PATH] = $this->responseFolder;
189
        $postValues['title'] = date('r') . ' - From: ' . $request::$requestUri;
190
191
        return $postValues;
192
    }
193
194
    /**
195
     * Temporarily stores the current user session in a backup variable
196
     * and sets a fake user instead
197
     */
198
    protected function setUserSessionBackup()
199
    {
200
        $this->userSessionBackup = isset($_SESSION[self::SESSION_PARAMETER_CLOUDCONTROL]) ? $_SESSION[self::SESSION_PARAMETER_CLOUDCONTROL] : null;
201
        $fakeUser = new \stdClass();
202
        $fakeUser->username = self::SESSION_PARAMETER_FORM_COMPONENT;
203
        $_SESSION[self::SESSION_PARAMETER_CLOUDCONTROL] = $fakeUser;
204
    }
205
206
    /**
207
     * Removes the fake user and restores the existing user
208
     * session if it was there
209
     */
210
    protected function restoreUserSessionBackup()
211
    {
212
        if ($this->userSessionBackup === null) {
213
            unset($_SESSION[self::SESSION_PARAMETER_CLOUDCONTROL]);
214
        } else {
215
            $_SESSION[self::SESSION_PARAMETER_CLOUDCONTROL] = $this->userSessionBackup;
216
        }
217
    }
218
219
    protected function setSubmitToSession()
220
    {
221
        $_SESSION[self::SESSION_PARAMETER_FORM_COMPONENT][$this->formParameterName]['submitted'] = true;
222
    }
223
224
    protected function isSubmitAllowed()
225
    {
226
        return !($this->submitOncePerSession === true && $_SESSION[self::SESSION_PARAMETER_FORM_COMPONENT][$this->formParameterName]['submitted'] === true);
227
    }
228
229
    protected function checkDocumentTypeParameter()
230
    {
231
        if (isset($this->parameters[self::PARAMETER_DOCUMENT_TYPE])) {
232
            $this->documentType = $this->parameters[self::PARAMETER_DOCUMENT_TYPE];
233
            unset($this->parameters[self::PARAMETER_DOCUMENT_TYPE]);
234
        }
235
    }
236
237
    protected function checkResponseFolderParameter()
238
    {
239
        if (isset($this->parameters[self::PARAMETER_RESPONSE_FOLDER])) {
240
            $this->responseFolder = $this->parameters[self::PARAMETER_RESPONSE_FOLDER];
241
            unset($this->parameters[self::PARAMETER_RESPONSE_FOLDER]);
242
        }
243
    }
244
245
    protected function checkSubTemplateParameter()
246
    {
247
        if (isset($this->parameters[self::PARAMETER_SUB_TEMPLATE])) {
248
            $this->subTemplate = $this->parameters[self::PARAMETER_SUB_TEMPLATE];
249
            unset($this->parameters[self::PARAMETER_SUB_TEMPLATE]);
250
        }
251
    }
252
253
    protected function checkFormParameterNameParameter()
254
    {
255
        if (isset($this->parameters[self::PARAMETER_FORM_PARAMETER_NAME])) {
256
            $this->formParameterName = $this->parameters[self::PARAMETER_FORM_PARAMETER_NAME];
257
            unset($this->parameters[self::PARAMETER_FORM_PARAMETER_NAME]);
258
        }
259
    }
260
261
    protected function checkThankYouMessageParameter()
262
    {
263
        if (isset($this->parameters[self::PARAMETER_THANK_YOU_MESSAGE])) {
264
            $this->thankYouMessage = $this->parameters[self::PARAMETER_THANK_YOU_MESSAGE];
265
            unset($this->parameters[self::PARAMETER_THANK_YOU_MESSAGE]);
266
        }
267
    }
268
269
    protected function checkSubmitOncePerSessionParameter()
270
    {
271
        if (isset($this->parameters[self::PARAMETER_SUBMIT_ONCE_PER_SESSION])) {
272
            $this->submitOncePerSession = $this->parameters[self::PARAMETER_SUBMIT_ONCE_PER_SESSION] === 'true';
273
            unset($this->parameters[self::PARAMETER_SUBMIT_ONCE_PER_SESSION]);
274
        }
275
    }
276
277
    /**
278
     * @throws \Exception
279
     */
280
    protected function checkRequiredParameters()
281
    {
282
        if ($this->documentType === null || $this->responseFolder === null) {
283
            throw new \RuntimeException('Parameters `documentType` and `responseFolder` are required for usage with this form');
284
        }
285
    }
286
287
    /**
288
     * @return Request
289
     */
290
    protected function setPathBackup()
291
    {
292
        $request = $this->request;
293
        if (isset($request::$get[self::GET_PARAMETER_PATH])) {
294
            $this->getPathBackup = $request::$get[self::GET_PARAMETER_PATH];
295
        }
296
        $request::$get[self::GET_PARAMETER_PATH] = $this->responseFolder;
297
298
        return $request;
299
    }
300
301
    /**
302
     * @param Request $request
303
     */
304
    protected function resetPathBackup($request)
305
    {
306
        if ($this->getPathBackup !== null) {
307
            $request::$get[self::GET_PARAMETER_PATH] = $this->getPathBackup;
308
        } else {
309
            $get = $request::$get;
310
            unset($get[self::GET_PARAMETER_PATH]);
311
            $request::$get = $get;
312
        }
313
    }
314
315
    /**
316
     * @param string|null $form
317
     */
318
    protected function setFormParameter($form)
319
    {
320
        if ($this->isFormSubmitted($this->request) || $this->isSubmitAllowed() === false) {
321
            $this->parameters[$this->formParameterName] = '<a name="' . $this->formId . '"></a>' . $this->thankYouMessage;
322
        } else {
323
            $this->parameters[$this->formParameterName] = $form;
324
        }
325
    }
326
327
    /**
328
     * Checks if this form has been submitted
329
     *
330
     * @param \CloudControl\Cms\cc\Request $request
331
     * @return bool
332
     */
333
    protected function isFormSubmitted($request)
334
    {
335
        if (empty($request::$post)) {
336
            return false;
337
        }
338
339
        return $this->checkFormId($request);
340
    }
341
342
    /**
343
     * Checks if the form id is set in all places
344
     * @param $request
345
     * @return bool
346
     */
347
    private function checkFormId($request)
348
    {
349
        if (!$this->checkFormIdInPost($request)) {
350
            return false;
351
        }
352
353
        return $this->checkFormIdInSession();
354
355
356
    }
357
358
    /**
359
     * Checks if form id is set in _POST variable
360
     *
361
     * @param $request
362
     * @return bool
363
     */
364
    private function checkFormIdInPost($request)
365
    {
366
        if (!isset($request::$post[self::PARAMETER_FORM_ID])) {
367
            return false;
368
        }
369
370
        if (!$request::$post[self::PARAMETER_FORM_ID] === $this->formId) {
371
            return false;
372
        }
373
374
        return true;
375
    }
376
377
    /**
378
     * Checks if form is is set in _SESSION variable
379
     * @return bool
380
     */
381
    private function checkFormIdInSession()
382
    {
383
        if (!isset($_SESSION[self::SESSION_PARAMETER_FORM_COMPONENT][$this->formParameterName][self::PARAMETER_FORM_ID])) {
384
            return false;
385
        }
386
387
        if (!$_SESSION[self::SESSION_PARAMETER_FORM_COMPONENT][$this->formParameterName][self::PARAMETER_FORM_ID] === $this->formId) {
0 ignored issues
show
The condition ! $_SESSION[self::SESSIO...M_ID] === $this->formId is always false.
Loading history...
388
            return false;
389
        }
390
391
        return true;
392
    }
393
}