Completed
Pull Request — master (#470)
by Claus
06:03
created

AbstractTemplateView::renderSection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 3
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
namespace TYPO3Fluid\Fluid\View;
4
5
/*
6
 * This file belongs to the package "TYPO3 Fluid".
7
 * See LICENSE.txt that was shipped with this package.
8
 */
9
10
use TYPO3Fluid\Fluid\Component\Error\ChildNotFoundException;
11
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContext;
12
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
13
use TYPO3Fluid\Fluid\Core\ViewHelper\ViewHelperResolver;
14
use TYPO3Fluid\Fluid\View\Exception\InvalidTemplateResourceException;
15
16
/**
17
 * Abstract Fluid Template View.
18
 *
19
 * Contains the fundamental methods which any Fluid based template view needs.
20
 *
21
 * @deprecated Will be removed in Fluid 4.0
22
 */
23
abstract class AbstractTemplateView extends AbstractView
0 ignored issues
show
Deprecated Code introduced by
The class TYPO3Fluid\Fluid\View\AbstractView has been deprecated with message: Will be removed in Fluid 4.0

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

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

Loading history...
24
{
25
    /**
26
     * The initial rendering context for this template view.
27
     * Due to the rendering stack, another rendering context might be active
28
     * at certain points while rendering the template.
29
     *
30
     * @var RenderingContextInterface
31
     */
32
    protected $baseRenderingContext;
33
34
    public function __construct(RenderingContextInterface $context = null)
35
    {
36
        if ($context === null) {
37
            $context = new RenderingContext();
38
            if (is_callable([$context, 'setControllerName'])) {
39
                $context->setControllerName('Default');
0 ignored issues
show
Bug introduced by
The method setControllerName() does not seem to exist on object<TYPO3Fluid\Fluid\...ering\RenderingContext>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
40
            }
41
            if (is_callable([$context, 'setControllerAction'])) {
42
                $context->setControllerAction('Default');
0 ignored issues
show
Bug introduced by
The method setControllerAction() does not seem to exist on object<TYPO3Fluid\Fluid\...ering\RenderingContext>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
43
            }
44
        }
45
        $this->setRenderingContext($context);
46
    }
47
48
    public function getTemplatePaths(): TemplatePaths
49
    {
50
        return $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...
51
    }
52
53
    public function getViewHelperResolver(): ViewHelperResolver
54
    {
55
        return $this->baseRenderingContext->getViewHelperResolver();
56
    }
57
58
    public function getRenderingContext(): RenderingContextInterface
59
    {
60
        return $this->baseRenderingContext;
61
    }
62
63
    public function setRenderingContext(RenderingContextInterface $renderingContext): void
64
    {
65
        $this->baseRenderingContext = $renderingContext;
66
        $this->baseRenderingContext->getViewHelperVariableContainer()->setView($this);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Vi...bleContainer::setView() 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...
67
        $this->baseRenderingContext->getRenderer()->setRenderingContext($this->baseRenderingContext);
68
    }
69
70
    /**
71
     * Assign a value to the variable container.
72
     *
73
     * @param string $key The key of a view variable to set
74
     * @param mixed $value The value of the view variable
75
     * @return $this
76
     */
77
    public function assign($key, $value): ViewInterface
78
    {
79
        $this->baseRenderingContext->getVariableProvider()->add($key, $value);
80
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (TYPO3Fluid\Fluid\View\AbstractTemplateView) is incompatible with the return type declared by the interface TYPO3Fluid\Fluid\View\ViewInterface::assign of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
81
    }
82
83
    /**
84
     * Assigns multiple values to the JSON output.
85
     * However, only the key "value" is accepted.
86
     *
87
     * @param array $values Keys and values - only a value with key "value" is considered
88
     * @return self
89
     */
90
    public function assignMultiple(array $values): ViewInterface
91
    {
92
        $templateVariableContainer = $this->baseRenderingContext->getVariableProvider();
93
        foreach ($values as $key => $value) {
94
            $templateVariableContainer->add($key, $value);
95
        }
96
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (TYPO3Fluid\Fluid\View\AbstractTemplateView) is incompatible with the return type declared by the interface TYPO3Fluid\Fluid\View\Vi...terface::assignMultiple of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
97
    }
98
99
    /**
100
     * Loads the template source and render the template.
101
     * If "layoutName" is set in a PostParseFacet callback, it will render the file with the given layout.
102
     *
103
     * @param string|null $actionName If set, this action's template will be rendered instead of the one defined in the context.
104
     * @return mixed Rendered Template
105
     */
106
    public function render(?string $actionName = null)
107
    {
108
        $renderingContext = $this->baseRenderingContext;
109
        $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...
110
        if ($actionName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $actionName of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
111
            $actionName = ucfirst($actionName);
112
            if (is_callable([$renderingContext, 'setControllerAction'])) {
113
                $renderingContext->setControllerAction($actionName);
0 ignored issues
show
Bug introduced by
The method setControllerAction() does not seem to exist on object<TYPO3Fluid\Fluid\...deringContextInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
114
            }
115
        } else {
116
            $actionName = is_callable([$renderingContext, 'getControllerAction']) ? $renderingContext->getControllerAction() : 'Default';
0 ignored issues
show
Bug introduced by
The method getControllerAction() does not seem to exist on object<TYPO3Fluid\Fluid\...deringContextInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
117
        }
118
        $controllerName = is_callable([$renderingContext, 'getControllerName']) ? $renderingContext->getControllerName() : 'Default';
0 ignored issues
show
Bug introduced by
The method getControllerName() does not seem to exist on object<TYPO3Fluid\Fluid\...deringContextInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
119
        $filePathAndFilename = $templatePaths->resolveTemplateFileForControllerAndActionAndFormat($controllerName, $actionName);
120
121
        if ($filePathAndFilename !== null) {
122
            return $renderingContext->getRenderer()->renderFile($filePathAndFilename);
123
        }
124
        return $renderingContext->getRenderer()->renderSource(
125
            $templatePaths->getTemplateSource($controllerName, $actionName)
126
        );
127
    }
128
129
    /**
130
     * Renders a given section.
131
     *
132
     * @param string $sectionName Name of section to render
133
     * @param array $variables The variables to use
134
     * @param boolean $ignoreUnknown Ignore an unknown section and just return an empty string
135
     * @return mixed rendered template for the section
136
     * @throws ChildNotFoundException
137
     * @throws InvalidTemplateResourceException
138
     * @throws Exception
139
     */
140
    public function renderSection(string $sectionName, array $variables = [], bool $ignoreUnknown = false)
141
    {
142
        $context = $this->baseRenderingContext;
143
        $templatePaths = $context->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...
144
        $templateClosure = function(RenderingContextInterface $renderingContext): string {
145
            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...
146
        };
147
        $identifierClosure = function() use ($context, $templatePaths) {
148
            return $templatePaths->getTemplateSource($context->getControllerName(), $context->getControllerAction());
0 ignored issues
show
Bug introduced by
The method getControllerName() does not seem to exist on object<TYPO3Fluid\Fluid\...deringContextInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getControllerAction() does not seem to exist on object<TYPO3Fluid\Fluid\...deringContextInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
149
        };
150
        return $this->baseRenderingContext->getRenderer()
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Re...etBaseTemplateClosure() 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...
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Re...BaseIdentifierClosure() 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...
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Re...nderer::renderSection() 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...
151
            ->setBaseTemplateClosure($templateClosure)
152
            ->setBaseIdentifierClosure($identifierClosure)
153
            ->renderSection($sectionName, $variables, $ignoreUnknown);
154
    }
155
156
    /**
157
     * Renders a partial.
158
     *
159
     * @param string $partialName
160
     * @param string|null $sectionName
161
     * @param array $variables
162
     * @param boolean $ignoreUnknown Ignore an unknown section and just return an empty string
163
     * @return mixed
164
     * @throws ChildNotFoundException
165
     * @throws InvalidTemplateResourceException
166
     * @throws Exception
167
     */
168
    public function renderPartial(string $partialName, ?string $sectionName, array $variables, bool $ignoreUnknown = false)
169
    {
170
        return $this->baseRenderingContext->getRenderer()->renderPartial($partialName, $sectionName, $variables, $ignoreUnknown);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3Fluid\Fluid\Core\Re...nderer::renderPartial() 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...
171
    }
172
}
173