• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FluidTYPO3 / vhs / 13566190336

27 Feb 2025 12:18PM UTC coverage: 72.127% (-0.6%) from 72.746%
13566190336

push

github

NamelessCoder
[TER] 7.1.0

5649 of 7832 relevant lines covered (72.13%)

20.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.85
/Classes/ViewHelpers/Resource/Record/AbstractRecordResourceViewHelper.php
1
<?php
2
namespace FluidTYPO3\Vhs\ViewHelpers\Resource\Record;
3

4
/*
5
 * This file is part of the FluidTYPO3/Vhs 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 FluidTYPO3\Vhs\Proxy\DoctrineQueryProxy;
12
use FluidTYPO3\Vhs\Traits\TemplateVariableViewHelperTrait;
13
use FluidTYPO3\Vhs\Utility\ContentObjectFetcher;
14
use FluidTYPO3\Vhs\Utility\ErrorUtility;
15
use TYPO3\CMS\Core\Context\Context;
16
use TYPO3\CMS\Core\Database\Connection;
17
use TYPO3\CMS\Core\Database\ConnectionPool;
18
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
19
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
20
use TYPO3\CMS\Core\Utility\GeneralUtility;
21
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
22
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
23
use TYPO3Fluid\Fluid\Core\ViewHelper\Exception;
24

25
/**
26
 * Base class: Record Resource ViewHelpers
27
 */
28
abstract class AbstractRecordResourceViewHelper extends AbstractViewHelper implements RecordResourceViewHelperInterface
29
{
30
    use TemplateVariableViewHelperTrait;
31

32
    protected string $table = '';
33
    protected string $field = '';
34
    protected string $idField = 'uid';
35

36
    /**
37
     * @var ConfigurationManagerInterface
38
     */
39
    protected $configurationManager;
40

41
    /**
42
     * @var boolean
43
     */
44
    protected $escapeOutput = false;
45

46
    public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager): void
47
    {
48
        $this->configurationManager = $configurationManager;
119✔
49
    }
50

51
    public function initializeArguments(): void
52
    {
53
        $this->registerArgument('table', 'string', 'The table to lookup records.', true);
42✔
54
        $this->registerArgument('field', 'string', 'The field of the table associated to resources.', true);
42✔
55
        $this->registerArgument(
42✔
56
            'record',
42✔
57
            'array',
42✔
58
            'The actual record. Alternatively you can use the "uid" argument.'
42✔
59
        );
42✔
60
        $this->registerArgument(
42✔
61
            'uid',
42✔
62
            'integer',
42✔
63
            'The uid of the record. Alternatively you can use the "record" argument.'
42✔
64
        );
42✔
65
        $this->registerArgument(
42✔
66
            'as',
42✔
67
            'string',
42✔
68
            'If specified, a template variable with this name containing the requested data will be inserted ' .
42✔
69
            'instead of returning it.'
42✔
70
        );
42✔
71
    }
72

73
    /**
74
     * @param mixed $identity
75
     * @return mixed
76
     */
77
    public function getResource($identity)
78
    {
79
        return $identity;
7✔
80
    }
81

82
    public function getResources(array $record): array
83
    {
84
        $field = $this->getField();
35✔
85

86
        if (!isset($record[$field])) {
28✔
87
            ErrorUtility::throwViewHelperException(
14✔
88
                'The "field" argument was not found on the selected record.',
14✔
89
                1384612728
14✔
90
            );
14✔
91
        }
92

93
        if (empty($record[$field])) {
14✔
94
            return [];
7✔
95
        }
96

97
        return GeneralUtility::trimExplode(',', $record[$field]);
7✔
98
    }
99

100
    public function getTable(): string
101
    {
102
        /** @var string|null $table */
103
        $table = $this->arguments['table'] ?? null;
49✔
104
        if (null === $table) {
49✔
105
            $table = $this->table;
7✔
106
        }
107

108
        if (empty($table) || !is_string($table)) {
49✔
109
            ErrorUtility::throwViewHelperException(
7✔
110
                'The "table" argument must be specified and must be a string.',
7✔
111
                1384611336
7✔
112
            );
7✔
113
        }
114

115
        return $table;
42✔
116
    }
