Completed
Push — master ( 0be645...952528 )
by Marc
03:07
created

compile()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 28
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 24
c 2
b 0
f 0
nc 1
nop 5
dl 0
loc 28
rs 8.8571
1
<?php
2
namespace TYPO3Fluid\Fluid\Core\ViewHelper\Traits;
3
4
use TYPO3Fluid\Fluid\Core\Compiler\TemplateCompiler;
5
use TYPO3Fluid\Fluid\Core\Compiler\ViewHelperCompiler;
6
use TYPO3Fluid\Fluid\Core\Exception;
7
use TYPO3Fluid\Fluid\Core\Parser\SyntaxTree\ViewHelperNode;
8
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
9
10
/**
11
 * Class CompilableWithContentArgumentAndRenderStatic
12
 *
13
 * Provides default methods for rendering and compiling
14
 * any ViewHelper that conforms to the `renderStatic`
15
 * method pattern but has the added common use case that
16
 * an argument value must be checked and used instead of
17
 * the normal render children closure, if that named
18
 * argument is specified and not empty.
19
 */
20
trait CompileWithContentArgumentAndRenderStatic
21
{
22
    /**
23
     * Name of variable that contains the value to use
24
     * instead of render children closure, if specified.
25
     * If no name is provided here, the first variable
26
     * registered in `initializeArguments` of the ViewHelper
27
     * will be used.
28
     *
29
     * Note: it is significantly better practice to define
30
     * this property in your ViewHelper class and so fix it
31
     * to one particular argument instead of resolving,
32
     * especially when your ViewHelper is called multiple
33
     * times within an uncompiled template!
34
     *
35
     * @var string
36
     */
37
    protected $contentArgumentName;
38
39
    /**
40
     * Default render method to render ViewHelper with
41
     * first defined optional argument as content.
42
     *
43
     * @return string Rendered string
44
     * @api
45
     */
46
    public function render()
47
    {
48
        return static::renderStatic(
0 ignored issues
show
Bug introduced by
The method renderStatic() does not exist on TYPO3Fluid\Fluid\Core\Vi...ArgumentAndRenderStatic. Did you maybe mean render()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
49
            $this->arguments,
0 ignored issues
show
Bug introduced by
The property arguments does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
50
            $this->buildRenderChildrenClosure(),
51
            $this->renderingContext
0 ignored issues
show
Bug introduced by
The property renderingContext does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
52
        );
53
    }
54
55
    /**
56
     * @param string $argumentsName
57
     * @param string $closureName
58
     * @param string $initializationPhpCode
59
     * @param ViewHelperNode $node
60
     * @param TemplateCompiler $compiler
61
     * @return string
62
     */
63
    public function compile(
64
        $argumentsName,
65
        $closureName,
66
        &$initializationPhpCode,
67
        ViewHelperNode $node,
0 ignored issues
show
Unused Code introduced by
The parameter $node is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
68
        TemplateCompiler $compiler
0 ignored issues
show
Unused Code introduced by
The parameter $compiler is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
69
    ) {
70
        list ($initialization, $execution) = ViewHelperCompiler::getInstance()->compileWithCallToStaticMethod(
71
            $this,
72
            $argumentsName,
73
            $closureName,
74
            ViewHelperCompiler::RENDER_STATIC,
75
            static::class
76
        );
77
        $contentArgumentName = $this->resolveContentArgumentName();
78
        $initializationPhpCode .= sprintf(
79
            '%s = %s[\'%s\'] ? function() use (%s) { return %s[\'%s\']; } : %s;',
80
            $closureName,
81
            $argumentsName,
82
            $contentArgumentName,
83
            $argumentsName,
84
            $argumentsName,
85
            $contentArgumentName,
86
            $closureName
87
        );
88
        $initializationPhpCode .= $initialization;
89
        return $execution;
90
    }
91
92
    /**
93
     * Helper which is mostly needed when calling renderStatic() from within
94
     * render().
95
     *
96
     * No public API yet.
97
     *
98
     * @return \Closure
99
     */
100
    protected function buildRenderChildrenClosure()
101
    {
102
        $argumentName = $this->resolveContentArgumentName();
103
        $arguments = $this->arguments;
104
        if (!empty($argumentName) && isset($arguments[$argumentName])) {
105
            $renderChildrenClosure = function () use ($arguments, $argumentName) {
106
                return $arguments[$argumentName];
107
            };
108
        } else {
109
            $self = clone $this;
110
            $renderChildrenClosure = function () use ($self) {
111
                return $self->renderChildren();
0 ignored issues
show
Bug introduced by
The method renderChildren() does not exist on TYPO3Fluid\Fluid\Core\Vi...ArgumentAndRenderStatic. Did you maybe mean render()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
112
            };
113
        }
114
        return $renderChildrenClosure;
115
    }
116
117
    /**
118
     * @return string
119
     */
120
    protected function resolveContentArgumentName()
121
    {
122
        if (empty($this->contentArgumentName)) {
123
            $registeredArguments = call_user_func_array([$this, 'prepareArguments'], []);
124
            foreach ($registeredArguments as $registeredArgument) {
125
                if (!$registeredArgument->isRequired()) {
126
                    $this->contentArgumentName = $registeredArgument->getName();
127
                    return $this->contentArgumentName;
128
                }
129
            }
130
            throw new Exception(
131
                'Attempting to compile %s failed. Chosen compile method requires that ViewHelper has ' .
132
                'at least one registered and optional argument'
133
            );
134
        }
135
        return $this->contentArgumentName;
136
    }
137
}
138