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

FluidTYPO3 / vhs / 12959392964

24 Jan 2025 11:33PM UTC coverage: 72.434% (-0.05%) from 72.481%
12959392964

Pull #1921

github

web-flow
Merge 424e141d6 into 933ceec1e
Pull Request #1921: [FEATURE] Introduce ContentObjectFetcher

13 of 24 new or added lines in 4 files covered. (54.17%)

1 existing line in 1 file now uncovered.

5547 of 7658 relevant lines covered (72.43%)

13.55 hits per line

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

43.84
/Classes/ViewHelpers/Media/Image/AbstractImageViewHelper.php
1
<?php
2
namespace FluidTYPO3\Vhs\ViewHelpers\Media\Image;
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\Utility\ContentObjectFetcher;
12
use FluidTYPO3\Vhs\Utility\ContextUtility;
13
use FluidTYPO3\Vhs\Utility\FrontendSimulationUtility;
14
use FluidTYPO3\Vhs\ViewHelpers\Media\AbstractMediaViewHelper;
15
use TYPO3\CMS\Core\Utility\CommandUtility;
16
use TYPO3\CMS\Core\Utility\GeneralUtility;
17
use TYPO3\CMS\Core\Utility\MathUtility;
18
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
19
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
20
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
21
use TYPO3Fluid\Fluid\Core\ViewHelper\Exception;
22

23
/**
24
 * Base class for image related view helpers adapted from FLUID
25
 * original image viewhelper.
26
 */
27

28
abstract class AbstractImageViewHelper extends AbstractMediaViewHelper
29
{
30
    /**
31
     * @var ContentObjectRenderer
32
     */
33
    protected $contentObject;
34

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

40
    /**
41
     * Result of \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::getImgResource()
42
     * @var array|null
43
     */
44
    protected $imageInfo;
45

46
    public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager): void
47
    {
48
        $contentObject = ContentObjectFetcher::resolve($configurationManager);
36✔
49
        if ($contentObject === null) {
36✔
NEW
50
            throw new \UnexpectedValueException(static::class . ' requires a cObj context, none was found', 1737756353);
×
51
        }
52
        $this->configurationManager = $configurationManager;
36✔
53
        $this->contentObject = $contentObject;
36✔
54
    }
55

56
    public function initializeArguments(): void
57
    {
58
        parent::initializeArguments();
24✔
59
        $this->registerArgument(
24✔
60
            'width',
24✔
61
            'string',
24✔
62
            'Width of the image. This can be a numeric value representing the fixed width of the image in pixels. ' .
24✔
63
            'But you can also perform simple calculations by adding "m" or "c" to the value. See imgResource.width ' .
24✔
64
            'for possible options.'
24✔
65
        );
24✔
66
        $this->registerArgument(
24✔
67
            'height',
24✔
68
            'string',
24✔
69
            'Height of the image. This can be a numeric value representing the fixed height of the image in pixels. ' .
24✔
70
            'But you can also perform simple calculations by adding "m" or "c" to the value. See imgResource.width ' .
24✔
71
            'for possible options.'
24✔
72
        );
24✔
73
        $this->registerArgument('maxW', 'integer', 'Maximum Width of the image. (no upscaling)');
24✔
74
        $this->registerArgument('maxH', 'integer', 'Maximum Height of the image. (no upscaling)');
24✔
75
        $this->registerArgument('minW', 'integer', 'Minimum Width of the image.');
24✔
76
        $this->registerArgument('minH', 'integer', 'Minimum Height of the image.');
24✔
77
        $this->registerArgument(
24✔
78
            'format',
24✔
79
            'string',
24✔
80
            'Format of the processed file - also determines the target file format. If blank, TYPO3/IM/GM default is ' .
24✔
81
            'taken into account.'
24✔
82
        );
24✔
83
        $this->registerArgument(
24✔
84
            'quality',
24✔
85
            'integer',
24✔
86
            'Quality of the processed image. If blank/not present falls back to the default quality defined in ' .
24✔
87
            'install tool.',
24✔
88
            false,
24✔
89
            $GLOBALS['TYPO3_CONF_VARS']['GFX']['jpg_quality'] ?? 90
24✔
90
        );
24✔
91
        $this->registerArgument(
24✔
92
            'treatIdAsReference',
24✔
93
            'boolean',
24✔
94
            'When TRUE treat given src argument as sys_file_reference record. Applies only to TYPO3 6.x and above.',
24✔
95
            false,
24✔
96
            false
24✔
97
        );
24✔
98
        $this->registerArgument('canvasWidth', 'integer', 'Width of an optional canvas to place the image on.');
24✔
99
        $this->registerArgument('canvasHeight', 'integer', 'Height of an optional canvas to place the image on.');
24✔
100
        $this->registerArgument(
24✔
101
            'canvasColor',
24✔
102
            'string',
24✔
103
            'Background color of an optional canvas to place the image on (hex triplet).'
24✔
104
        );
24✔
105
        $this->registerArgument(
24✔
106
            'transparencyColor',
24✔
107
            'string',
24✔
108
            'Color to set transparent when using canvas feature (hex triplet).'
24✔
109
        );
24✔
110
        $this->registerArgument('crop', 'string', 'Information generated by the backend\'s graphical cropping UI');
24✔
111
        $this->registerArgument(
24✔
112
            'graceful',
24✔
113
            'bool',
24✔
114
            'Set to TRUE to ignore files that cannot be loaded. Default behavior is to throw an Exception.',
24✔
115
            false,
24✔
116
            false
24✔
117
        );
24✔
118
    }