117

118
    public function getField(): string
119
    {
120
        /** @var string|null $field */
121
        $field = $this->arguments['field'] ?? null;
63✔
122
        if (null === $field) {
63✔
123
            $field = $this->field;
14✔
124
        }
125

126
        if (empty($field) || !is_string($field)) {
63✔
127
            ErrorUtility::throwViewHelperException(
14✔
128
                'The "field" argument must be specified and must be a string.',
14✔
129
                1384611355
14✔
130
            );
14✔
131
        }
132

133
        return $field;
49✔
134
    }
135

136
    public function getRecord(int $id): ?array
137
    {
138
        $table = $this->getTable();
21✔
139
        $idField = $this->idField;
21✔
140

141
        /** @var ConnectionPool $connectionPool */
142
        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
21✔
143
        /** @var QueryBuilder $queryBuilder */
144
        $queryBuilder = $connectionPool->getQueryBuilderForTable($table);
21✔
145

146
        /** @var Context $context */
147
        $context = GeneralUtility::makeInstance(Context::class);
21✔
148
        $fePreview = $context->hasAspect('frontend.preview')
21✔
149
            && $context->getPropertyFromAspect('frontend.preview', 'isPreview');
21✔
150

151
        if ($fePreview) {
21✔
152
            $queryBuilder->getRestrictions()->removeByType(HiddenRestriction::class);
7✔
153
        }
154

155
        $queryBuilder->createNamedParameter($id, Connection::PARAM_INT, ':id');
21✔
156

157
        $queryBuilder
21✔
158
            ->select('*')
21✔
159
            ->from($table)
21✔
160
            ->where(
21✔
161
                $queryBuilder->expr()->eq($idField, ':id')
21✔
162
            );
21✔
163
        $statement = DoctrineQueryProxy::executeQueryOnQueryBuilder($queryBuilder);
21✔
164
        $result = DoctrineQueryProxy::fetchAssociative($statement);
21✔
165
        return $result;
21✔
166
    }
167

168
    public function getActiveRecord(): array
169
    {
170
        $contentObject = ContentObjectFetcher::resolve($this->configurationManager);
35✔
171
        if ($contentObject === null) {
35✔
172
            throw new Exception(static::class . ' requires a ContentObjectRenderer, none found', 1737807859);
×
173
        }
174
        return $contentObject->data;
35✔
175
    }
176

177
    /**
178
     * @return mixed
179
     */
180
    public function render()
181
    {
182
        /** @var array|null $record */
183
        $record = $this->arguments['record'] ?? null;
42✔
184
        /** @var int|null $uid */
185
        $uid = $this->arguments['uid'] ?? null;
42✔
186

187
        if (null === $record) {
42✔
188
            if (null === $uid) {
42✔
189
                $record = $this->getActiveRecord();
35✔
190
            } else {
191
                $record = $this->getRecord($uid);
7✔
192
            }
193
        }
194

195
        if (null === $record) {
42✔
196
            ErrorUtility::throwViewHelperException(
7✔
197
                'No record was found. The "record" or "uid" argument must be specified.',
7✔
198
                1384611413
7✔
199
            );
7✔
200
        }
201

202
        // attempt to load resources. If any Exceptions happen, transform them to
203
        // ViewHelperExceptions which render as an inline text error message.
204
        $content = null;
35✔
205
        try {
206
            $resources = $this->getResources((array) $record);
35✔
207
            $content = $this->renderChildrenWithVariableOrReturnInput($resources);
14✔
208
        } catch (\Exception $error) {
21✔
209
            // we are doing the pokemon-thing and catching the very top level
210
            // of Exception because the range of Exceptions that are possibly
211
            // thrown by the getResources() method in subclasses are not
212
            // extended from a shared base class like RuntimeException. Thus,
213
            // we are forced to "catch them all" - but we also output them.
214
            ErrorUtility::throwViewHelperException($error->getMessage(), $error->getCode());
21✔
215
        }
216
        return $content;
14✔
217
    }
218
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc