Completed
Push — development ( 9be619...e22509 )
by Romain
02:55
created

SlotContextEntry::restoreTemplateVariables()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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