Issues (186)

Classes/ViewHelpers/Slot/RenderViewHelper.php (3 issues)

1
<?php
2
declare(strict_types=1);
3
4
/*
5
 * Copyright (C)
6
 * Nathan Boiron <[email protected]>
7
 * Romain Canon <[email protected]>
8
 *
9
 * This file is part of the TYPO3 NotiZ project.
10
 * It is free software; you can redistribute it and/or modify it
11
 * under the terms of the GNU General Public License, either
12
 * version 3 of the License, or any later version.
13
 *
14
 * For the full copyright and license information, see:
15
 * http://www.gnu.org/licenses/gpl-3.0.html
16
 */
17
18
namespace CuyZ\Notiz\ViewHelpers\Slot;
19
20
use Closure;
21
use CuyZ\Notiz\Core\Exception\DuplicateEntryException;
22
use CuyZ\Notiz\Core\Property\Service\MarkerParser;
23
use CuyZ\Notiz\Domain\Property\Marker;
24
use CuyZ\Notiz\Service\Container;
25
use CuyZ\Notiz\View\Slot\SlotContainer;
26
use CuyZ\Notiz\View\Slot\SlotView;
27
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractConditionViewHelper;
0 ignored issues
show
The type TYPO3\CMS\Fluid\Core\Vie...ractConditionViewHelper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
28
use TYPO3\CMS\Fluid\Core\ViewHelper\ViewHelperVariableContainer;
0 ignored issues
show
The type TYPO3\CMS\Fluid\Core\Vie...HelperVariableContainer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
29
use TYPO3Fluid\Fluid\Core\Compiler\TemplateCompiler;
30
use TYPO3Fluid\Fluid\Core\Parser\SyntaxTree\ViewHelperNode;
31
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
32
33
/**
34
 * Will process and render the wanted slot, by getting the value filled by the
35
 * user and replacing markers within it.
36
 *
37
 * This view-helper can be used in several ways:
38
 *
39
 * Inline
40
 * ------
41
 *
42
 * The processed slot value will be returned.
43
 *
44
 * ```
45
 * <nz:slot.render name="MySlot"
46
 *                 markers="{foo: 'bar'}" />
47
 * ```
48
 *
49
 * Conditional
50
 * -----------
51
 *
52
 * Can be used to check whether the slot exists, and do something if it doesn't.
53
 *
54
 * When using this way, a variable `slotValue` becomes accessible within the
55
 * view-helper, that contains the processed value of the slot. However, this
56
 * variable is filled only when the slot exists and can be processed.
57
 *
58
 * ```
59
 * <nz:slot.render name="SomeOptionalSlot">
60
 *     <f:then>
61
 *         {slotValue -> f:format.html()}
62
 *     </f:then>
63
 *     <f:else>
64
 *         Some default value
65
 *     </f:else>
66
 * </nz:slot.render>
67
 * ```
68
 *
69
 * Wrapping
70
 * --------
71
 *
72
 * You may need to add HTML around the slot value only when the slot exists.
73
 *
74
 * ```
75
 * <nz:slot.render name="SomeOptionalSlot">
76
 *     <hr />
77
 *
78
 *     <div class="some-class">
79
 *         {slotValue}
80
 *     </div>
81
 * </nz:slot.render>
82
 * ```
83
 */
