Completed
Push — middleware-wip-tmp2 ( 6948fe )
by Romain
03:15
created

FormObjectFactory::addToGlobalConfiguration()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
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\FormObject;
15
16
use Romm\Formz\Configuration\Configuration;
17
use Romm\Formz\Configuration\ConfigurationFactory;
18
use Romm\Formz\Core\Core;
19
use Romm\Formz\Exceptions\ClassNotFoundException;
20
use Romm\Formz\Exceptions\InvalidArgumentTypeException;
21
use Romm\Formz\Form\FormInterface;
22
use Romm\Formz\Form\FormObject\Builder\DefaultFormObjectBuilder;
23
use Romm\Formz\Form\FormObject\Builder\FormObjectBuilderInterface;
24
use Romm\Formz\Service\CacheService;
25
use Romm\Formz\Service\StringService;
26
use Romm\Formz\Service\Traits\ExtendedSelfInstantiateTrait;
27
use TYPO3\CMS\Core\SingletonInterface;
28
29
/**
30
 * Factory class that will manage form object instances.
31
 *
32
 * You can fetch a new instance by calling one of the following methods:
33
 * `getInstanceFromFormInstance()` or `getInstanceFromClassName()`
34
 *
35
 * @see \Romm\Formz\Form\FormObject\FormObject
36
 */
37
class FormObjectFactory implements SingletonInterface
38
{
39
    use ExtendedSelfInstantiateTrait;
40
41
    /**
42
     * @var FormObject[]
43
     */
44
    protected $instances = [];
45
46
    /**
47
     * @var FormObjectStatic[]
48
     */
49
    protected $static = [];
50
51
    /**
52
     * @var FormObjectProxy[]
53
     */
54
    protected $proxy = [];
55
56
    /**
57
     * @var Configuration
58
     */
59
    protected $globalConfiguration;
60
61
    /**
62
     * Will fetch FormZ global configuration.
63
     */
64
    public function initializeObject()
65
    {
66
        $this->globalConfiguration = ConfigurationFactory::get()->getFormzConfiguration()->getObject(true);
67
    }
68
69
    /**
70
     * @param FormInterface $form
71
     * @param string        $name
72
     * @return FormObject
73
     */
74
    public function getInstanceWithFormInstance(FormInterface $form, $name = 'defaultName')
75
    {
76
        $hash = $name . '-' . spl_object_hash($form);
77
78
        if (false === isset($this->instances[$hash])) {
79
            $this->instances[$hash] = $this->getInstanceWithClassName(get_class($form), $name);
80
            $this->instances[$hash]->setForm($form);
81
        }
82
83
        return $this->instances[$hash];
84
    }
85
86
    /**
87
     * Will create an instance of `FormObject` based on a class that implements
88
     * the interface `FormInterface`.
89
     *
90
     * @param string $className
91
     * @param string $name
92
     * @return FormObject
93
     */
94
    public function getInstanceWithClassName($className, $name)
95
    {
96
        /** @var FormObject $formObject */
97
        $formObject = Core::instantiate(FormObject::class, $name, $this->getStaticInstance($className));
98
99
        return $formObject;
100
    }
101
102
    /**
103
     * Returns the proxy object for the given form object and form instance.
104
     *
105
     * Please use with caution, as this is a very low level function!
106
     *
107
     * @param FormInterface $form
108
     * @return FormObjectProxy
109
     */
110
    public function getProxy(FormInterface $form)
111
    {
112
        $hash = spl_object_hash($form);
113
114
        if (false === isset($this->proxy[$hash])) {
115
            $this->proxy[$hash] = $this->getNewProxyInstance($form);
116
        }
117
118
        return $this->proxy[$hash];
119
    }
120
121
    /**
122
     * @param string $className
123
     * @return FormObjectStatic
124
     * @throws ClassNotFoundException
125
     * @throws InvalidArgumentTypeException
126
     */
127
    protected function getStaticInstance($className)
128
    {
129
        if (false === class_exists($className)) {
130
            throw ClassNotFoundException::wrongFormClassName($className);
131
        }
132
133
        if (false === in_array(FormInterface::class, class_implements($className))) {
134
            throw InvalidArgumentTypeException::wrongFormType($className);
135
        }
136
137
        $cacheIdentifier = $this->getCacheIdentifier($className);
138
139
        if (false === isset($this->static[$cacheIdentifier])) {
140
            $cacheInstance = CacheService::get()->getCacheInstance();
141
142
            if ($cacheInstance->has($cacheIdentifier)) {
143
                $static = $cacheInstance->get($cacheIdentifier);
144
            } else {
145
                $static = $this->buildStaticInstance($className);
146
                $static->getObjectHash();
147
148
                $cacheInstance->set($cacheIdentifier, $static);
149
            }
150
151
            $this->addToGlobalConfiguration($static);
152
153
            $this->static[$cacheIdentifier] = $static;
154
        }
155
156
        return $this->static[$cacheIdentifier];
157
    }
158
159
    /**
160
     * Adds the given form configuration to the global FormZ configuration
161
     * object.
162
     *
163
     * @param FormObjectStatic $static
164
     */
165
    public function addToGlobalConfiguration(FormObjectStatic $static)
166
    {
167
        if (false === $this->globalConfiguration->hasForm($static->getClassName())) {
168
            $this->globalConfiguration->addForm($static);
169
        }
170
    }
171
172
    /**
173
     * @param string $className
174
     * @return string
175
     */
176
    protected function getCacheIdentifier($className)
177
    {
178
        $sanitizedClassName = StringService::get()->sanitizeString(str_replace('\\', '-', $className));
179
180
        return 'form-object-' . $sanitizedClassName;
181
    }
182
183
    /**
184
     * Wrapper for unit tests.
185
     *
186
     * @param string $className
187
     * @return FormObjectStatic
188
     */
189
    protected function buildStaticInstance($className)
190
    {
191
        /** @var FormObjectBuilderInterface $builder */
192
        $builder = Core::instantiate(DefaultFormObjectBuilder::class);
193
194
        return $builder->getStaticInstance($className);
195
    }
196
197
    /**
198
     * Wrapper for unit tests.
199
     *
200
     * @param FormInterface $form
201
     * @return FormObjectProxy
202
     */
203
    protected function getNewProxyInstance(FormInterface $form)
204
    {
205
        /** @var FormObjectProxy $formObjectProxy */
206
        $formObjectProxy = Core::instantiate(FormObjectProxy::class, $form);
207
208
        return $formObjectProxy;
209
    }
210
}
211