119

120
    public function preprocessImage(?string $imageSource = null): void
121
    {
122
        /** @var string $src */
123
        $src = (null === $imageSource) ? $this->arguments['src'] : $imageSource;
×
124
        $width = $this->arguments['width'];
×
125
        $height = $this->arguments['height'];
×
126
        $minW = $this->arguments['minW'];
×
127
        $minH = $this->arguments['minH'];
×
128
        $maxW = $this->arguments['maxW'];
×
129
        $maxH = $this->arguments['maxH'];
×
130
        $format = $this->arguments['format'];
×
131
        /** @var int $quality */
132
        $quality = $this->arguments['quality'];
×
133
        $treatIdAsReference = (boolean) $this->arguments['treatIdAsReference'];
×
134
        $crop = $this->arguments['crop'];
×
135

136
        if ($src instanceof FileReference) {
×
137
            if ($crop === null) {
×
138
                $crop = $src->_getProperty('crop');
×
139
            }
140
            $src = $src->getUid();
×
141
            $treatIdAsReference = true;
×
142
        }
143

144
        $tsfeBackup = FrontendSimulationUtility::simulateFrontendEnvironment();
×
145

146
        $setup = [
×
147
            'width' => $width,
×
148
            'height' => $height,
×
149
            'minW' => $minW,
×
150
            'minH' => $minH,
×
151
            'maxW' => $maxW,
×
152
            'maxH' => $maxH,
×
153
            'treatIdAsReference' => $treatIdAsReference,
×
154
            'crop' => $crop,
×
155
        ];
×
156
        if (!empty($format)) {
×
157
            $setup['ext'] = $format;
×
158
        }
159
        if (0 < (integer) $quality) {
×
160
            /** @var int $quality */
161
            $quality = MathUtility::forceIntegerInRange($quality, 10, 100, 75);
×
162
            $setup['params'] = '-quality ' . $quality;
×
163
        }
164

165
        if (ContextUtility::isBackend() && strpos($src, '../') === 0) {
×
166
            $src = mb_substr($src, 3);
×
167
        }
168
        $this->imageInfo = $this->contentObject->getImgResource($src, $setup);
×
169

170
        if (!is_array($this->imageInfo)) {
×
171
            if ($this->arguments['graceful'] ?? false) {
×
172
                $this->mediaSource = '';
×
173
                FrontendSimulationUtility::resetFrontendEnvironment($tsfeBackup);
×
174
                return;
×
175
            }
176
            throw new Exception('Could not get image resource for "' . htmlspecialchars($src) . '".', 1253191060);
×
177
        }
178

179
        if (property_exists($GLOBALS['TSFE'], 'lastImageInfo')) {
×
180
            $GLOBALS['TSFE']->lastImageInfo = $this->imageInfo;
×
181
        }
182

183
        if ($this->hasArgument('canvasWidth') && $this->hasArgument('canvasHeight')) {
×
184
            /** @var int $canvasWidth */
185
            $canvasWidth = $this->arguments['canvasWidth'];
×
186
            /** @var int $canvasHeight */
187
            $canvasHeight = $this->arguments['canvasHeight'];
×
188
            /** @var string $canvasColor */
189
            $canvasColor = $this->arguments['canvasColor'] ?? '';
×
190
            $canvasColor = str_replace('#', '', $canvasColor);
×
191
            $originalFilename = $this->imageInfo[3];
×
192
            $originalExtension = mb_substr($originalFilename, -3);
×
193
            $tempPath = 'typo3temp/assets/';
×
194
            $destinationFilename = $tempPath .
×
195
                'vhs-canvas-' .
×
196
                md5($originalFilename . $canvasColor . $canvasWidth . $canvasHeight) .
×
197
                '.' .
×
198
                $originalExtension;
×
199
            $destinationFilepath = GeneralUtility::getFileAbsFileName($destinationFilename);
×
200
            $transparency = '';
×
201
            if ($this->hasArgument('transparencyColor')) {
×
202
                /** @var string $transparencyColor */
203
                $transparencyColor = $this->arguments['transparencyColor'];
×
204
                $transparencyColor = str_replace('#', '', $transparencyColor);
×
205
                $transparency = ' -transparent \'#' . $transparencyColor . '\'';
×
206
            }
207
            if (!file_exists($destinationFilepath)) {
×
208
                $arguments = sprintf(
×
209
                    '%s -background \'#%s\'%s -gravity center -extent %dx%d %s',
×
210
                    $originalFilename,
×
211
                    $canvasColor,
×
212
                    $transparency,
×
213
                    $canvasWidth,
×
214
                    $canvasHeight,
×
215
                    $destinationFilepath
×
216
                );
×
217
                $command = CommandUtility::imageMagickCommand('convert', $arguments);
×
218
                CommandUtility::exec($command);
×
219
            }
220
            $this->mediaSource = $destinationFilename;
×
221
        } elseif ($this->imageInfo['processedFile'] ?? false) {
×
222
            $this->mediaSource = $this->imageInfo['processedFile']->getPublicUrl();
×
223
        } else {
224
            $this->mediaSource = rawurldecode($this->imageInfo[3]);
×
225
        }
226

227
        if (property_exists($GLOBALS['TSFE'], 'imagesOnPage')) {
×
228
            $GLOBALS['TSFE']->imagesOnPage[] = $this->imageInfo[3];
×
229
        }
230

231
        FrontendSimulationUtility::resetFrontendEnvironment($tsfeBackup);
×
232
    }
233
}
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