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

FluidTYPO3 / vhs / 28589492669

02 Jul 2026 12:19PM UTC coverage: 70.574%. Remained the same
28589492669

push

github

NamelessCoder
[TASK] Catch all throwables instead of just exceptions

0 of 1 new or added line in 1 file covered. (0.0%)

4847 of 6868 relevant lines covered (70.57%)

4.45 hits per line

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

92.0
/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\Core\ViewHelper\AbstractViewHelper;
12
use FluidTYPO3\Vhs\Proxy\DoctrineQueryProxy;
13
use FluidTYPO3\Vhs\Traits\TemplateVariableViewHelperTrait;
14
use FluidTYPO3\Vhs\Utility\ErrorUtility;
15
use FluidTYPO3\Vhs\Utility\RequestResolver;
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

23
/**
24
 * Base class: Record Resource ViewHelpers
25
 */
26
abstract class AbstractRecordResourceViewHelper extends AbstractViewHelper
27
{
28
    use TemplateVariableViewHelperTrait;
29

30
    protected string $table = '';
31
    protected string $field = '';
32
    protected string $idField = 'uid';
33

34
    /**
35
     * @var ConfigurationManagerInterface
36
     */
37
    protected $configurationManager;
38

39
    /**
40
     * @var boolean
41
     */
42
    protected $escapeOutput = false;
43

44
    public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager): void
45
    {
46
        $this->configurationManager = $configurationManager;
34✔
47
    }
48

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

71
    public function getResources(array $record): array
72
    {
73
        $field = $this->getField();
4✔
74

75
        if (!isset($record[$field])) {
4✔
76
            ErrorUtility::throwViewHelperException(
×
77
                'The field "' . $field . '" was not found on the selected record.',
×
78
                1384612728
×
79
            );
×
80
        }
81

82
        if (empty($record[$field])) {
4✔
83
            return [];
2✔
84
        }
85

86
        return GeneralUtility::trimExplode(',', $record[$field]);
2✔
87
    }
88

89
    public function getTable(): string
90
    {
91
        /** @var string|null $table */
92
        $table = $this->arguments['table'] ?? null;
14✔
93
        if (null === $table) {
14✔
94
            $table = $this->table;
4✔
95
        }
96

97
        if (empty($table) || !is_string($table)) {
14✔
98
            ErrorUtility::throwViewHelperException(
4✔
99
                'The "table" argument must be specified and must be a string.',
4✔
100
                1384611336
4✔
101
            );
4✔
102
        }
103

104
        return $table;
10✔
105
    }
106

107
    public function getField(): string
108
    {
109
        /** @var string|null $field */
110
        $field = $this->arguments['field'] ?? null;
10✔
111
        if (null === $field) {
10✔
112
            $field = $this->field;
2✔
113
        }
114

115
        if (empty($field) || !is_string($field)) {
10✔
116
            ErrorUtility::throwViewHelperException(
2✔
117
                'The "field" argument must be specified and must be a string.',
2✔
118
                1384611355
2✔
119
            );
2✔
120
        }
121

122
        return $field;
8✔
123
    }
124

125
    public function getRecord(int $id): ?array
126
    {
127
        $table = $this->getTable();
8✔
128
        $idField = $this->idField;
6✔
129

130
        /** @var ConnectionPool $connectionPool */
131
        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
6✔
132
        /** @var QueryBuilder $queryBuilder */
133
        $queryBuilder = $connectionPool->getQueryBuilderForTable($table);
6✔
134

135
        if (RequestResolver::isPreview()) {
6✔
136
            $queryBuilder->getRestrictions()->removeByType(HiddenRestriction::class);
2✔
137
        }
138

139
        $queryBuilder->createNamedParameter($id, Connection::PARAM_INT, ':id');
6✔
140

141
        $queryBuilder
6✔
142
            ->select('*')
6✔
143
            ->from($table)
6✔
144
            ->where(
6✔
145
                $queryBuilder->expr()->eq($idField, ':id')
6✔
146
            );
6✔
147
        $statement = DoctrineQueryProxy::executeQueryOnQueryBuilder($queryBuilder);
6✔
148
        $result = DoctrineQueryProxy::fetchAssociative($statement);
6✔
149
        return $result;
6✔
150
    }
151

152
    public function render(): string|array
153
    {
154
        /** @var int|null $uid */
155
        $uid = $this->arguments['uid'] ?? null;
12✔
156

157
        /** @var array|null $record */
158
        $record = $this->arguments['record'] ?? $this->getRecord((int) $uid);
12✔
159

160
        if ($record === null) {
10✔
161
            ErrorUtility::throwViewHelperException(
6✔
162
                'No record was found. The "record" or "uid" argument must be specified.',
6✔
163
                1384611413
6✔
164
            );
6✔
165
        }
166

167
        // attempt to load resources. If any Exceptions happen, transform them to
168
        // ViewHelperExceptions which render as an inline text error message.
169
        $content = null;
4✔
170
        try {
171
            $resources = $this->getResources((array) $record);
4✔
172
            /** @var string|array $content */
173
            $content = $this->renderChildrenWithVariableOrReturnInput($resources);
4✔
NEW
174
        } catch (\Throwable $error) {
×
175
            // we are doing the pokemon-thing and catching the very top level
176
            // of Exception because the range of Exceptions that are possibly
177
            // thrown by the getResources() method in subclasses are not
178
            // extended from a shared base class like RuntimeException. Thus,
179
            // we are forced to "catch them all" - but we also output them.
180
            ErrorUtility::throwViewHelperException($error->getMessage(), $error->getCode(), $error);
×
181
        }
182
        return $content ?? '';
4✔
183
    }
184
}
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