Completed
Push — master ( 6d03f6...61bd88 )
by Fabien
55:58
created

FindOneViewHelper::initializeArguments()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 10
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 10
loc 10
rs 9.4285
cc 1
eloc 7
nc 1
nop 0
1
<?php
2
namespace Fab\Vidi\ViewHelpers\Content;
3
4
/*
5
 * This file is part of the Fab/Vidi project under GPLv2 or later.
6
 *
7
 * For the full copyright and license information, please read the
8
 * LICENSE.md file that was distributed with this source code.
9
 */
10
11
use Fab\Vidi\Domain\Repository\ContentRepositoryFactory;
12
use Fab\Vidi\Persistence\Matcher;
13
use Fab\Vidi\Resolver\FieldPathResolver;
14
use Fab\Vidi\Tca\Tca;
15
use TYPO3\CMS\Core\Utility\ArrayUtility;
16
use TYPO3\CMS\Core\Utility\GeneralUtility;
17
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface;
18
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
19
use TYPO3\CMS\Fluid\Core\ViewHelper\Facets\CompilableInterface;
20
21
/**
22
 * Class FindOneViewHelper
23
 */
24
class FindOneViewHelper extends AbstractViewHelper implements CompilableInterface
25
{
26
27
    /**
28
     * @return void
29
     * @throws \TYPO3\CMS\Fluid\Core\ViewHelper\Exception
30
     */
31 View Code Duplication
    public function initializeArguments()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
32
    {
33
        parent::initializeArguments();
34
35
        $this->registerArgument('type', 'string', 'The content type', true, '');
36
        $this->registerArgument('matches', 'array', 'Key / value array to be used as filter. The key corresponds to a field name.', false, []);
37
        $this->registerArgument('identifier', 'int', 'The identifier of the object to be fetched.', false, 0);
38
        $this->registerArgument('argumentName', 'string', 'The parameter name where to retrieve the identifier', false, 'tx_vidifrontend_pi1|uid');
39
        $this->registerArgument('as', 'string', 'The alias object', false, 'object');
40
    }
41
42
    /**
43
     * @return string Rendered string
44
     * @throws \Fab\Vidi\Exception\NotExistingClassException
45
     * @throws \TYPO3\CMS\Fluid\Core\ViewHelper\Exception\InvalidVariableException
46
     * @throws \InvalidArgumentException
47
     * @api
48
     */
49
    public function render()
50
    {
51
        return static::renderStatic(
52
            $this->arguments,
53
            $this->buildRenderChildrenClosure(),
54
            $this->renderingContext
55
        );
56
    }
57
58
    /**
59
     * @param array $arguments
60
     * @param \Closure $renderChildrenClosure
61
     * @param RenderingContextInterface $renderingContext
62
     *
63
     * @return string
64
     * @throws \Fab\Vidi\Exception\NotExistingClassException
65
     * @throws \TYPO3\CMS\Fluid\Core\ViewHelper\Exception\InvalidVariableException
66
     * @throws \InvalidArgumentException
67
     */
68
    public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
69
    {
70
71
        // Fetch the object
72
        $matches = self::computeMatches($arguments);
73
        $matcher = self::getMatcher($arguments['type'], $matches);
74
75
        $contentRepository = ContentRepositoryFactory::getInstance($arguments['type']);
76
        $object = $contentRepository->findOneBy($matcher);
77
78
        $output = '';
79
        if ($object) {
80
            // Render children with "as" variable.
81
            $templateVariableContainer = $renderingContext->getTemplateVariableContainer();
82
            $templateVariableContainer->add($arguments['as'], $object);
83
            $output = $renderChildrenClosure();
84
            $templateVariableContainer->remove($arguments['as']);
85
        }
86
87
        return $output;
88
    }
89
90
    /**
91
     * @param array $arguments
92
     * @return array
93
     */
94
    protected static function computeMatches(array $arguments)
95
    {
96
97
        $matches = [];
98
99
        $argumentValue = self::getArgumentValue($arguments['argumentName']);
100
        if ($argumentValue > 0) {
101
            $matches['uid'] = $argumentValue;
102
        }
103
104
        if ($arguments['matches']) {
105
            $matches = $arguments['matches'];
106
        }
107
108
        if ($arguments['identifier'] > 0) {
109
            $matches['uid'] = $arguments['identifier'];
110
        }
111
112
        // We want a default value in any case.
113
        if (!$matches) {
114
            $matches['uid'] = 0;
115
        }
116
        return $matches;
117
    }
118
119
    /**
120
     * Returns a matcher object.
121
     *
122
     * @param string $dataType
123
     * @param array $matches
124
     * @return Matcher
125
     * @throws \Fab\Vidi\Exception\NotExistingClassException
126
     * @throws \InvalidArgumentException
127
     */
128
    protected static function getMatcher($dataType, array $matches = [])
129
    {
130
131
        /** @var $matcher Matcher */
132
        $matcher = GeneralUtility::makeInstance(Matcher::class, [], $dataType);
133
134
        foreach ($matches as $fieldNameAndPath => $value) {
135
136
            // CSV values should be considered as "in" operator in Query, otherwise "equals".
137
            $explodedValues = GeneralUtility::trimExplode(',', $value, true);
138
139
            // The matching value contains a "1,2" as example
140
            if (count($explodedValues) > 1) {
141
142
                $resolvedDataType = self::getFieldPathResolver()->getDataType($fieldNameAndPath, $dataType);
143
                $resolvedFieldName = self::getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $dataType);
144
145
                // "equals" if in presence of a relation.
146
                // "in" if not a relation.
147 View Code Duplication
                if (Tca::table($resolvedDataType)->field($resolvedFieldName)->hasRelation()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
148
                    foreach ($explodedValues as $explodedValue) {
149
                        $matcher->equals($fieldNameAndPath, $explodedValue);
150
                    }
151
                } else {
152
                    $matcher->in($fieldNameAndPath, $explodedValues);
153
                }
154
            } else {
155
                $matcher->equals($fieldNameAndPath, $explodedValues[0]);
156
            }
157
        }
158
159
        return $matcher;
160
    }
161
162
    /**
163
     * @return FieldPathResolver
164
     * @throws \InvalidArgumentException
165
     */
166
    protected static function getFieldPathResolver()
167
    {
168
        return GeneralUtility::makeInstance(FieldPathResolver::class);
169
    }
170
171
    /**
172
     * @param string $argumentName
173
     * @return int
174
     */
175
    protected static function getArgumentValue($argumentName)
176
    {
177
178
        $value = ''; // default value
179
180
        // Merge parameters
181
        $parameters = GeneralUtility::_GET();
182
        $post = GeneralUtility::_POST();
183
        ArrayUtility::mergeRecursiveWithOverrule($parameters, $post);
184
185
        // Traverse argument parts and retrieve value.
186
        $argumentParts = GeneralUtility::trimExplode('|', $argumentName);
187 View Code Duplication
        foreach ($argumentParts as $argumentPart) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
188
            if (isset($parameters[$argumentPart])) {
189
                $value = $parameters[$argumentPart];
190
                $parameters = $value;
191
            }
192
        }
193
194
        return (int)$value;
195
    }
196
197
}
198