‪TYPO3CMS  ‪main
ImageViewHelperTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use PHPUnit\Framework\Attributes\DataProvider;
21 use PHPUnit\Framework\Attributes\Test;
33 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
34 use TYPO3Fluid\Fluid\Core\ViewHelper\Exception;
35 use TYPO3Fluid\Fluid\View\TemplateView;
36 
37 final class ‪ImageViewHelperTest extends FunctionalTestCase
38 {
40  'typo3/sysext/fluid/Tests/Functional/Fixtures/ViewHelpers/ImageViewHelper/Folders/fileadmin/' => 'fileadmin/',
41  ];
42 
43  public function ‪setUp(): void
44  {
45  parent::setUp();
46  $this->importCSVDataSet(__DIR__ . '/../../Fixtures/ViewHelpers/ImageViewHelper/fal_image.csv');
47  }
48 
49  public static function ‪invalidArgumentsDataProvider(): array
50  {
51  return [
52  [
53  '<f:uri.image />',
54  1460976233,
55  'Unable to render image uri: You must either specify a string src or a File object.',
56  ],
57  [
58  '<f:uri.image src="" />',
59  1460976233,
60  'Unable to render image uri: You must either specify a string src or a File object.',
61  ],
62  [
63  '<f:uri.image src="something" />',
64  1509741907,
65  'Unable to render image uri: Folder "/something/" does not exist.',
66  ],
67  [
68  '<f:uri.image src="EXT:fluid/Tests/Functional/Fixtures/ViewHelpers/" />',
69  1509741910,
70  'Unable to render image uri: File /typo3/sysext/fluid/Tests/Functional/Fixtures/ViewHelpers does not exist.',
71  ],
72  [
73  '<f:uri.image src="fileadmin/image.jpg" />',
74  1509741908,
75  'Unable to render image uri: Supplied fileadmin/image.jpg could not be resolved to a File or FileReference.',
76  ],
77  [
78  '<f:uri.image src="something" fileExtension="dummy" />',
79  1618992262,
80  'Unable to render image uri: The extension dummy is not specified in $GLOBALS[\'TYPO3_CONF_VARS\'][\'GFX\'][\'imagefile_ext\'] as a valid image file extension and can not be processed.',
81  ],
82  ];
83  }
84 
85  #[DataProvider('invalidArgumentsDataProvider')]
86  #[Test]
87  public function ‪renderThrowsExceptionOnInvalidArguments(string $template, int $expectedExceptionCode, string $message): void
88  {
89  $this->expectException(Exception::class);
90  $this->expectExceptionCode($expectedExceptionCode);
91  $this->expectExceptionMessage($message);
92 
93  $context = $this->get(RenderingContextFactory::class)->create();
94  $context->getTemplatePaths()->setTemplateSource($template);
95  (new TemplateView($context))->render();
96  }
97 
99  {
100  return [
101  [
102  '<f:uri.image />',
103  1460976233,
104  'Unable to render image uri in "tt_content:123": You must either specify a string src or a File object.',
105  ],
106  [
107  '<f:uri.image src="" />',
108  1460976233,
109  'Unable to render image uri in "tt_content:123": You must either specify a string src or a File object.',
110  ],
111  [
112  '<f:uri.image src="something" />',
113  1509741907,
114  'Unable to render image uri in "tt_content:123": Folder "/something/" does not exist.',
115  ],
116  [
117  '<f:uri.image src="EXT:fluid/Tests/Functional/Fixtures/ViewHelpers/" />',
118  1509741910,
119  'Unable to render image uri in "tt_content:123": File /typo3/sysext/fluid/Tests/Functional/Fixtures/ViewHelpers does not exist.',
120  ],
121  [
122  '<f:uri.image src="fileadmin/image.jpg" />',
123  1509741908,
124  'Unable to render image uri in "tt_content:123": Supplied fileadmin/image.jpg could not be resolved to a File or FileReference.',
125  ],
126  [
127  '<f:uri.image src="something" fileExtension="dummy" />',
128  1618992262,
129  'Unable to render image uri in "tt_content:123": The extension dummy is not specified in $GLOBALS[\'TYPO3_CONF_VARS\'][\'GFX\'][\'imagefile_ext\'] as a valid image file extension and can not be processed.',
130  ],
131  ];
132  }
133 
134  #[DataProvider('invalidArgumentsWithContentObjectPresentDataProvider')]
135  #[Test]
136  public function ‪renderThrowsExceptionWithContentObjectPresentOnInvalidArguments(string $template, int $expectedExceptionCode, string $message): void
137  {
138  $this->expectException(Exception::class);
139  $this->expectExceptionCode($expectedExceptionCode);
140  $this->expectExceptionMessage($message);
141 
142  $cObj = new ‪ContentObjectRenderer();
143  $cObj->start(['uid' => 123], 'tt_content');
144  $serverRequest = (new ‪ServerRequest())
145  ->withAttribute('currentContentObject', $cObj)
146  ->withAttribute('extbase', new ‪ExtbaseRequestParameters())
147  ->withAttribute('applicationType', ‪SystemEnvironmentBuilder::REQUESTTYPE_BE);
148 
149  $context = $this->get(RenderingContextFactory::class)->create();
150  $context->setRequest(new ‪Request($serverRequest));
151  $context->getTemplatePaths()->setTemplateSource($template);
152  (new TemplateView($context))->render();
153  }
154 
155  public static function ‪basicScalingCroppingDataProvider(): \Generator
156  {
157  yield 'original size' => [
158  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" />',
159  '@^(fileadmin/ImageViewHelperTest\.jpg)$@',
160  400,
161  300,
162  ];
163  yield 'half width' => [
164  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" width="200" />',
165  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
166  200,
167  150,
168  ];
169  yield 'stretched' => [
170  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" width="200" height="200" />',
171  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
172  200,
173  200,
174  ];
175  yield 'inline-cropped' => [
176  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" width="100c" height="100c" />',
177  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
178  100,
179  100,
180  ];
181  yield 'inline-max width' => [
182  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" width="300m" height="300m" />',
183  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
184  300,
185  225,
186  ];
187  yield 'inline-max height' => [
188  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" width="400m" height="150m" />',
189  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
190  200,
191  150,
192  ];
193  yield 'inline-max width & height' => [
194  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" width="200m" height="150m" />',
195  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
196  200,
197  150,
198  ];
199  yield 'inline-max width does not upscale' => [
200  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" width="500m" />',
201  '@^(fileadmin/ImageViewHelperTest\.jpg)$@',
202  400,
203  300,
204  ];
205  yield 'inline-max height does not upscale' => [
206  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" height="350m" />',
207  '@^(fileadmin/ImageViewHelperTest\.jpg)$@',
208  400,
209  300,
210  ];
211  yield 'min width' => [
212  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" height="150" minWidth="250" />',
213  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
214  250,
215  188,
216  ];
217  // would be 200x150, but image will be scaled down to have a width of 100
218  yield 'max width' => [
219  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" height="150" maxWidth="100" />',
220  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
221  100,
222  75,
223  ];
224  yield 'min height' => [
225  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" width="200" minHeight="200" />',
226  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
227  267,
228  200,
229  ];
230  // would be 200x150, but image will be scaled down to have a height of 75
231  yield 'max height' => [
232  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" width="200" maxHeight="75" />',
233  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
234  100,
235  75,
236  ];
237  yield 'file record' => [
238  '<f:uri.image image="{fileReference.originalFile}" />',
239  '@^(fileadmin/user_upload/ImageViewHelperFalTest\.jpg)$@',
240  400,
241  300,
242  ];
243  yield 'file id' => [
244  '<f:uri.image src="1" />',
245  '@^(fileadmin/user_upload/ImageViewHelperFalTest\.jpg)$@',
246  400,
247  300,
248  ];
249  yield 'file reference record' => [
250  '<f:uri.image image="{fileReference}" cropVariant="square" />',
251  '@^(fileadmin/_processed_/c/f/csm_ImageViewHelperFalTest_.*\.jpg)$@',
252  300,
253  300,
254  ];
255  yield 'file reference id' => [
256  '<f:uri.image src="1" treatIdAsReference="1" cropVariant="square" />',
257  '@^(fileadmin/_processed_/c/f/csm_ImageViewHelperFalTest_.*\.jpg)$@',
258  300,
259  300,
260  ];
261  }
262 
263  #[DataProvider('basicScalingCroppingDataProvider')]
264  #[Test]
265  public function ‪basicScalingCropping(string $template, string $expected, int $expectedWidth, int $expectedHeight): void
266  {
267  $context = $this->get(RenderingContextFactory::class)->create();
268  $context->getVariableProvider()->add('fileReference', $this->get(ResourceFactory::class)->getFileReferenceObject(1));
269  $context->getTemplatePaths()->setTemplateSource($template);
270  $result = (new TemplateView($context))->render();
271  self::assertMatchesRegularExpression($expected, $result);
272 
273  $matches = [];
274  preg_match($expected, $result, $matches);
275  [$width, $height] = getimagesize($this->instancePath . '/' . $matches[1]);
276  self::assertEquals($expectedWidth, $width, 'width of generated image does not match expected width');
277  self::assertEquals($expectedHeight, $height, 'height of generated image does not match expected height');
278  }
279 
280  public static function ‪cropVariantDataProvider(): \Generator
281  {
282  yield 'crop false' => [
283  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" crop="false" />',
284  '@^(fileadmin/ImageViewHelperTest\.jpg)$@',
285  400,
286  300,
287  ];
288  yield 'crop null' => [
289  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" crop="null" />',
290  '@^(fileadmin/ImageViewHelperTest\.jpg)$@',
291  400,
292  300,
293  ];
294  yield 'crop as array' => [
295  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" crop="{default: {cropArea: {x: 0.2, y: 0.2, width: 0.5, height: 0.5}}}" />',
296  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
297  200,
298  150,
299  ];
300  yield 'default crop variant' => [
301  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" crop="{crop}" />',
302  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
303  200,
304  225,
305  ];
306  yield 'square crop variant' => [
307  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" crop="{crop}" cropVariant="square" />',
308  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
309  300,
310  300,
311  ];
312  yield 'wide crop variant' => [
313  '<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" crop="{crop}" cropVariant="wide" />',
314  '@^(fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.jpg)$@',
315  400,
316  200,
317  ];
318  }
319 
320  #[DataProvider('cropVariantDataProvider')]
321  #[Test]
322  public function ‪cropVariant(string $template, string $expected, int $expectedWidth, int $expectedHeight): void
323  {
324  // Based on 400x300 dimensions
325  $cropVariantCollection = new ‪CropVariantCollection([
326  new ‪CropVariant('default', 'Default', new ‪Area(0.25, 0.25, 0.5, 0.75)),
327  new ‪CropVariant('square', 'Square', new ‪Area(0.125, 0, 0.75, 1)),
328  new ‪CropVariant('wide', 'Wide', new ‪Area(0, 1 / 6, 1, 2 / 3)),
329  ]);
330 
331  $context = $this->get(RenderingContextFactory::class)->create();
332  $context->getVariableProvider()->add('crop', (string)$cropVariantCollection);
333  $context->getTemplatePaths()->setTemplateSource($template);
334  $result = (new TemplateView($context))->render();
335  self::assertMatchesRegularExpression($expected, $result);
336 
337  $matches = [];
338  preg_match($expected, $result, $matches);
339  [$width, $height] = getimagesize($this->instancePath . '/' . $matches[1]);
340  self::assertEquals($expectedWidth, $width, 'width of generated image does not match expected width');
341  self::assertEquals($expectedHeight, $height, 'height of generated image does not match expected height');
342  }
343 
344  #[Test]
345  public function ‪fileExtensionArgument(): void
346  {
347  $context = $this->get(RenderingContextFactory::class)->create();
348  $context->getTemplatePaths()->setTemplateSource('<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" fileExtension="png" />');
349  self::assertMatchesRegularExpression(
350  '@^fileadmin/_processed_/5/3/csm_ImageViewHelperTest_.*\.png$@',
351  (new TemplateView($context))->render(),
352  );
353  }
354 
355  #[Test]
356  public function ‪absoluteArgument(): void
357  {
358  GeneralUtility::setIndpEnv('TYPO3_REQUEST_DIR', 'https://typo3-testing.local/');
359 
360  $context = $this->get(RenderingContextFactory::class)->create();
361  $context->getTemplatePaths()->setTemplateSource('<f:uri.image src="fileadmin/ImageViewHelperTest.jpg" absolute="1" />');
362  self::assertEquals(
363  'https://typo3-testing.local/fileadmin/ImageViewHelperTest.jpg',
364  (new TemplateView($context))->render(),
365  );
366  }
367 }
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest\invalidArgumentsDataProvider
‪static invalidArgumentsDataProvider()
Definition: ImageViewHelperTest.php:49
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest\invalidArgumentsWithContentObjectPresentDataProvider
‪static invalidArgumentsWithContentObjectPresentDataProvider()
Definition: ImageViewHelperTest.php:98
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest
Definition: ImageViewHelperTest.php:38
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariant
Definition: CropVariant.php:23
‪TYPO3\CMS\Core\Imaging\ImageManipulation\Area
Definition: Area.php:23
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder
Definition: SystemEnvironmentBuilder.php:41
‪TYPO3\CMS\Core\Core\SystemEnvironmentBuilder\REQUESTTYPE_BE
‪const REQUESTTYPE_BE
Definition: SystemEnvironmentBuilder.php:45
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest\renderThrowsExceptionOnInvalidArguments
‪renderThrowsExceptionOnInvalidArguments(string $template, int $expectedExceptionCode, string $message)
Definition: ImageViewHelperTest.php:87
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest\cropVariantDataProvider
‪static cropVariantDataProvider()
Definition: ImageViewHelperTest.php:280
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest\absoluteArgument
‪absoluteArgument()
Definition: ImageViewHelperTest.php:356
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest\renderThrowsExceptionWithContentObjectPresentOnInvalidArguments
‪renderThrowsExceptionWithContentObjectPresentOnInvalidArguments(string $template, int $expectedExceptionCode, string $message)
Definition: ImageViewHelperTest.php:136
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest\fileExtensionArgument
‪fileExtensionArgument()
Definition: ImageViewHelperTest.php:345
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest\$pathsToProvideInTestInstance
‪array $pathsToProvideInTestInstance
Definition: ImageViewHelperTest.php:39
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:42
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest\cropVariant
‪cropVariant(string $template, string $expected, int $expectedWidth, int $expectedHeight)
Definition: ImageViewHelperTest.php:322
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest\basicScalingCroppingDataProvider
‪static basicScalingCroppingDataProvider()
Definition: ImageViewHelperTest.php:155
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest\setUp
‪setUp()
Definition: ImageViewHelperTest.php:43
‪TYPO3\CMS\Core\Http\ServerRequest
Definition: ServerRequest.php:39
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri
Definition: ActionViewHelperTest.php:18
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection
Definition: CropVariantCollection.php:23
‪TYPO3\CMS\Fluid\Core\Rendering\RenderingContextFactory
Definition: RenderingContextFactory.php:51
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:102
‪TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters
Definition: ExtbaseRequestParameters.php:35
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Extbase\Mvc\Request
Definition: Request.php:35
‪TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri\ImageViewHelperTest\basicScalingCropping
‪basicScalingCropping(string $template, string $expected, int $expectedWidth, int $expectedHeight)
Definition: ImageViewHelperTest.php:265