Completed
Push — master ( c41709...42f2c0 )
by Romain
9s
created

getTemplateVariableContainer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
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\Service\ViewHelper;
15
16
use Closure;
17
use Romm\Formz\Exceptions\EntryNotFoundException;
18
use TYPO3\CMS\Core\SingletonInterface;
19
use TYPO3\CMS\Core\Utility\ArrayUtility;
20
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface;
21
use TYPO3\CMS\Fluid\Core\ViewHelper\TemplateVariableContainer;
22
23
class SlotViewHelperService implements SingletonInterface
24
{
25
    /**
26
     * Contains the closures which will render the registered slots. The keys
27
     * of this array are the names of the slots.
28
     *
29
     * @var Closure[]
30
     */
31
    private $closures = [];
32
33
    /**
34
     * @var array[]
35
     */
36
    private $arguments = [];
37
38
    /**
39
     * @var RenderingContextInterface|\TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface[]
40
     */
41
    private $renderingContext = [];
42
43
    /**
44
     * @var array[]
45
     */
46
    private $injectedVariables = [];
47
48
    /**
49
     * @var array[]
50
     */
51
    private $savedVariables = [];
52
53
    /**
54
     * Adds a closure - which will render the slot with the given name - to the
55
     * private storage in this class.
56
     *
57
     * @param string                    $name
58
     * @param Closure                   $closure
59
     * @param array                     $arguments
60
     * @param RenderingContextInterface $renderingContext
61
     */
62
    public function addSlot($name, Closure $closure, array $arguments, RenderingContextInterface $renderingContext)
63
    {
64
        $this->closures[$name] = $closure;
65
        $this->arguments[$name] = $arguments;
66
        $this->renderingContext[$name] = $renderingContext;
67
    }
68
69
    /**
70
     * Returns the closure which will render the slot with the given name.
71
     *
72
     * @param string $name
73
     * @return Closure
74
     * @throws EntryNotFoundException
75
     */
76
    public function getSlotClosure($name)
77
    {
78
        if (false === $this->hasSlot($name)) {
79
            throw EntryNotFoundException::slotClosureSlotNotFound($name);
80
        }
81
82
        return $this->closures[$name];
83
    }
84
85
    /**
86
     * Returns the closure which will render the slot with the given name.
87
     *
88
     * @param string $name
89
     * @return array
90
     * @throws EntryNotFoundException
91
     */
92
    public function getSlotArguments($name)
93
    {
94
        if (false === $this->hasSlot($name)) {
95
            throw EntryNotFoundException::slotArgumentsSlotNotFound($name);
96
        }
97
98
        return $this->arguments[$name];
99
    }
100
101
    /**
102
     * @param string $name
103
     * @return bool
104
     */
105
    public function hasSlot($name)
106
    {
107
        return true === isset($this->closures[$name]);
108
    }
109
110
    /**
111
     * Will merge the given arguments with the ones registered by the given
112
     * slot, and inject them in the template variable container.
113
     *
114
     * Note that the variables that are already defined are first saved before
115
     * being overridden, so they can be restored later.
116
     *
117
     * @param string                    $slotName
118
     * @param array                     $arguments
119
     */
120
    public function addTemplateVariables($slotName, array $arguments)
121
    {
122
        $templateVariableContainer = $this->getTemplateVariableContainer($slotName);
123
        $savedArguments = [];
124
125
        ArrayUtility::mergeRecursiveWithOverrule(
126
            $arguments,
127
            $this->getSlotArguments($slotName)
128
        );
129
130
        foreach ($arguments as $key => $value) {
131
            if ($templateVariableContainer->exists($key)) {
132
                $savedArguments[$key] = $templateVariableContainer->get($key);
133
                $templateVariableContainer->remove($key);
134
            }
135
136
            $templateVariableContainer->add($key, $value);
137
        }
138
139
        $this->injectedVariables[$slotName] = $arguments;
140
        $this->savedVariables[$slotName] = $savedArguments;
141
    }
142
143
    /**
144
     * Will remove all variables previously injected in the template variable
145
     * container, and restore the ones that were saved before being overridden.
146
     *
147
     * @param string                    $slotName
148
     */
149
    public function restoreTemplateVariables($slotName)
150
    {
151
        $templateVariableContainer = $this->getTemplateVariableContainer($slotName);
152
        $mergedArguments = (isset($this->injectedVariables[$slotName])) ? $this->injectedVariables[$slotName] : [];
153
        $savedArguments = (isset($this->savedVariables[$slotName])) ? $this->savedVariables[$slotName] : [];
154
155
        foreach (array_keys($mergedArguments) as $key) {
156
            $templateVariableContainer->remove($key);
157
        }
158
159
        foreach ($savedArguments as $key => $value) {
160
            $templateVariableContainer->add($key, $value);
161
        }
162
    }
163
164
    /**
165
     * @param string $slotName
166
     * @return TemplateVariableContainer
167
     */
168
    protected function getTemplateVariableContainer($slotName)
169
    {
170
        /** @var TemplateVariableContainer $templateVariableContainer */
171
        $templateVariableContainer = $this->renderingContext[$slotName]->getTemplateVariableContainer();
172
173
        return $templateVariableContainer;
174
    }
175
176
    /**
177
     * Resets the service variables.
178
     */
179
    public function resetState()
180
    {
181
        $this->closures = [];
182
        $this->arguments = [];
183
        $this->injectedVariables = [];
184
        $this->savedVariables = [];
185
    }
186
}
187