84
class RenderViewHelper extends AbstractConditionViewHelper
85
{
86
    /**
87
     * Unfortunately, the rendering context is not passed to the method
88
     * `evaluateCondition`. We need to first save the variable container in the
89
     * class before the method is called.
90
     *
91
     * @var ViewHelperVariableContainer
92
     */
93
    protected static $currentVariableContainer;
94
95
    /**
96
     * @inheritdoc
97
     */
98
    public function initializeArguments()
99
    {
100
        parent::initializeArguments();
101
102
        $this->registerArgument('name', 'string', 'Name of the slot that will be rendered.', true);
103
        $this->registerArgument('markers', 'array', 'Additional markers that will be added to the slot and can be used within the FlexForm.', false, []);
104
    }
105
106
    /**
107
     * @inheritdoc
108
     */
109
    public function render()
110
    {
111
        return self::getSlotValue($this->arguments, $this->renderingContext);
112
    }
113
114
    /**
115
     * @inheritdoc
116
     */
117
    public static function renderStatic(array $arguments, Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
118
    {
119
        self::addSlotValueToVariables($arguments, $renderingContext);
120
121
        return parent::renderStatic($arguments, $renderChildrenClosure, $renderingContext);
122
    }
123
124
    /**
125
     * Adds a new variable `slotValue` to the view, that contains the processed
126
     * value of the slot.
127
     *
128
     * @param array $arguments
129
     * @param RenderingContextInterface $renderingContext
130
     */
131
    protected static function addSlotValueToVariables(array $arguments, RenderingContextInterface $renderingContext)
132
    {
133
        $slotValue = self::getSlotValue($arguments, $renderingContext);
134
135
        $renderingContext->getVariableProvider()->add('slotValue', $slotValue);
136
    }
137
138
    /**
139
     * @inheritdoc
140
     */
141
    public function compile($argumentsName, $closureName, &$initializationPhpCode, ViewHelperNode $node, TemplateCompiler $compiler)
142
    {
143
        if (empty($node->getChildNodes())) {
144
            return sprintf(
145
                '%s::getSlotValue(%s, $renderingContext)',
146
                get_class($this),
147
                $argumentsName
148
            );
149
        } else {
150
            return parent::compile($argumentsName, $closureName, $initializationPhpCode, $node, $compiler);
151
        }
152
    }
153
154
    /**
155
     * Fetches the final value of the wanted slot, by getting the user value and
156
     * replacing markers in it.
157
     *
158
     * @param array $arguments
159
     * @param RenderingContextInterface $renderingContext
160
     * @return string
161
     *
162
     * @throws DuplicateEntryException
163
     */
164
    public static function getSlotValue(array $arguments, RenderingContextInterface $renderingContext): string
165
    {
166
        self::$currentVariableContainer = $renderingContext->getViewHelperVariableContainer();
0 ignored issues
show
Documentation Bug introduced by
It seems like $renderingContext->getVi...lperVariableContainer() of type TYPO3Fluid\Fluid\Core\Vi...HelperVariableContainer is incompatible with the declared type TYPO3\CMS\Fluid\Core\Vie...HelperVariableContainer of property $currentVariableContainer.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
167
168
        $result = '';
169
        $name = $arguments['name'];
170
        $newMarkers = $arguments['markers'];
171
172
        $slotValues = self::getSlotValues();
173
        $markers = self::getMarkers();
174
175
        foreach ($newMarkers as $key => $value) {
176
            if (isset($markers[$key])) {
177
                throw DuplicateEntryException::markerAlreadyDefined($key, $name);
178
            }
179
        }
180
181
        if (isset($slotValues[$name])) {
182
            foreach ($newMarkers as $key => $value) {
183
                $marker = new Marker($key);
184
                $marker->setValue($value);
185
186
                $markers[$key] = $marker;
187
            }
188
189
            $markerParser = Container::get(MarkerParser::class);
190
191
            $result = $markerParser->replaceMarkers(
192
                $slotValues[$name],
193
                $markers
194
            );
195
        }
196
197
        return $result;
198
    }
199
200
    /**
201
     * @param array $arguments
202
     * @return bool
203
     */
204
    protected static function evaluateCondition($arguments = null): bool
205
    {
206
        return self::getSlotContainer()->has($arguments['name']);
207
    }
208
209
    /**
210
     * @return SlotContainer
211
     */
212
    protected static function getSlotContainer(): SlotContainer
213
    {
214
        return self::$currentVariableContainer->get(SlotView::class, SlotView::SLOT_CONTAINER);
215
    }
216
217
    /**
218
     * @return array
219
     */
220
    protected static function getSlotValues(): array
221
    {
222
        return self::$currentVariableContainer->get(SlotView::class, SlotView::SLOT_VALUES);
223
    }
224
225
    /**
226
     * @return array
227
     */
228
    protected static function getMarkers(): array
229
    {
230
        return self::$currentVariableContainer->get(SlotView::class, SlotView::MARKERS);
231
    }
232
}
233