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

FluidTYPO3 / vhs / 30001290505

23 Jul 2026 10:57AM UTC coverage: 70.309% (-1.7%) from 72.022%
30001290505

push

github

NamelessCoder
[TER] 8.0.0

4819 of 6854 relevant lines covered (70.31%)

6.54 hits per line

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

46.25
/Classes/ViewHelpers/Media/SourceViewHelper.php
1
<?php
2
namespace FluidTYPO3\Vhs\ViewHelpers\Media;
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\ImageResourceProxy;
12
use FluidTYPO3\Vhs\Traits\TagViewHelperCompatibility;
13
use FluidTYPO3\Vhs\Utility\ContentObjectFetcher;
14
use FluidTYPO3\Vhs\Utility\ContextUtility;
15
use FluidTYPO3\Vhs\Utility\FrontendSimulationUtility;
16
use FluidTYPO3\Vhs\Utility\ParameterUtility;
17
use TYPO3\CMS\Core\Resource\FileReference;
18
use TYPO3\CMS\Core\Utility\GeneralUtility;
19
use TYPO3\CMS\Core\Utility\MathUtility;
20
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
21
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper;
22

23
/**
24
 * Used in conjuntion with the `v:media.PictureViewHelper`.
25
 * Please take a look at the `v:media.PictureViewHelper` documentation for more
26
 * information.
27
 */
28
class SourceViewHelper extends AbstractTagBasedViewHelper
29
{
30
    use TagViewHelperCompatibility;
31

32
    public const string SCOPE = 'FluidTYPO3\Vhs\ViewHelpers\Media\PictureViewHelper';
33
    public const string SCOPE_VARIABLE_SRC = 'src';
34
    public const string SCOPE_VARIABLE_ID = 'treatIdAsReference';
35
    public const string SCOPE_VARIABLE_DEFAULT_SOURCE = 'default-source';
36

37
    /**
38
     * name of the tag to be created by this view helper
39
     *
40
     * @var string
41
     * @api
42
     */
43
    protected $tagName = 'source';
44
    /**
45
     * @var ConfigurationManagerInterface
46
     */
47
    protected $configurationManager;
48

49
    public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager): void
50
    {
51
        $this->configurationManager = $configurationManager;
6✔
52
    }
53

54
    public function initializeArguments(): void
55
    {
56
        parent::initializeArguments();
3✔
57
        $this->registerUniversalTagAttributes();
3✔
58
        $this->registerArgument('media', 'string', 'Media query for which breakpoint this sources applies');
3✔
59
        $this->registerArgument(
3✔
60
            'width',
3✔
61
            'string',
3✔
62
            'Width of the image. This can be a numeric value representing the fixed width of the image in pixels. ' .
3✔
63
            'But you can also perform simple calculations by adding "m" or "c" to the value. See imgResource.width ' .
3✔
64
            'for possible options.'
3✔
65
        );
3✔
66
        $this->registerArgument(
3✔
67
            'height',
3✔
68
            'string',
3✔
69
            'Height of the image. This can be a numeric value representing the fixed height of the image in pixels. ' .
3✔
70
            'But you can also perform simple calculations by adding "m" or "c" to the value. See imgResource.width ' .
3✔
71
            'for possible options.'
3✔
72
        );
3✔
73
        $this->registerArgument('maxW', 'integer', 'Maximum Width of the image. (no upscaling)');
3✔
74
        $this->registerArgument('maxH', 'integer', 'Maximum Height of the image. (no upscaling)');
3✔
75
        $this->registerArgument('minW', 'integer', 'Minimum Width of the image.');
3✔
76
        $this->registerArgument('minH', 'integer', 'Minimum Height of the image.');
3✔
77
        $this->registerArgument(
3✔
78
            'format',
3✔
79
            'string',
3✔
80
            'Format of the processed file - also determines the target file format. If blank, TYPO3/IM/GM default ' .
3✔
81
            'is taken into account.'
3✔
82
        );
3✔
83
        $this->registerArgument(
3✔
84
            'quality',
3✔
85
            'integer',
3✔
86
            'Quality of the processed image. If blank/not present falls back to the default quality defined ' .
3✔
87
            'in install tool.',
3✔
88
            false,
3✔
89
            $GLOBALS['TYPO3_CONF_VARS']['GFX']['jpg_quality'] ?? 90
3✔
90
        );
3✔
91
        $this->registerArgument('relative', 'boolean', 'Produce a relative URL instead of absolute', false, false);
3✔
92
    }
