Completed
Push — unit-tests-validation ( 23f8f6...d146ca )
by Romain
02:30
created

FormObject::hasProperty()   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\Service\CacheService;
22
use TYPO3\CMS\Extbase\Error\Result;
23
24
/**
25
 * This is the object representation of a form. In here we can manage which
26
 * properties the form does have, its configuration, and more.
27
 */
28
class FormObject
29
{
30
31
    /**
32
     * @var ConfigurationFactory
33
     */
34
    protected $configurationFactory;
35
36
    /**
37
     * Name of the form.
38
     *
39
     * @var string
40
     */
41
    protected $name;
42
43
    /**
44
     * @var string
45
     */
46
    protected $className;
47
48
    /**
49
     * The properties of the form.
50
     *
51
     * @var array
52
     */
53
    protected $properties = [];
54
55
    /**
56
     * Contains the form configuration.
57
     *
58
     * @var array
59
     */
60
    protected $configurationArray = [];
61
62
    /**
63
     * Contains the form configuration object, which was created from the
64
     * configuration array.
65
     *
66
     * @var ConfigurationObjectInstance
67
     */
68
    protected $configurationObject;
69
70
    /**
71
     * @var string
72
     */
73
    protected $hash;
74
75
    /**
76
     * @var bool
77
     */
78
    protected $hashShouldBeCalculated = true;
79
80
    /**
81
     * You should never create a new instance of this class directly, use the
82
     * `FormObjectFactory->getInstanceFromClassName()` function instead.
83
     *
84
     * @param string $className
85
     * @param string $name
86
     */
87
    public function __construct($className, $name)
88
    {
89
        $this->className = $className;
90
        $this->name = $name;
91
    }
92
93
    /**
94
     * @return Form
95
     */
96
    public function getConfiguration()
97
    {
98
        /** @var Form $configuration */
99
        $configuration = $this->getConfigurationObject()->getObject(true);
100
101
        return $configuration;
102
    }
103
104
    /**
105
     * @return string
106
     */
107
    public function getName()
108
    {
109
        return $this->name;
110
    }
111
112
    /**
113
     * @return string
114
     */
115
    public function getClassName()
116
    {
117
        return $this->className;
118
    }
119
120
    /**
121
     * Registers a new property for this form.
122
     *
123
     * @param string $name
124
     * @return $this
125
     */
126
    public function addProperty($name)
127
    {
128
        if (false === $this->hasProperty($name)) {
129
            $this->properties[] = $name;
130
            $this->hashShouldBeCalculated = true;
131
        }
132
133
        return $this;
134
    }
135
136
    /**
137
     * @param string $name
138
     * @return bool
139
     */
140
    public function hasProperty($name)
141
    {
142
        return in_array($name, $this->properties);
143
    }
144
145
    /**
146
     * @return array
147
     */
148
    public function getProperties()
149
    {
150
        return $this->properties;
151
    }
152
153
    /**
154
     * Returns the hash, which should be calculated only once for performance
155
     * concerns.
156
     *
157
     * @return string
158
     */
159
    public function getHash()
160
    {
161
        if (true === $this->hashShouldBeCalculated
162
            || null === $this->hash
163
        ) {
164
            $this->hashShouldBeCalculated = false;
165
            $this->hash = $this->calculateHash();
166
        }
167
168
        return $this->hash;
169
    }
170
171
    /**
172
     * @return array
173
     * @internal Should not be used, it is here only for unit tests.
174
     */
175
    public function getConfigurationArray()
176
    {
177
        return $this->configurationArray;
178
    }
179
180
    /**
181
     * @param array $configuration
182
     * @return $this
183
     */
184
    public function setConfigurationArray($configuration)
185
    {
186
        $this->configurationArray = $this->sanitizeConfiguration($configuration);
187
        $this->hashShouldBeCalculated = true;
188
189
        return $this;
190
    }
191
192
    /**
193
     * Returns an instance of configuration object. Checks if it was previously
194
     * stored in cache, otherwise it is created from scratch.
195
     *
196
     * @return ConfigurationObjectInstance
197
     * @internal
198
     */
199
    public function getConfigurationObject()
200
    {
201
        if (null === $this->configurationObject) {
202
            $cacheInstance = CacheService::get()->getCacheInstance();
203
            $cacheIdentifier = 'configuration-' . $this->getHash();
204
205
            if ($cacheInstance->has($cacheIdentifier)) {
206
                $configurationObject = $cacheInstance->get($cacheIdentifier);
207
            } else {
208
                $configurationObject = $this->buildConfigurationObject();
209
210
                if (false === $configurationObject->getValidationResult()->hasErrors()) {
211
                    $cacheInstance->set($cacheIdentifier, $configurationObject);
212
                }
213
            }
214
215
            $this->configurationObject = $configurationObject;
216
        }
217
218
        return $this->configurationObject;
219
    }
220
221
    /**
222
     * This function will merge and return the validation results of both the
223
     * global Formz configuration object, and this form configuration object.
224
     *
225
     * @return Result
226
     */
227
    public function getConfigurationValidationResult()
228
    {
229
        $result = new Result();
230
        $formzConfigurationValidationResult = $this->configurationFactory
231
            ->getFormzConfiguration()
232
            ->getValidationResult();
233
234
        $result->merge($formzConfigurationValidationResult);
235
236
        $result->forProperty('forms.' . $this->getClassName())
237
            ->merge($this->getConfigurationObject()->getValidationResult());
238
239
        return $result;
240
    }
241
242
    /**
243
     * @return ConfigurationObjectInstance
244
     */
245
    protected function buildConfigurationObject()
246
    {
247
        return ConfigurationObjectFactory::getInstance()
248
            ->get(Form::class, $this->configurationArray);
249
    }
250
251
    /**
252
     * This function will clean the configuration array by removing useless data
253
     * and updating needed ones.
254
     *
255
     * @param array $configuration
256
     * @return array
257
     */
258
    protected function sanitizeConfiguration(array $configuration)
259
    {
260
        // Removing configuration of fields which do not exist for this form.
261
        $sanitizedFieldsConfiguration = [];
262
        $fieldsConfiguration = (isset($configuration['fields']))
263
            ? $configuration['fields']
264
            : [];
265
266
        foreach ($this->properties as $property) {
267
            $sanitizedFieldsConfiguration[$property] = (isset($fieldsConfiguration[$property]))
268
                ? $fieldsConfiguration[$property]
269
                : [];
270
        }
271
272
        $configuration['fields'] = $sanitizedFieldsConfiguration;
273
274
        return $configuration;
275
    }
276
277
    /**
278
     * Returns the calculated hash of this class.
279
     *
280
     * @return string
281
     */
282
    protected function calculateHash()
283
    {
284
        return sha1(serialize($this));
285
    }
286
287
    /**
288
     * @param ConfigurationFactory $configurationFactory
289
     */
290
    public function injectConfigurationFactory(ConfigurationFactory $configurationFactory)
291
    {
292
        $this->configurationFactory = $configurationFactory;
293
    }
294
295
    /**
296
     * When this instance is saved in TYPO3 cache, we need not to store all the
297
     * properties to increase performance.
298
     *
299
     * @return array
300
     */
301
    public function __sleep()
302
    {
303
        return ['name', 'className', 'properties', 'configurationArray', 'hash'];
304
    }
305
306
    /**
307
     * When this class is unserialized, we update the flag to know if the hash
308
     * should be calculated or not (if it was calculated before it was
309
     * serialized, there is no need to calculate it again).
310
     */
311
    public function __wakeup()
312
    {
313
        $this->hashShouldBeCalculated = (null === $this->hash);
314
315
        /** @var ConfigurationFactory $configurationFactory */
316
        $configurationFactory = Core::instantiate(ConfigurationFactory::class);
317
        $this->injectConfigurationFactory($configurationFactory);
318
    }
319
}
320