Completed
Push — middleware ( 9c87df...9c572f )
by Romain
02:14 queued 12s
created

FormObject::injectConfigurationFactory()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
/*
3
 * 2017 Romain CANON <[email protected]>
4
 *
5
 * This file is part of the TYPO3 Formz project.
6
 * It is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License, either
8
 * version 3 of the License, or any later version.
9
 *
10
 * For the full copyright and license information, see:
11
 * http://www.gnu.org/licenses/gpl-3.0.html
12
 */
13
14
namespace Romm\Formz\Form;
15
16
use Romm\ConfigurationObject\ConfigurationObjectFactory;
17
use Romm\ConfigurationObject\ConfigurationObjectInstance;
18
use Romm\Formz\Configuration\ConfigurationFactory;
19
use Romm\Formz\Configuration\Form\Form;
20
use Romm\Formz\Core\Core;
21
use Romm\Formz\Error\FormResult;
22
use Romm\Formz\Service\CacheService;
23
use TYPO3\CMS\Extbase\Error\Result;
24
25
/**
26
 * This is the object representation of a form. In here we can manage which
27
 * properties the form does have, its configuration, and more.
28
 */
29
class FormObject
30
{
31
32
    /**
33
     * @var ConfigurationFactory
34
     */
35
    protected $configurationFactory;
36
37
    /**
38
     * Name of the form.
39
     *
40
     * @var string
41
     */
42
    protected $name;
43
44
    /**
45
     * @var string
46
     */
47
    protected $className;
48
49
    /**
50
     * The properties of the form.
51
     *
52
     * @var array
53
     */
54
    protected $properties = [];
55
56
    /**
57
     * Contains the form configuration.
58
     *
59
     * @var array
60
     */
61
    protected $configurationArray = [];
62
63
    /**
64
     * Contains the form configuration object, which was created from the
65
     * configuration array.
66
     *
67
     * @var ConfigurationObjectInstance
68
     */
69
    protected $configurationObject;
70
71
    /**
72
     * @var Result
73
     */
74
    protected $configurationValidationResult;
75
76
    /**
77
     * @var FormResult
78
     */
79
    protected $lastValidationResult;
80
81
    /**
82
     * @var string
83
     */
84
    protected $hash;
85
86
    /**
87
     * @var string
88
     */
89
    protected $lastConfigurationHash;
90
91
    /**
92
     * @var bool
93
     */
94
    protected $hashShouldBeCalculated = true;
95
96
    /**
97
     * You should never create a new instance of this class directly, use the
98
     * `FormObjectFactory->getInstanceFromClassName()` function instead.
99
     *
100
     * @param string $className
101
     * @param string $name
102
     */
103
    public function __construct($className, $name)
104
    {
105
        $this->className = $className;
106
        $this->name = $name;
107
    }
108
109
    /**
110
     * @return Form
111
     */
112
    public function getConfiguration()
113
    {
114
        /** @var Form $configuration */
115
        $configuration = $this->getConfigurationObject()->getObject(true);
116
117
        return $configuration;
118
    }
119
120
    /**
121
     * @return string
122
     */
123
    public function getName()
124
    {
125
        return $this->name;
126
    }
127
128
    /**
129
     * @return string
130
     */
131
    public function getClassName()
132
    {
133
        return $this->className;
134
    }
135
136
    /**
137
     * Registers a new property for this form.
138
     *
139
     * @param string $name
140
     * @return $this
141
     */
142
    public function addProperty($name)
143
    {
144
        if (false === $this->hasProperty($name)) {
145
            $this->properties[] = $name;
146
            $this->hashShouldBeCalculated = true;
147
        }
148
149
        return $this;
150
    }
151
152
    /**
153
     * @param string $name
154
     * @return bool
155
     */
156
    public function hasProperty($name)
157
    {
158
        return in_array($name, $this->properties);
159
    }
160
161
    /**
162
     * @return array
163
     */
164
    public function getProperties()
165
    {
166
        return $this->properties;
167
    }
168
169
    /**
170
     * Returns the hash, which should be calculated only once for performance
171
     * concerns.
172
     *
173
     * @return string
174
     */
175
    public function getHash()
176
    {
177
        if (true === $this->hashShouldBeCalculated
178
            || null === $this->hash
179
        ) {
180
            $this->hashShouldBeCalculated = false;
181
            $this->hash = $this->calculateHash();
182
        }
183
184
        return $this->hash;
185
    }
186
187
    /**
188
     * @return array
189
     * @internal Should not be used, it is here only for unit tests.
190
     */
191
    public function getConfigurationArray()
192
    {
193
        return $this->configurationArray;
194
    }
195
196
    /**
197
     * @param array $configuration
198
     * @return $this
199
     */
200
    public function setConfigurationArray($configuration)
201
    {
202
        $this->configurationArray = $this->sanitizeConfiguration($configuration);
203
        $this->hashShouldBeCalculated = true;
204
205
        return $this;
206
    }
207
208
    /**
209
     * Returns an instance of configuration object. Checks if it was previously
210
     * stored in cache, otherwise it is created from scratch.
211
     *
212
     * @return ConfigurationObjectInstance
213
     */
214
    protected function getConfigurationObject()
215
    {
216
        if (null === $this->configurationObject
217
            || $this->lastConfigurationHash !== $this->getHash()
218
        ) {
219
            $cacheInstance = CacheService::get()->getCacheInstance();
220
            $cacheIdentifier = 'configuration-' . $this->getHash();
221
            $this->lastConfigurationHash = $this->getHash();
222
223
            if ($cacheInstance->has($cacheIdentifier)) {
224
                $configurationObject = $cacheInstance->get($cacheIdentifier);
225
            } else {
226
                $configurationObject = $this->buildConfigurationObject();
227
228
                if (false === $configurationObject->getValidationResult()->hasErrors()) {
229
                    $cacheInstance->set($cacheIdentifier, $configurationObject);
230
                }
231
            }
232
233
            $this->configurationObject = $configurationObject;
234
        }
235
236
        return $this->configurationObject;
237
    }
238
239
    /**
240
     * This function will merge and return the validation results of both the
241
     * global Formz configuration object, and this form configuration object.
242
     *
243
     * @return Result
244
     */
245
    public function getConfigurationValidationResult()
246
    {
247
        if (null === $this->configurationValidationResult
248
            || $this->lastConfigurationHash !== $this->getHash()
249
        ) {
250
            $this->configurationValidationResult = new Result;
251
            $formzConfigurationValidationResult = $this->configurationFactory
252
                ->getFormzConfiguration()
253
                ->getValidationResult();
254
255
            $this->configurationValidationResult->merge($formzConfigurationValidationResult);
256
257
            $this->configurationValidationResult->forProperty('forms.' . $this->getClassName())
258
                ->merge($this->getConfigurationObject()->getValidationResult());
259
        }
260
261
        return $this->configurationValidationResult;
262
    }
263
264
    /**
265
     * @return ConfigurationObjectInstance
266
     */
267
    protected function buildConfigurationObject()
268
    {
269
        return ConfigurationObjectFactory::getInstance()
270
            ->get(Form::class, $this->configurationArray);
271
    }
272
273
    /**
274
     * This function will clean the configuration array by removing useless data
275
     * and updating needed ones.
276
     *
277
     * @param array $configuration
278
     * @return array
279
     */
280
    protected function sanitizeConfiguration(array $configuration)
281
    {
282
        // Removing configuration of fields which do not exist for this form.
283
        $sanitizedFieldsConfiguration = [];
284
        $fieldsConfiguration = (isset($configuration['fields']))
285
            ? $configuration['fields']
286
            : [];
287
288
        foreach ($this->properties as $property) {
289
            $sanitizedFieldsConfiguration[$property] = (isset($fieldsConfiguration[$property]))
290
                ? $fieldsConfiguration[$property]
291
                : [];
292
        }
293
294
        $configuration['fields'] = $sanitizedFieldsConfiguration;
295
296
        return $configuration;
297
    }
298
299
    /**
300
     * Returns the calculated hash of this class.
301
     *
302
     * @return string
303
     */
304
    protected function calculateHash()
305
    {
306
        return sha1(serialize($this));
307
    }
308
309
    /**
310
     * @param ConfigurationFactory $configurationFactory
311
     */
312
    public function injectConfigurationFactory(ConfigurationFactory $configurationFactory)
313
    {
314
        $this->configurationFactory = $configurationFactory;
315
    }
316
317
    /**
318
     * @return FormResult
319
     */
320
    public function getLastValidationResult()
321
    {
322
        return $this->lastValidationResult;
323
    }
324
325
    /**
326
     * @return bool
327
     */
328
    public function hasLastValidationResult()
329
    {
330
        return null !== $this->lastValidationResult;
331
    }
332
333
    /**
334
     * @param FormResult $lastValidationResult
335
     */
336
    public function setLastValidationResult($lastValidationResult)
337
    {
338
        $this->lastValidationResult = $lastValidationResult;
339
    }
340
341
    /**
342
     * When this instance is saved in TYPO3 cache, we need not to store all the
343
     * properties to increase performance.
344
     *
345
     * @return array
346
     */
347
    public function __sleep()
348
    {
349
        return ['name', 'className', 'properties', 'configurationArray', 'hash'];
350
    }
351
352
    /**
353
     * When this class is unserialized, we update the flag to know if the hash
354
     * should be calculated or not (if it was calculated before it was
355
     * serialized, there is no need to calculate it again).
356
     */
357
    public function __wakeup()
358
    {
359
        $this->hashShouldBeCalculated = (null === $this->hash);
360
361
        /** @var ConfigurationFactory $configurationFactory */
362
        $configurationFactory = Core::instantiate(ConfigurationFactory::class);
363
        $this->injectConfigurationFactory($configurationFactory);
364
    }
365
}
366