Completed
Push — middleware-wip ( a29b16...4a8d7b )
by Romain
11:57
created

ConditionProcessor::attachFormObject()   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\Condition\Processor;
15
16
use Romm\Formz\Condition\Parser\ConditionParserFactory;
17
use Romm\Formz\Condition\Parser\Node\ConditionNode;
18
use Romm\Formz\Condition\Parser\Node\NodeInterface;
19
use Romm\Formz\Condition\Parser\Tree\ConditionTree;
20
use Romm\Formz\Condition\Parser\Tree\EmptyConditionTree;
21
use Romm\Formz\Form\Definition\Condition\ActivationInterface;
22
use Romm\Formz\Form\Definition\Field\Field;
23
use Romm\Formz\Form\Definition\Field\Validation\Validator;
24
use Romm\Formz\Form\Definition\Step\Step\ConditionalStepDefinition;
25
use Romm\Formz\Form\Definition\Step\Step\Substep\ConditionalSubstepDefinition;
26
use Romm\Formz\Form\FormObject\FormObject;
27
28
class ConditionProcessor
29
{
30
    /**
31
     * @var FormObject
32
     */
33
    private $formObject;
34
35
    /**
36
     * @var ConditionTree[]
37
     */
38
    private $fieldsTrees = [];
39
40
    /**
41
     * @var ConditionTree[]
42
     */
43
    private $conditionTrees = [];
44
45
    /**
46
     * @var ConditionTree[]
47
     */
48
    private $stepTree = [];
49
50
    /**
51
     * @var ConditionTree[]
52
     */
53
    private $substepTree = [];
54
55
    /**
56
     * @var array
57
     */
58
    private $javaScriptFiles = [];
59
60
    /**
61
     * @param FormObject $formObject
62
     */
63
    public function __construct(FormObject $formObject)
64
    {
65
        $this->attachFormObject($formObject);
66
    }
67
68
    /**
69
     * Returns the condition tree for a given field instance, giving access to
70
     * CSS, JavaScript and PHP transpiled results.
71
     *
72
     * @param Field $field
73
     * @return ConditionTree
74
     */
75
    public function getActivationConditionTreeForField(Field $field)
76
    {
77
        $key = $field->getName();
78
79
        if (false === array_key_exists($key, $this->fieldsTrees)) {
80
            $this->fieldsTrees[$key] = $field->hasActivation()
81
                ? $this->getConditionTree($field->getActivation())
82
                : EmptyConditionTree::get();
83
        }
84
85
        if ($field->hasActivation()) {
86
            $this->fieldsTrees[$key]->injectDependencies($this, $field->getActivation());
87
        }
88
89
        return $this->fieldsTrees[$key];
90
    }
91
92
    /**
93
     * Returns the condition tree for a given validator instance, giving access
94
     * to CSS, JavaScript and PHP transpiled results.
95
     *
96
     * @param Validator $validator
97
     * @return ConditionTree
98
     */
99
    public function getActivationConditionTreeForValidator(Validator $validator)
100
    {
101
        $key = $validator->getParentField()->getName() . '->' . $validator->getName();
102
103
        if (false === array_key_exists($key, $this->conditionTrees)) {
104
            $this->conditionTrees[$key] = $validator->hasActivation()
105
                ? $this->getConditionTree($validator->getActivation())
106
                : EmptyConditionTree::get();
107
        }
108
109
        if ($validator->hasActivation()) {
110
            $this->conditionTrees[$key]->injectDependencies($this, $validator->getActivation());
111
        }
112
113
        return $this->conditionTrees[$key];
114
    }
115
116
    /**
117
     * @todo
118
     *
119
     * @param ConditionalStepDefinition $step
120
     * @return ConditionTree
121
     */
122
    public function getActivationConditionTreeForStep(ConditionalStepDefinition $step)
123
    {
124
        $key = 'step-' . serialize($step);
125
126
        if (false === array_key_exists($key, $this->stepTree)) {
127
            $this->stepTree[$key] = $this->getConditionTree($step->getActivation());
128
        }
129
130
        $this->stepTree[$key]->injectDependencies($this, $step->getActivation());
131
132
        return $this->stepTree[$key];
133
    }
134
135
    /**
136
     * @todo
137
     *
138
     * @param ConditionalSubstepDefinition $substep
139
     * @return ConditionTree
140
     */
141
    public function getActivationConditionTreeForSubstep(ConditionalSubstepDefinition $substep)
142
    {
143
        $key = 'substep-' . serialize($substep);
144
145
        if (false === array_key_exists($key, $this->substepTree)) {
146
            $this->substepTree[$key] = $this->getConditionTree($substep->getActivation());
147
        }
148
149
        $this->substepTree[$key]->injectDependencies($this, $substep->getActivation());
150
151
        return $this->substepTree[$key];
152
    }
153
154
    /**
155
     * Function that will calculate all trees from fields and their validators.
156
     *
157
     * This is useful to be able to store this instance in cache.
158
     */
159
    public function calculateAllTrees()
160
    {
161
        $fields = $this->formObject->getDefinition()->getFields();
162
163
        foreach ($fields as $field) {
164
            $this->getActivationConditionTreeForField($field);
165
166
            foreach ($field->getValidators() as $validator) {
167
                $this->getActivationConditionTreeForValidator($validator);
168
            }
169
        }
170
    }
171
172
    /**
173
     * @param ActivationInterface $activation
174
     * @return ConditionTree
175
     */
176
    protected function getConditionTree(ActivationInterface $activation)
177
    {
178
        $tree = $this->getNewConditionTreeFromActivation($activation);
179
        $tree->alongNodes(function (NodeInterface $node) {
180
            $this->attachNodeJavaScriptFiles($node);
181
        });
182
183
        return $tree;
184
    }
185
186
    /**
187
     * @param ActivationInterface $activation
188
     * @return ConditionTree
189
     */
190
    protected function getNewConditionTreeFromActivation(ActivationInterface $activation)
191
    {
192
        return ConditionParserFactory::get()
193
            ->parse($activation);
194
    }
195
196
    /**
197
     * @param NodeInterface $node
198
     */
199
    protected function attachNodeJavaScriptFiles(NodeInterface $node)
200
    {
201
        if ($node instanceof ConditionNode) {
202
            $files = $node->getCondition()->getJavaScriptFiles();
203
204
            foreach ($files as $file) {
205
                if (false === in_array($file, $this->javaScriptFiles)) {
206
                    $this->javaScriptFiles[] = $file;
207
                }
208
            }
209
        }
210
    }
211
212
    /**
213
     * @param FormObject $formObject
214
     */
215
    public function attachFormObject(FormObject $formObject)
216
    {
217
        $this->formObject = $formObject;
218
    }
219
220
    /**
221
     * @return FormObject
222
     */
223
    public function getFormObject()
224
    {
225
        return $this->formObject;
226
    }
227
228
    /**
229
     * @return array
230
     */
231
    public function getJavaScriptFiles()
232
    {
233
        return $this->javaScriptFiles;
234
    }
235
236
    /**
237
     * @return array
238
     */
239
    public function __sleep()
240
    {
241
        return ['fieldsTrees', 'conditionTrees', 'javaScriptFiles'];
242
    }
243
}
244