Completed
Pull Request — master (#470)
by Claus
01:41
created

FluidRenderer::renderSource()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 3
nop 1
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
namespace TYPO3Fluid\Fluid\Core\Rendering;
4
5
use TYPO3Fluid\Fluid\Component\ComponentInterface;
6
use TYPO3Fluid\Fluid\Component\Error\ChildNotFoundException;
7
use TYPO3Fluid\Fluid\Core\Parser\PassthroughSourceException;
8
use TYPO3Fluid\Fluid\View\Exception;
9
use TYPO3Fluid\Fluid\View\Exception\InvalidTemplateResourceException;
10
11
class FluidRenderer
12
{
13
    /**
14
     * The initial rendering context for this template view.
15
     * Due to the rendering stack, another rendering context might be active
16
     * at certain points while rendering the template.
17
     *
18
     * @var RenderingContextInterface
19
     */
20
    protected $baseRenderingContext;
21
22
    /**
23
     * Stack containing the current rendering type, the current rendering context, and the current parsed template
24
     * Do not manipulate directly, instead use the methods"getCurrent*()", "startRendering(...)" and "stopRendering()"
25
     *
26
     * @var array
27
     */
28
    protected $renderingStack = [];
29
30
    /**
31
     * @var callable|null
32
     * @deprecated Will be removed in Fluid 4.0
33
     */
34
    protected $baseTemplateClosure;
35
36
    /**
37
     * @var callable|null
38
     * @deprecated Will be removed in Fluid 4.0
39
     */
40
    protected $baseIdentifierClosure;
41
42
    public function __construct(RenderingContextInterface $renderingContext)
43
    {
44
        $this->baseRenderingContext = $renderingContext;
45
    }
46
47
    /**
48
     * @param callable|null $baseTemplateClosure
49
     * @return FluidRenderer
50
     * @deprecated Will be removed in Fluid 4.0
51
     */
52
    public function setBaseTemplateClosure(?callable $baseTemplateClosure): self
53
    {
54
        $this->baseTemplateClosure = $baseTemplateClosure;
0 ignored issues
show
Deprecated Code introduced by
The property TYPO3Fluid\Fluid\Core\Re...r::$baseTemplateClosure has been deprecated with message: Will be removed in Fluid 4.0

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
55
        return $this;
56
    }
57
58
    /**
59
     * @param callable|null $baseIdentifierClosure
60
     * @return FluidRenderer
61
     * @deprecated Will be removed in Fluid 4.0
62
     */
63
    public function setBaseIdentifierClosure(?callable $baseIdentifierClosure): self
64
    {
65
        $this->baseIdentifierClosure = $baseIdentifierClosure;
0 ignored issues
show
Deprecated Code introduced by
The property TYPO3Fluid\Fluid\Core\Re...:$baseIdentifierClosure has been deprecated with message: Will be removed in Fluid 4.0

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
66
        return $this;
67
    }
68
69
    public function getRenderingContext(): RenderingContextInterface
70
    {
71
        return $this->baseRenderingContext;
72
    }
73
74
    public function setRenderingContext(RenderingContextInterface $renderingContext): void
75
    {
76
        $this->baseRenderingContext = $renderingContext;
77
    }
78
79
    public function renderSource(string $source)
80
    {
81
        $renderingContext = $this->baseRenderingContext;
82
        $renderingContext->getTemplatePaths()->setTemplateSource($source);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Re...ace::getTemplatePaths() has been deprecated with message: Will be removed in Fluid 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
83
        $templateParser = $renderingContext->getTemplateParser();
84
        try {
85
            $parsedTemplate = $templateParser->getOrParseAndStoreTemplate(
86
                sha1($source),
87
                function() use ($source): string { return $source; }
88
            );
89
            $parsedTemplate->getArguments()->setRenderingContext($renderingContext);
90
        } catch (PassthroughSourceException $error) {
91
            return $error->getSource();
92
        }
93
94
        $this->renderingStack[] = $parsedTemplate;
95
        $output = $parsedTemplate->evaluate($this->baseRenderingContext);
96
        array_pop($this->renderingStack);
97
        return $output;
98
    }
99
100
    /**
101
     * Loads the template source and render the template.
102
     * If "layoutName" is set in a PostParseFacet callback, it will render the file with the given layout.
103
     *
104
     * @param string $filePathAndName
105
     * @return mixed Rendered Template
106
     */
107
    public function renderFile(string $filePathAndName)
108
    {
109
        $this->baseRenderingContext->getTemplatePaths()->setTemplatePathAndFilename($filePathAndName);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Re...ace::getTemplatePaths() has been deprecated with message: Will be removed in Fluid 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
110
        $output = $this->renderSource(file_get_contents($filePathAndName));
111
        $this->baseRenderingContext->getTemplatePaths()->setTemplatePathAndFilename(null);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Re...ace::getTemplatePaths() has been deprecated with message: Will be removed in Fluid 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
112
        return $output;
113
    }
114
115
    /**
116
     * Renders a given section.
117
     *
118
     * Deprecated in favor of the Atoms concept which can be accessed through the ViewHelperResolver.
119
     *
120
     * A section can be rendered by resolving the appropriate (template, layout or partial-like)
121
     * Atom and using either getTypedChildren() or getNamedChild() to extract the desired section
122
     * and render it via the Component interface the return value implements.
123
     *
124
     * @param string $sectionName Name of section to render
125
     * @param array $variables The variables to use
126
     * @param boolean $ignoreUnknown Ignore an unknown section and just return an empty string
127
     * @return mixed rendered template for the section
128
     * @throws ChildNotFoundException
129
     * @throws InvalidTemplateResourceException
130
     * @throws Exception
131
     */
132
    public function renderSection(string $sectionName, array $variables = [], bool $ignoreUnknown = false)
133
    {
134
        $renderingContext = $this->baseRenderingContext;
135
136
        try {
137
            $parsedTemplate = $this->getCurrentParsedTemplate();
138
            $section = $parsedTemplate->getNamedChild($sectionName);
139
            $section->getArguments()->assignAll($variables);
0 ignored issues
show
Unused Code introduced by
The call to the method TYPO3Fluid\Fluid\Compone...Collection::assignAll() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
140
        } catch (ChildNotFoundException $error) {
141
            if (!$ignoreUnknown) {
142
                return $renderingContext->getErrorHandler()->handleViewError($error);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Er...face::handleViewError() has been deprecated with message: Will be removed in Fluid 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
143
            }
144
            return '';
145
        } catch (InvalidTemplateResourceException $error) {
146
            if (!$ignoreUnknown) {
147
                return $renderingContext->getErrorHandler()->handleViewError($error);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Er...face::handleViewError() has been deprecated with message: Will be removed in Fluid 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
148
            }
149
            return '';
150
        } catch (Exception $error) {
151
            return $renderingContext->getErrorHandler()->handleViewError($error);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Er...face::handleViewError() has been deprecated with message: Will be removed in Fluid 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
152
        }
153
154
        $output = $section->evaluate($renderingContext);
155
156
        return $output;
157
    }
158
159
    /**
160
     * Renders a partial.
161
     *
162
     * Deprecated in favor of Atoms concept which can be accessed through the
163
     * ViewHelperResolver to fetch and render a (partial-like) Atom directly.
164
     *
165
     * @param string $partialName
166
     * @param string|null $sectionName
167
     * @param array $variables
168
     * @param boolean $ignoreUnknown Ignore an unknown section and just return an empty string
169
     * @return mixed
170
     * @throws ChildNotFoundException
171
     * @throws InvalidTemplateResourceException
172
     * @throws Exception
173
     * @deprecated Will be removed in Fluid 4.0
174
     */
175
    public function renderPartial(string $partialName, ?string $sectionName, array $variables = [], bool $ignoreUnknown = false)
176
    {
177
        $templatePaths = $this->baseRenderingContext->getTemplatePaths();
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Re...ace::getTemplatePaths() has been deprecated with message: Will be removed in Fluid 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
178
        $renderingContext = $this->baseRenderingContext;
179
        try {
180
            $parsedPartial = $renderingContext->getTemplateParser()->getOrParseAndStoreTemplate(
181
                $templatePaths->getPartialIdentifier($partialName),
182
                function (RenderingContextInterface $renderingContext) use ($partialName): string {
183
                    return $renderingContext->getTemplatePaths()->getPartialSource($partialName);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Re...ace::getTemplatePaths() has been deprecated with message: Will be removed in Fluid 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
184
                }
185
            );
186
            $parsedPartial->getArguments()->setRenderingContext($renderingContext);
187
            $this->renderingStack[] = $parsedPartial;
188
            if ($sectionName !== null) {
189
                $output = $this->renderSection($sectionName, $variables, $ignoreUnknown);
190
            } else {
191
                $parsedPartial->getArguments()->assignAll($variables);
0 ignored issues
show
Unused Code introduced by
The call to the method TYPO3Fluid\Fluid\Compone...Collection::assignAll() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
192
                $output = $parsedPartial->evaluate($renderingContext);
193
            }
194
            array_pop($this->renderingStack);
195
        } catch (PassthroughSourceException $error) {
196
            return $error->getSource();
197
        } catch (InvalidTemplateResourceException $error) {
198
            if (!$ignoreUnknown) {
199
                return $renderingContext->getErrorHandler()->handleViewError($error);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Er...face::handleViewError() has been deprecated with message: Will be removed in Fluid 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
200
            }
201
            return '';
202
        } catch (Exception $error) {
203
            return $renderingContext->getErrorHandler()->handleViewError($error);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Er...face::handleViewError() has been deprecated with message: Will be removed in Fluid 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
204
        }
205
206
        return $output;
207
    }
208
209
    protected function getCurrentParsedTemplate(): ComponentInterface
210
    {
211
        $renderingContext = $this->baseRenderingContext;
212
        $parsedTemplate = end($this->renderingStack);
213
        if ($parsedTemplate) {
214
            return $parsedTemplate;
215
        }
216
        $templatePaths = $renderingContext->getTemplatePaths();
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Re...ace::getTemplatePaths() has been deprecated with message: Will be removed in Fluid 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
217
        $templateParser = $renderingContext->getTemplateParser();
218
219
        // Retrieve the current parsed template, which happens if the renderSection() method was called as first entry
220
        // method (as opposed to rendering through renderFile / renderSource which causes stack entries which in turn
221
        // causes this method to return early).
222
        // Support for the closures will be removed in Fluid 4.0 since they are a temporary measure.
223
        $parsedTemplate = $templateParser->getOrParseAndStoreTemplate(
224
            $this->baseIdentifierClosure ? call_user_func($this->baseIdentifierClosure) : $templatePaths->getTemplateIdentifier('Default', 'Default'),
0 ignored issues
show
Deprecated Code introduced by
The property TYPO3Fluid\Fluid\Core\Re...:$baseIdentifierClosure has been deprecated with message: Will be removed in Fluid 4.0

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
225
            $this->baseTemplateClosure ?? function(RenderingContextInterface $renderingContext): string {
0 ignored issues
show
Documentation introduced by
$this->baseTemplateClosu...Default', 'Default'); } is of type callable, but the function expects a object<Closure>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Deprecated Code introduced by
The property TYPO3Fluid\Fluid\Core\Re...r::$baseTemplateClosure has been deprecated with message: Will be removed in Fluid 4.0

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
226
                return $renderingContext->getTemplatePaths()->getTemplateSource('Default', 'Default');
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Re...ace::getTemplatePaths() has been deprecated with message: Will be removed in Fluid 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
227
            }
228
        );
229
        return $parsedTemplate;
230
    }
231
}