Completed
Pull Request — master (#470)
by Claus
01:35
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
        }
39
        $this->setRenderingContext($context);
40
    }
41
42
    public function getTemplatePaths(): TemplatePaths
43
    {
44
        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...
45
    }
46
47
    public function getViewHelperResolver(): ViewHelperResolver
48
    {
49
        return $this->baseRenderingContext->getViewHelperResolver();
50
    }
51
52
    public function getRenderingContext(): RenderingContextInterface
53
    {
54
        return $this->baseRenderingContext;
55
    }
56
57
    public function setRenderingContext(RenderingContextInterface $renderingContext): void
58
    {
59
        $this->baseRenderingContext = $renderingContext;
60
        $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...
61
        $this->baseRenderingContext->getRenderer()->setRenderingContext($this->baseRenderingContext);
62
    }
63
64
    /**
65
     * Assign a value to the variable container.
66
     *
67
     * @param string $key The key of a view variable to set
68
     * @param mixed $value The value of the view variable
69
     * @return $this
70
     */
71
    public function assign($key, $value): ViewInterface
72
    {
73
        $this->baseRenderingContext->getVariableProvider()->add($key, $value);
74
        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...
75
    }
76
77
    /**
78
     * Assigns multiple values to the JSON output.
79
     * However, only the key "value" is accepted.
80
     *
81
     * @param array $values Keys and values - only a value with key "value" is considered
82
     * @return self
83
     */
84
    public function assignMultiple(array $values): ViewInterface
85
    {
86
        $templateVariableContainer = $this->baseRenderingContext->getVariableProvider();
87
        foreach ($values as $key => $value) {
88
            $templateVariableContainer->add($key, $value);
89
        }
90
        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...
91
    }
92
93
    /**
94
     * Loads the template source and render the template.
95
     * If "layoutName" is set in a PostParseFacet callback, it will render the file with the given layout.
96
     *
97
     * @param string|null $actionName If set, this action's template will be rendered instead of the one defined in the context.
98
     * @return mixed Rendered Template
99
     */
100
    public function render(?string $actionName = null)
101
    {
102
        $renderingContext = $this->baseRenderingContext;
103
        $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...
104
        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...
105
            $actionName = ucfirst($actionName);
106
            if (is_callable([$renderingContext, 'setControllerAction'])) {
107
                $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...
108
            }
109
        } else {
110
            $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...
111
        }
112
        $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...
113
        $filePathAndFilename = $templatePaths->resolveTemplateFileForControllerAndActionAndFormat($controllerName, $actionName);
114
115
        if ($filePathAndFilename !== null) {
116
            return $renderingContext->getRenderer()->renderFile($filePathAndFilename);
117
        }
118
        return $renderingContext->getRenderer()->renderSource(
119
            $templatePaths->getTemplateSource($controllerName, $actionName)
120
        );
121
    }
122
123
    /**
124
     * Renders a given section.
125
     *
126
     * @param string $sectionName Name of section to render
127
     * @param array $variables The variables to use
128
     * @param boolean $ignoreUnknown Ignore an unknown section and just return an empty string
129
     * @return mixed rendered template for the section
130
     * @throws ChildNotFoundException
131
     * @throws InvalidTemplateResourceException
132
     * @throws Exception
133
     */
134
    public function renderSection(string $sectionName, array $variables = [], bool $ignoreUnknown = false)
135
    {
136
        $context = $this->baseRenderingContext;
137
        $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...
138
        $templateClosure = function(RenderingContextInterface $renderingContext): string {
139
            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...
140
        };
141
        $identifierClosure = function() use ($context, $templatePaths) {
142
            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...
143
        };
144
        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...
145
            ->setBaseTemplateClosure($templateClosure)
146
            ->setBaseIdentifierClosure($identifierClosure)
147
            ->renderSection($sectionName, $variables, $ignoreUnknown);
148
    }
149
150
    /**
151
     * Renders a partial.
152
     *
153
     * @param string $partialName
154
     * @param string|null $sectionName
155
     * @param array $variables
156
     * @param boolean $ignoreUnknown Ignore an unknown section and just return an empty string
157
     * @return mixed
158
     * @throws ChildNotFoundException
159
     * @throws InvalidTemplateResourceException
160
     * @throws Exception
161
     */
162
    public function renderPartial(string $partialName, ?string $sectionName, array $variables, bool $ignoreUnknown = false)
163
    {
164
        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...
165
    }
166
}
167