FormObjectFactory::insertObjectProperties()   B
last analyzed

Complexity

Conditions 6
Paths 3

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.9137
c 0
b 0
f 0
cc 6
nc 3
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\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\Service\CacheService;
22
use Romm\Formz\Service\HashService;
23
use Romm\Formz\Service\TypoScriptService;
24
use TYPO3\CMS\Core\SingletonInterface;
25
use TYPO3\CMS\Core\Utility\GeneralUtility;
26
use TYPO3\CMS\Extbase\Reflection\ReflectionService;
27
28
/**
29
 * Factory class which will manage instances of `FormObject`.
30
 */
31
class FormObjectFactory implements SingletonInterface
32
{
33
    const IGNORE_PROPERTY = 'formz-ignore';
34
35
    /**
36
     * @var ConfigurationFactory
37
     */
38
    protected $configurationFactory;
39
40
    /**
41
     * @var TypoScriptService
42
     */
43
    protected $typoScriptService;
44
45
    /**
46
     * @var FormObject[]
47
     */
48
    protected $instances = [];
49
50
    /**
51
     * @var array
52
     */
53
    private static $ignoredProperties = ['validationData', 'uid', 'pid', '_localizedUid', '_languageUid', '_versionedUid'];
54
55
    /**
56
     * Will create an instance of `FormObject` based on a class which implements
57
     * the interface `FormInterface`.
58
     *
59
     * @param string $className
60
     * @param string $name
61
     * @return FormObject
62
     * @throws ClassNotFoundException
63
     * @throws InvalidArgumentTypeException
64
     */
65
    public function getInstanceFromClassName($className, $name)
66
    {
67
        if (false === class_exists($className)) {
68
            throw ClassNotFoundException::wrongFormClassName($className);
69
        }
70
71
        if (false === in_array(FormInterface::class, class_implements($className))) {
72
            throw InvalidArgumentTypeException::wrongFormType($className);
73
        }
74
75
        $cacheIdentifier = $this->getCacheIdentifier($className, $name);
76
77
        if (false === isset($this->instances[$cacheIdentifier])) {
78
            $cacheInstance = CacheService::get()->getCacheInstance();
79
80
            if ($cacheInstance->has($cacheIdentifier)) {
81
                $instance = $cacheInstance->get($cacheIdentifier);
82
            } else {
83
                $instance = $this->createInstance($className, $name);
84
                $cacheInstance->set($cacheIdentifier, $instance);
85
            }
86
87
            /** @var Configuration $formzConfigurationObject */
88
            $formzConfigurationObject = $this->configurationFactory
89
                ->getFormzConfiguration()
90
                ->getObject(true);
91
92
            if (false === $formzConfigurationObject->hasForm($instance->getClassName(), $instance->getName())) {
93
                $formzConfigurationObject->addForm($instance);
94
            }
95
96
            $this->instances[$cacheIdentifier] = $instance;
97
        }
98
99
        return $this->instances[$cacheIdentifier];
100
    }
101
102
    /**
103
     * @param FormInterface $form
104
     * @param string        $name
105
     * @return FormObject
106
     */
107
    public function getInstanceFromFormInstance(FormInterface $form, $name)
108
    {
109
        $formObject = $this->getInstanceFromClassName(get_class($form), $name);
110
111
        return $formObject;
112
    }
113
114
    /**
115
     * Creates and initializes a new `FormObject` instance.
116
     *
117
     * @param string $className
118
     * @param string $name
119
     * @return FormObject
120
     */
121
    protected function createInstance($className, $name)
122
    {
123
        $formConfiguration = $this->typoScriptService->getFormConfiguration($className);
124
125
        /** @var FormObject $instance */
126
        $instance = Core::instantiate(FormObject::class, $className, $name, $formConfiguration);
127
128
        $this->insertObjectProperties($instance);
129
130
        $instance->getHash();
131
132
        return $instance;
133
    }
134
135
    /**
136
     * Will insert all the accessible properties of the given instance.
137
     *
138
     * @param FormObject $instance
139
     */
140
    protected function insertObjectProperties(FormObject $instance)
141
    {
142
        $className = $instance->getClassName();
143
144
        /** @var ReflectionService $reflectionService */
145
        $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
146
        $reflectionProperties = $reflectionService->getClassPropertyNames($className);
147
148
        $classReflection = new \ReflectionClass($className);
149
        $publicProperties = $classReflection->getProperties(\ReflectionProperty::IS_PUBLIC);
150
151
        foreach ($reflectionProperties as $property) {
152
            if (false === in_array($property, self::$ignoredProperties)
153
                && false === $reflectionService->isPropertyTaggedWith($className, $property, self::IGNORE_PROPERTY)
154
                && ((true === in_array($property, $publicProperties))
155
                    || $reflectionService->hasMethod($className, 'get' . ucfirst($property))
156
                )
157
            ) {
158
                $instance->addProperty($property);
159
            }
160
        }
161
162
        unset($publicProperties);
163
    }
164
165
    /**
166
     * @param string $className
167
     * @param string $name
168
     * @return string
169
     */
170
    protected function getCacheIdentifier($className, $name)
171
    {
172
        return vsprintf(
173
            'form-object-%s-%s',
174
            [
175
                CacheService::get()->getFormCacheIdentifier($className, $name),
176
                HashService::get()->getHash($className)
177
            ]
178
        );
179
    }
180
181
    /**
182
     * @param ConfigurationFactory $configurationFactory
183
     */
184
    public function injectConfigurationFactory(ConfigurationFactory $configurationFactory)
185
    {
186
        $this->configurationFactory = $configurationFactory;
187
    }
188
189
    /**
190
     * @param TypoScriptService $typoScriptService
191
     */
192
    public function injectTypoScriptService(TypoScriptService $typoScriptService)
193
    {
194
        $this->typoScriptService = $typoScriptService;
195
    }
196
}
197