‪TYPO3CMS  ‪main
MetaTagGeneratorTest.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 
35 final class ‪MetaTagGeneratorTest extends FunctionalTestCase
36 {
39  protected array ‪$coreExtensionsToLoad = ['seo'];
40 
41  protected function ‪setUp(): void
42  {
43  parent::setUp();
44  // functional tests use GraphicMagick per default, resolve the corresponding path in current OS
45  ‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path'] = $this->‪determineGraphicMagickBinaryPath();
46  $this->subject = GeneralUtility::makeInstance(MetaTagGenerator::class);
47  $this->defaultStorage = GeneralUtility::makeInstance(StorageRepository::class)->getDefaultStorage();
48  }
49 
50  public static function ‪socialImageIsProcessedDataProvider(): \Generator
51  {
52  // having a valid `crop` definition, images are only process if there's a necessity
53  yield 'social: 600x600 enforced ratio' => [
54  true,
55  ['width' => 600, 'height' => 600],
56  ['width' => 600, 'height' => 315],
57  ProcessedFile::class,
58  ];
59  yield 'social: 600x315 kept as is' => [
60  true,
61  ['width' => 600, 'height' => 315],
62  ['width' => 600, 'height' => 315],
63  File::class,
64  ];
65  yield 'social: 1200x630 kept as is' => [
66  true,
67  ['width' => 1200, 'height' => 630],
68  ['width' => 1200, 'height' => 630],
69  File::class,
70  ];
71  yield 'social: 2400x1260 limited to maxWidth, kept ratio' => [
72  true,
73  ['width' => 2400, 'height' => 1260],
74  ['width' => 2000, 'height' => 1050],
75  ProcessedFile::class,
76  ];
77  yield 'social: 3000x3000 limited to maxWidth, enforced ratio' => [
78  true,
79  ['width' => 3000, 'height' => 3000],
80  ['width' => 2000, 'height' => 1050],
81  ProcessedFile::class,
82  ];
83  yield 'social: 600x300 enforced ratio (no up-scaling)' => [
84  true,
85  ['width' => 600, 'height' => 3000],
86  ['width' => 600, 'height' => 315],
87  ProcessedFile::class,
88  ];
89  yield 'social: 3000x600 enforced ratio (no up-scaling)' => [
90  true,
91  ['width' => 3000, 'height' => 600],
92  // width = round(1200/630*600)
93  ['width' => 1143, 'height' => 600],
94  ProcessedFile::class,
95  ];
96 
97  // in case `crop` is not defined, no target ratio is defined for these images
98  // (data created prior to https://review.typo3.org/c/Packages/TYPO3.CMS/+/58774/ in v9.5.1 behaves like this)
99  yield 'empty crop: 600x600 kept as is' => [
100  false,
101  ['width' => 600, 'height' => 600],
102  ['width' => 600, 'height' => 600],
103  File::class,
104  ];
105  yield 'empty crop: 600x315 kept as is' => [
106  false,
107  ['width' => 600, 'height' => 315],
108  ['width' => 600, 'height' => 315],
109  File::class,
110  ];
111  yield 'empty crop: 1200x630 kept as is' => [
112  false,
113  ['width' => 1200, 'height' => 630],
114  ['width' => 1200, 'height' => 630],
115  File::class,
116  ];
117  yield 'empty crop: 2400x1260 limited to maxWidth' => [
118  false,
119  ['width' => 2400, 'height' => 1260],
120  ['width' => 2000, 'height' => 1050],
121  ProcessedFile::class,
122  ];
123  yield 'empty crop: 3000x3000 limited to maxWidth' => [
124  false,
125  ['width' => 3000, 'height' => 3000],
126  ['width' => 2000, 'height' => 2000],
127  ProcessedFile::class,
128  ];
129  yield 'empty crop: 600x300 kept as is' => [
130  false,
131  ['width' => 600, 'height' => 3000],
132  ['width' => 600, 'height' => 3000],
133  File::class,
134  ];
135  yield 'empty crop: 3000x600 limited to maxWidth' => [
136  false,
137  ['width' => 3000, 'height' => 600],
138  ['width' => 2000, 'height' => 400],
139  ProcessedFile::class,
140  ];
141  }
142 
147  #[DataProvider('socialImageIsProcessedDataProvider')]
148  #[Test]
149  public function ‪socialImageIsProcessed(bool $hasCrop, array $imageDimension, array $expectedDimension, string $expectedClassName): void
150  {
151  $fileName = sprintf('test_%dx%d.png', $imageDimension['width'], $imageDimension['height']);
152  $folder = $this->defaultStorage->getFolder('/');
153  // drop file if it exists
154  $file = $folder->getFile($fileName);
155  if ($file !== null) {
156  $file->delete();
157  }
158  // create new file, fill it dummy PNG data for given dimension
160  $file = $this->defaultStorage->createFile($fileName, $folder);
161  $file->setContents($this->‪createImagePngContent($imageDimension['width'], $imageDimension['height']));
162  // temporary file reference to an actual existing file
163  $fileReferenceProperties = [
164  'uid_local' => $file->getUid(),
165  'uid_foreign' => 0,
166  'uid' => 0,
167  'crop' => '',
168  ];
169  if ($hasCrop) {
170  $cropVariantCollection = ‪CropVariantCollection::create('', $this->‪resolveCropVariantsConfiguration());
171  $cropVariantCollection = $cropVariantCollection->applyRatioRestrictionToSelectedCropArea($file);
172  $fileReferenceProperties['crop'] = (string)$cropVariantCollection;
173  }
174  $fileReference = GeneralUtility::makeInstance(ResourceFactory::class)
175  ->createFileReferenceObject($fileReferenceProperties);
176  // invoke processing of social image
177  $reflectionSubject = new \ReflectionObject($this->subject);
178  $reflectionMethod = $reflectionSubject->getMethod('processSocialImage');
180  $processedSocialImage = $reflectionMethod->invoke($this->subject, $fileReference);
181 
182  self::assertSame($expectedDimension, [
183  'width' => (int)$processedSocialImage->getProperty('width'),
184  'height' => (int)$processedSocialImage->getProperty('height'),
185  ]);
186  self::assertInstanceOf($expectedClassName, $processedSocialImage);
187  }
188 
189  private function ‪createImagePngContent(int $width, int $height): string
190  {
191  $filePath = $this->instancePath . '/typo3temp/var/transient/seo-test-image.png';
192  $gdImage = imagecreatetruecolor($width, $height);
193  imagepng($gdImage, $filePath);
194  $content = file_get_contents($filePath);
195  unlink($this->instancePath . '/typo3temp/var/transient/seo-test-image.png');
196  return $content;
197  }
198 
199  private function ‪determineGraphicMagickBinaryPath(): string
200  {
201  $values = GeneralUtility::makeInstance(GraphicsMagickPreset::class)->getConfigurationValues();
202  return $values['GFX/processor_path'] ?? ‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path'];
203  }
204 
208  private function ‪resolveCropVariantsConfiguration(): array
209  {
210  $config = ‪$GLOBALS['TCA']['pages']['columns']['og_image']['config']['overrideChildTca']['columns']['crop']['config'];
211  $cropVariants = [];
212  foreach ($config['cropVariants'] as $id => $cropVariant) {
213  // Filter allowed aspect ratios
214  $cropVariant['allowedAspectRatios'] = array_filter(
215  $cropVariant['allowedAspectRatios'] ?? [],
216  static fn($aspectRatio) => empty($aspectRatio['disabled'])
217  );
218  // Ignore disabled crop variants
219  if (!empty($cropVariant['disabled'])) {
220  continue;
221  }
222  // Enforce a crop area (default is full image)
223  if (empty($cropVariant['cropArea'])) {
224  $cropVariant['cropArea'] = ‪Area::createEmpty()->‪asArray();
225  }
226  $cropVariants[$id] = $cropVariant;
227  }
228  return $cropVariants;
229  }
230 }
‪TYPO3\CMS\Seo\Tests\Functional\MetaTag\MetaTagGeneratorTest
Definition: MetaTagGeneratorTest.php:36
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection\create
‪static create(string $jsonString, array $tcaConfig=[])
Definition: CropVariantCollection.php:37
‪TYPO3\CMS\Core\Resource\FileInterface
Definition: FileInterface.php:26
‪TYPO3\CMS\Seo\Tests\Functional\MetaTag\MetaTagGeneratorTest\socialImageIsProcessed
‪socialImageIsProcessed(bool $hasCrop, array $imageDimension, array $expectedDimension, string $expectedClassName)
Definition: MetaTagGeneratorTest.php:149
‪TYPO3\CMS\Core\Imaging\ImageManipulation\Area
Definition: Area.php:23
‪TYPO3\CMS\Seo\Tests\Functional\MetaTag\MetaTagGeneratorTest\$subject
‪MetaTagGenerator $subject
Definition: MetaTagGeneratorTest.php:37
‪TYPO3\CMS\Seo\Tests\Functional\MetaTag
Definition: MetaTagGeneratorTest.php:18
‪TYPO3\CMS\Seo\MetaTag\MetaTagGenerator
Definition: MetaTagGenerator.php:36
‪TYPO3\CMS\Core\Imaging\ImageManipulation\Area\asArray
‪asArray()
Definition: Area.php:109
‪TYPO3\CMS\Seo\Tests\Functional\MetaTag\MetaTagGeneratorTest\setUp
‪setUp()
Definition: MetaTagGeneratorTest.php:41
‪TYPO3\CMS\Seo\Tests\Functional\MetaTag\MetaTagGeneratorTest\$defaultStorage
‪ResourceStorage $defaultStorage
Definition: MetaTagGeneratorTest.php:38
‪TYPO3\CMS\Install\Configuration\Image\GraphicsMagickPreset
Definition: GraphicsMagickPreset.php:26
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:42
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:38
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:26
‪TYPO3\CMS\Seo\Tests\Functional\MetaTag\MetaTagGeneratorTest\socialImageIsProcessedDataProvider
‪static socialImageIsProcessedDataProvider()
Definition: MetaTagGeneratorTest.php:50
‪TYPO3\CMS\Seo\Tests\Functional\MetaTag\MetaTagGeneratorTest\resolveCropVariantsConfiguration
‪resolveCropVariantsConfiguration()
Definition: MetaTagGeneratorTest.php:208
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:47
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:129
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Seo\Tests\Functional\MetaTag\MetaTagGeneratorTest\$coreExtensionsToLoad
‪array $coreExtensionsToLoad
Definition: MetaTagGeneratorTest.php:39
‪TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection
Definition: CropVariantCollection.php:23
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Seo\Tests\Functional\MetaTag\MetaTagGeneratorTest\createImagePngContent
‪createImagePngContent(int $width, int $height)
Definition: MetaTagGeneratorTest.php:189
‪TYPO3\CMS\Seo\Tests\Functional\MetaTag\MetaTagGeneratorTest\determineGraphicMagickBinaryPath
‪determineGraphicMagickBinaryPath()
Definition: MetaTagGeneratorTest.php:199
‪TYPO3\CMS\Core\Imaging\ImageManipulation\Area\createEmpty
‪static Area createEmpty()
Definition: Area.php:81