93

94
    public function render(): string
95
    {
96
        $viewHelperVariableContainer = $this->renderingContext->getViewHelperVariableContainer();
×
97
        /** @var FileReference|string $imageSource */
98
        $imageSource = $viewHelperVariableContainer->get(static::SCOPE, static::SCOPE_VARIABLE_SRC);
×
99
        $treatIdAsRerefence = $viewHelperVariableContainer->get(static::SCOPE, static::SCOPE_VARIABLE_ID);
×
100

101
        $tsfeBackup = FrontendSimulationUtility::simulateFrontendEnvironment();
×
102

103
        $setup = [
×
104
            'width' => $this->arguments['width'],
×
105
            'height' => $this->arguments['height'],
×
106
            'minW' => $this->arguments['minW'],
×
107
            'minH' => $this->arguments['minH'],
×
108
            'maxW' => $this->arguments['maxW'],
×
109
            'maxH' => $this->arguments['maxH'],
×
110
            'treatIdAsReference' => $treatIdAsRerefence,
×
111
            'params' => '',
×
112
        ];
×
113
        /** @var int $quality */
114
        $quality = $this->arguments['quality'];
×
115
        /** @var string $format */
116
        $format = $this->arguments['format'];
×
117

118
        if (!empty($format)) {
×
119
            $setup['ext'] = $format;
×
120
        }
121
        if (0 < intval($quality)) {
×
122
            $quality = MathUtility::forceIntegerInRange($quality, 10, 100, 75);
×
123
            $setup['params'] .= ' -quality ' . $quality;
×
124
        }
125

126
        if (is_string($imageSource) && ContextUtility::isBackend() && '../' === mb_substr($imageSource, 0, 3)) {
×
127
            $imageSource = mb_substr($imageSource, 3);
×
128
        }
129
        $contentObject = ContentObjectFetcher::resolve($this->configurationManager);
×
130

131
        $result = new ImageResourceProxy($contentObject->getImgResource($imageSource, $setup));
×
132
        $imageUrl = $result->getPublicUrl();
×
133
        $src = $this->preprocessSourceUri(rawurldecode((string) $imageUrl));
×
134

135
        /** @var string|null $media */
136
        $media = $this->arguments['media'];
×
137

138
        if (null === $media) {
×
139
            $viewHelperVariableContainer->addOrUpdate(static::SCOPE, static::SCOPE_VARIABLE_DEFAULT_SOURCE, $src);
×
140
        } else {
141
            $this->tag->addAttribute('media', $media);
×
142
        }
143

144
        $this->tag->addAttribute('srcset', $src);
×
145
        return $this->tag->render();
×
146
    }
147

148
    /**
149
     * Turns a relative source URI into an absolute URL
150
     * if required.
151
     */
152
    public function preprocessSourceUri(string $src): string
153
    {
154
        if (!empty($GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_vhs.']['settings.']['prependPath'])) {
×
155
            $src = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_vhs.']['settings.']['prependPath'] . $src;
×
156
        } elseif (ContextUtility::isBackend() || !$this->arguments['relative']) {
×
157
            if (GeneralUtility::isValidUrl($src)) {
×
158
                $src = ltrim($src, '/');
×
159
            } elseif (ContextUtility::isFrontend()) {
×
160
                $src = $GLOBALS['TSFE']->absRefPrefix . ltrim($src, '/');
×
161
            } else {
162
                /** @var string $siteUrl */
163
                $siteUrl = ParameterUtility::resolveParameterValue('TYPO3_SITE_URL');
×
164
                $src = $siteUrl . ltrim($src, '/');
×
165
            }
166
        }
167
        return $src;
×
168
    }
169
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc