diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2cfa1d4..6c47855 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.0 + php-version: 8.2 extensions: exif, dom, fileinfo, filter, gd, hash, intl, json, mbstring, pcre, pdo, zlib tools: prestissimo, flex coverage: pcov @@ -47,7 +47,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.1 + php-version: 8.2 extensions: exif, dom, fileinfo, filter, gd, hash, intl, json, mbstring, pcre, pdo, zlib tools: prestissimo, flex coverage: none @@ -73,7 +73,7 @@ jobs: strategy: fail-fast: false matrix: - php: [7.2, 7.3, 7.4, 8.0, 8.1, 8.2] + php: [8.1, 8.2] steps: - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -121,7 +121,7 @@ jobs: strategy: fail-fast: false matrix: - php: [7.2, 7.4, 8.0] + php: [8.1] steps: - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -136,7 +136,6 @@ jobs: - name: Install the dependencies run: | - if [ "${{ matrix.php }}" = "8" ]; then composer require contao/imagine-svg:1.0.2 --no-update; fi composer update --prefer-lowest --prefer-stable --no-interaction --no-suggest --no-progress - name: Run the unit tests @@ -149,7 +148,7 @@ jobs: strategy: fail-fast: false matrix: - php: [7.2, 7.3, 7.4, 8.0, 8.1, 8.2] + php: [8.1, 8.2] steps: - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index c6e3536..a6950d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.0] () + + * Remove method signatures `getImg(null, …)` and `getSources(null, …)` + from `PictureInterface` and + add new methods `getRawImg()` and `getRawSources()` as a replacement. + ## [Unreleased] * Add EXIF, IPTC, XMP metadata handling for JPEG, PNG, WEBP, GIF, HEIC, JXL, AVIF. [#93], [#95], [#96] diff --git a/composer.json b/composer.json index 6cd3efa..d343e37 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "php": "^7.2 || ^8.0", + "php": "^8.1", "ext-dom": "*", "ext-gd": "*", "ext-hash": "*", @@ -18,20 +18,17 @@ "ext-zlib": "*", "imagine/imagine": "^1.3", "symfony/deprecation-contracts": "^2.1 || ^3.0", - "symfony/filesystem": "^5.4 || ^6.0", - "symfony/polyfill-php73": "^1.27", - "symfony/polyfill-php80": "^1.27" + "symfony/filesystem": "^5.4 || ^6.0" }, "conflict": { "contao/imagine-svg": "<1.0 || >=2.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.4", + "bamarni/composer-bin-plugin": "^1.8", "contao/imagine-svg": "^1.0", - "contao/test-case": "^4.5", - "phpunit/phpunit": "^8.5 || ^9.5", - "symfony/phpunit-bridge": "^5.4", - "symfony/polyfill-php81": "^1.27" + "contao/test-case": "^4.13", + "phpunit/phpunit": "^9.6.8", + "symfony/phpunit-bridge": "^5.4" }, "suggest": { "ext-exif": "To support EXIF auto-rotation and preserve copyright metadata" diff --git a/phpstan.neon.dist b/phpstan.neon.dist index c2c9ab7..b45960e 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -10,24 +10,18 @@ rules: - TheCodingMachine\PHPStan\Rules\Exceptions\ThrowMustBundlePreviousExceptionRule parameters: - level: 5 + level: 6 + treatPhpDocTypesAsCertain: false paths: - %currentWorkingDirectory%/src - %currentWorkingDirectory%/tests ignoreErrors: - - - # Ignore the forward compatible phpDoc comment - message: '#PHPDoc tag @param references unknown parameter:#' - path: %currentWorkingDirectory%/src/Resizer.php - - - # Ignore the forward compatible phpDoc comment - message: '#PHPDoc tag @param references unknown parameter:#' - path: %currentWorkingDirectory%/src/DeferredResizer.php - message: '#class Imagine\\Image\\(Box|Point) constructor expects int, float given#' path: %currentWorkingDirectory%/tests/ResizeCoordinatesTest.php - - message: '#ResizeCoordinates::isEqualTo\(\) expects .*, stdClass given#' - path: %currentWorkingDirectory%/tests/ResizeCoordinatesTest.php + message: '#Access to an undefined property XMLReader::#' + - + message: '#no value type specified#' diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b00c11d..bc246d5 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -22,8 +22,4 @@ ./src - - - - diff --git a/src/DeferredImageStorageFilesystem.php b/src/DeferredImageStorageFilesystem.php index 40846d1..524b086 100644 --- a/src/DeferredImageStorageFilesystem.php +++ b/src/DeferredImageStorageFilesystem.php @@ -25,65 +25,37 @@ class DeferredImageStorageFilesystem implements DeferredImageStorageInterface private const PATH_PREFIX = 'deferred'; private const PATH_SUFFIX = '.json'; - /** - * @var string - */ - private $cacheDir; - - /** - * @var Filesystem - */ - private $filesystem; - - /** - * @var array - */ - private $locks = []; + private readonly string $cacheDir; - public function __construct(string $cacheDir, Filesystem $filesystem = null) - { - if (null === $filesystem) { - $filesystem = new Filesystem(); - } + private array $locks = []; + public function __construct( + string $cacheDir, + private readonly Filesystem $filesystem = new Filesystem(), + ) { $this->cacheDir = Path::join($cacheDir, self::PATH_PREFIX); - $this->filesystem = $filesystem; } - /** - * {@inheritdoc} - */ public function set(string $path, array $value): void { - $json = json_encode($value); - - if (JSON_ERROR_NONE !== json_last_error()) { - throw new JsonException(json_last_error_msg()); + try { + $this->filesystem->dumpFile($this->getConfigPath($path), json_encode($value, JSON_THROW_ON_ERROR)); + } catch (\JsonException $e) { + throw new JsonException($e->getMessage(), $e->getCode(), $e); } - - $this->filesystem->dumpFile($this->getConfigPath($path), $json); } - /** - * {@inheritdoc} - */ public function get(string $path): array { return $this->decode(file_get_contents($this->getConfigPath($path))); } - /** - * {@inheritdoc} - */ public function has(string $path): bool { return $this->filesystem->exists($this->getConfigPath($path)); } - /** - * {@inheritdoc} - */ - public function getLocked(string $path, bool $blocking = true): ?array + public function getLocked(string $path, bool $blocking = true): array|null { if (isset($this->locks[$path])) { if ($blocking) { @@ -114,9 +86,6 @@ public function getLocked(string $path, bool $blocking = true): ?array return $this->decode(stream_get_contents($handle)); } - /** - * {@inheritdoc} - */ public function releaseLock(string $path): void { if (!isset($this->locks[$path])) { @@ -129,9 +98,6 @@ public function releaseLock(string $path): void unset($this->locks[$path]); } - /** - * {@inheritdoc} - */ public function delete(string $path): void { try { @@ -150,9 +116,6 @@ public function delete(string $path): void } } - /** - * {@inheritdoc} - */ public function listPaths(): iterable { if (!$this->filesystem->exists($this->cacheDir)) { @@ -164,28 +127,20 @@ public function listPaths(): iterable $iterator = new \CallbackFilterIterator( $iterator, - static function ($path) { - return self::PATH_SUFFIX === substr((string) $path, -\strlen(self::PATH_SUFFIX)); - } + static fn ($path) => str_ends_with((string) $path, self::PATH_SUFFIX) ); return new class($iterator, $this->cacheDir, self::PATH_SUFFIX) extends \IteratorIterator { - private $cacheDir; - private $suffix; - - public function __construct(\Traversable $iterator, string $cacheDir, string $suffix) + public function __construct(\Traversable $iterator, private readonly string $cacheDir, private readonly string $suffix) { parent::__construct($iterator); - - $this->cacheDir = $cacheDir; - $this->suffix = $suffix; } public function current(): string { $path = Path::makeRelative((string) parent::current(), $this->cacheDir); - return substr($path, 0, -\strlen($this->suffix)); + return substr($path, 0, -\strlen((string) $this->suffix)); } }; } @@ -204,14 +159,14 @@ private function getConfigPath(string $path): string */ private function decode(string $contents): array { - $content = json_decode($contents, true); - - if (JSON_ERROR_NONE !== json_last_error()) { - throw new JsonException(json_last_error_msg()); + try { + $content = json_decode($contents, true, 512, JSON_THROW_ON_ERROR); + } catch (\JsonException $e) { + throw new JsonException($e->getMessage(), $e->getCode(), $e); } if (!\is_array($content)) { - throw new InvalidArgumentException(sprintf('Invalid JSON data: expected array, got "%s"', \gettype($content))); + throw new InvalidArgumentException(sprintf('Invalid JSON data: expected array, got "%s"', get_debug_type($content))); } return $content; diff --git a/src/DeferredImageStorageInterface.php b/src/DeferredImageStorageInterface.php index 9ec74cb..16c604f 100644 --- a/src/DeferredImageStorageInterface.php +++ b/src/DeferredImageStorageInterface.php @@ -18,7 +18,7 @@ public function set(string $path, array $value): void; public function get(string $path): array; - public function getLocked(string $path, bool $blocking = true): ?array; + public function getLocked(string $path, bool $blocking = true): array|null; public function releaseLock(string $path): void; diff --git a/src/DeferredResizer.php b/src/DeferredResizer.php index 584a2fd..3619b4c 100644 --- a/src/DeferredResizer.php +++ b/src/DeferredResizer.php @@ -21,64 +21,30 @@ use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Path; -/** - * @method __construct(string $cacheDir, string $secret, ResizeCalculator $calculator = null, Filesystem $filesystem = null, DeferredImageStorageInterface $storage = null, MetadataReaderWriter $metadataReaderWriter = null) - */ class DeferredResizer extends Resizer implements DeferredResizerInterface { + private readonly Filesystem $filesystem; + + private readonly string $cacheDir; + /** - * @var DeferredImageStorageInterface - * * @internal */ - private $storage; + private readonly DeferredImageStorageInterface $storage; /** - * @param string $cacheDir - * @param string $secret - * @param ResizeCalculator|null $calculator - * @param Filesystem|null $filesystem - * @param DeferredImageStorageInterface|null $storage - * @param MetadataReaderWriter|null $metadataReaderWriter + * @param non-empty-string $secret */ - public function __construct(string $cacheDir/*, string $secret, ResizeCalculator $calculator = null, Filesystem $filesystem = null, DeferredImageStorageInterface $storage = null, MetadataReaderWriter $metadataReaderWriter = null*/) + public function __construct(string $cacheDir, string $secret, ResizeCalculator $calculator = null, Filesystem $filesystem = null, DeferredImageStorageInterface $storage = null, MetadataReaderWriter $metadataReaderWriter = null) { - if (\func_num_args() > 1 && \is_string(func_get_arg(1))) { - $secret = func_get_arg(1); - $calculator = \func_num_args() > 2 ? func_get_arg(2) : null; - $filesystem = \func_num_args() > 3 ? func_get_arg(3) : null; - $storage = \func_num_args() > 4 ? func_get_arg(4) : null; - $metadataReaderWriter = \func_num_args() > 5 ? func_get_arg(5) : null; - } else { - trigger_deprecation('contao/image', '1.2', 'Not passing a secret to "%s()" has been deprecated and will no longer work in version 2.0.', __METHOD__); - $secret = null; - $calculator = \func_num_args() > 1 ? func_get_arg(1) : null; - $filesystem = \func_num_args() > 2 ? func_get_arg(2) : null; - $storage = \func_num_args() > 3 ? func_get_arg(3) : null; - $metadataReaderWriter = \func_num_args() > 4 ? func_get_arg(4) : null; - } - - if (null === $storage) { - $storage = new DeferredImageStorageFilesystem($cacheDir); - } - - if (!$storage instanceof DeferredImageStorageInterface) { - throw new \TypeError(sprintf('%s(): Argument #5 ($storage) must be of type DeferredImageStorageInterface|null, %s given', __METHOD__, get_debug_type($storage))); - } - - if (null === $secret) { - parent::__construct($cacheDir, $calculator, $filesystem, $metadataReaderWriter); - } else { - parent::__construct($cacheDir, $secret, $calculator, $filesystem, $metadataReaderWriter); - } + parent::__construct($cacheDir, $secret, $calculator, $filesystem, $metadataReaderWriter); - $this->storage = $storage; + $this->filesystem = $filesystem ?? new Filesystem(); + $this->cacheDir = $cacheDir; + $this->storage = $storage ?? new DeferredImageStorageFilesystem($cacheDir); } - /** - * {@inheritdoc} - */ - public function getDeferredImage(string $targetPath, ImagineInterface $imagine): ?DeferredImageInterface + public function getDeferredImage(string $targetPath, ImagineInterface $imagine): DeferredImageInterface|null { if (Path::isAbsolute($targetPath)) { if (!Path::isBasePath($this->cacheDir, $targetPath)) { @@ -106,10 +72,7 @@ public function getDeferredImage(string $targetPath, ImagineInterface $imagine): ); } - /** - * {@inheritdoc} - */ - public function resizeDeferredImage(DeferredImageInterface $image, bool $blocking = true): ?ImageInterface + public function resizeDeferredImage(DeferredImageInterface $image, bool $blocking = true): ImageInterface|null { if (!Path::isBasePath($this->cacheDir, $image->getPath())) { throw new InvalidArgumentException(sprintf('Path "%s" is not inside cache directory "%s"', $image->getPath(), $this->cacheDir)); @@ -148,9 +111,6 @@ public function resizeDeferredImage(DeferredImageInterface $image, bool $blockin return $resizedImage; } - /** - * {@inheritdoc} - */ protected function processResize(ImageInterface $image, ResizeConfiguration $config, ResizeOptions $options): ImageInterface { // Resize the source image if it is deferred @@ -161,9 +121,6 @@ protected function processResize(ImageInterface $image, ResizeConfiguration $con return parent::processResize($image, $config, $options); } - /** - * {@inheritdoc} - */ protected function executeResize(ImageInterface $image, ResizeCoordinates $coordinates, string $path, ResizeOptions $options): ImageInterface { if (null !== $options->getTargetPath() || $options->getBypassCache()) { diff --git a/src/DeferredResizerInterface.php b/src/DeferredResizerInterface.php index bf1e282..4fec423 100644 --- a/src/DeferredResizerInterface.php +++ b/src/DeferredResizerInterface.php @@ -19,10 +19,7 @@ interface DeferredResizerInterface extends ResizerInterface /** * Gets a deferred image object for a not yet resized image. */ - public function getDeferredImage(string $targetPath, ImagineInterface $imagine): ?DeferredImageInterface; + public function getDeferredImage(string $targetPath, ImagineInterface $imagine): DeferredImageInterface|null; - /** - * Resizes a deferred image. - */ - public function resizeDeferredImage(DeferredImageInterface $image, bool $blocking = true): ?ImageInterface; + public function resizeDeferredImage(DeferredImageInterface $image, bool $blocking = true): ImageInterface|null; } diff --git a/src/Image.php b/src/Image.php index 4927ca0..f08b36c 100644 --- a/src/Image.php +++ b/src/Image.php @@ -26,30 +26,21 @@ class Image implements ImageInterface { /** - * @var string - * * @internal */ - protected $path; + protected string $path; /** - * @var ImageDimensions - * * @internal */ - protected $dimensions; + protected ImageDimensions|null $dimensions = null; /** - * @var ImagineInterface - * * @internal */ - protected $imagine; + protected ImagineInterface $imagine; - /** - * @var ImportantPart|null - */ - private $importantPart; + private ImportantPart|null $importantPart = null; public function __construct(string $path, ImagineInterface $imagine, Filesystem $filesystem = null) { @@ -69,25 +60,16 @@ public function __construct(string $path, ImagineInterface $imagine, Filesystem $this->imagine = $imagine; } - /** - * {@inheritdoc} - */ public function getImagine(): ImagineInterface { return $this->imagine; } - /** - * {@inheritdoc} - */ public function getPath(): string { return $this->path; } - /** - * {@inheritdoc} - */ public function getUrl(string $rootDir, string $prefix = ''): string { if (!Path::isBasePath($rootDir, $this->path)) { @@ -100,9 +82,6 @@ public function getUrl(string $rootDir, string $prefix = ''): string return $prefix.$url; } - /** - * {@inheritdoc} - */ public function getDimensions(): ImageDimensions { if (null === $this->dimensions) { @@ -141,18 +120,12 @@ public function getDimensions(): ImageDimensions return $this->dimensions; } - /** - * {@inheritdoc} - */ public function getImportantPart(): ImportantPart { return $this->importantPart ?? new ImportantPart(); } - /** - * {@inheritdoc} - */ - public function setImportantPart(ImportantPart $importantPart = null): ImageInterface + public function setImportantPart(ImportantPart $importantPart = null): static { $this->importantPart = $importantPart; @@ -162,7 +135,7 @@ public function setImportantPart(ImportantPart $importantPart = null): ImageInte /** * Corrects invalid EXIF orientation values. */ - private function fixOrientation($orientation): int + private function fixOrientation(int|string|null $orientation): int { $orientation = (int) $orientation; @@ -202,7 +175,7 @@ private function fixSizeOrientation(BoxInterface $size, int $orientation): BoxIn * This is faster than reading and parsing the whole SVG file just to get * the size of it, especially for large files. */ - private function getSvgSize(): ?BoxInterface + private function getSvgSize(): BoxInterface|null { if (!class_exists(SvgImage::class) || !class_exists(\XMLReader::class) || !class_exists(\DOMDocument::class)) { return null; @@ -260,7 +233,7 @@ private function getSvgSize(): ?BoxInterface /** * Extracts the SVG image size from the given XMLReader object. */ - private function getSvgSizeFromReader(\XMLReader $reader): ?BoxInterface + private function getSvgSizeFromReader(\XMLReader $reader): BoxInterface|null { // Move the pointer to the first element in the document while ($reader->read() && \XMLReader::ELEMENT !== $reader->nodeType); diff --git a/src/ImageDimensions.php b/src/ImageDimensions.php index ae2a9a0..f083b60 100644 --- a/src/ImageDimensions.php +++ b/src/ImageDimensions.php @@ -23,53 +23,31 @@ class ImageDimensions * * @see */ - public const ORIENTATION_NORMAL = 1; - public const ORIENTATION_90 = 6; - public const ORIENTATION_180 = 3; - public const ORIENTATION_270 = 8; - public const ORIENTATION_MIRROR = 2; - public const ORIENTATION_MIRROR_90 = 7; - public const ORIENTATION_MIRROR_180 = 4; - public const ORIENTATION_MIRROR_270 = 5; - - /** - * @var BoxInterface - */ - private $size; - - /** - * @var int - */ - private $orientation; - - /** - * @var bool - */ - private $relative; - - /** - * @var bool - */ - private $undefined; - - public function __construct(BoxInterface $size, bool $relative = null, bool $undefined = null, int $orientation = self::ORIENTATION_NORMAL) - { + final public const ORIENTATION_NORMAL = 1; + final public const ORIENTATION_90 = 6; + final public const ORIENTATION_180 = 3; + final public const ORIENTATION_270 = 8; + final public const ORIENTATION_MIRROR = 2; + final public const ORIENTATION_MIRROR_90 = 7; + final public const ORIENTATION_MIRROR_180 = 4; + final public const ORIENTATION_MIRROR_270 = 5; + + private readonly bool $relative; + + private readonly bool $undefined; + + public function __construct( + private readonly BoxInterface $size, + bool $relative = null, + bool $undefined = null, + private readonly int $orientation = self::ORIENTATION_NORMAL, + ) { if ($orientation < 1 || $orientation > 8) { throw new InvalidArgumentException('Orientation must be one of the ImageDimensions::ORIENTATION_* constants'); } - if (null === $relative) { - $relative = $size instanceof SvgBox && SvgBox::TYPE_ASPECT_RATIO === $size->getType(); - } - - if (null === $undefined) { - $undefined = $size instanceof SvgBox && SvgBox::TYPE_NONE === $size->getType(); - } - - $this->size = $size; - $this->orientation = $orientation; - $this->relative = $relative; - $this->undefined = $undefined; + $this->relative = $relative ?? $size instanceof SvgBox && SvgBox::TYPE_ASPECT_RATIO === $size->getType(); + $this->undefined = $undefined ?? $size instanceof SvgBox && SvgBox::TYPE_NONE === $size->getType(); } public function getSize(): BoxInterface diff --git a/src/ImageInterface.php b/src/ImageInterface.php index 0fdd2ba..ccc431c 100644 --- a/src/ImageInterface.php +++ b/src/ImageInterface.php @@ -16,14 +16,8 @@ interface ImageInterface { - /** - * Returns the imagine instance. - */ public function getImagine(): ImagineInterface; - /** - * Returns the path. - */ public function getPath(): string; /** @@ -32,18 +26,9 @@ public function getPath(): string; */ public function getUrl(string $rootDir, string $prefix = ''): string; - /** - * Returns the dimensions. - */ public function getDimensions(): ImageDimensions; - /** - * Returns the important part. - */ public function getImportantPart(): ImportantPart; - /** - * Sets the important part. - */ - public function setImportantPart(ImportantPart $importantPart = null): self; + public function setImportantPart(ImportantPart $importantPart = null): static; } diff --git a/src/ImportantPart.php b/src/ImportantPart.php index ef6a5d0..790eb70 100644 --- a/src/ImportantPart.php +++ b/src/ImportantPart.php @@ -18,28 +18,16 @@ class ImportantPart { private const ROUNDING_ERROR_THRESHOLD = 1 / 100000; - /** - * @var float - */ - private $x; + private readonly float $width; - /** - * @var float - */ - private $y; + private readonly float $height; - /** - * @var float - */ - private $width; - - /** - * @var float - */ - private $height; - - public function __construct(float $x = 0, float $y = 0, float $width = 1, float $height = 1) - { + public function __construct( + private readonly float $x = 0, + private readonly float $y = 0, + float $width = 1, + float $height = 1, + ) { if ($x < 0 || $x > 1 || $y < 0 || $y > 1 || $width < 0 || $width > 1 || $height < 0 || $height > 1) { throw new CoordinatesOutOfBoundsException('X, Y, width and height must be a float between 0 and 1'); } @@ -60,8 +48,6 @@ public function __construct(float $x = 0, float $y = 0, float $width = 1, float $height = 1 - $y; } - $this->x = $x; - $this->y = $y; $this->width = $width; $this->height = $height; } diff --git a/src/Metadata/AbstractContainer.php b/src/Metadata/AbstractContainer.php index 6313148..79c46c0 100644 --- a/src/Metadata/AbstractContainer.php +++ b/src/Metadata/AbstractContainer.php @@ -35,7 +35,7 @@ protected function parseFormat(string $format, string $binaryChunk): array { try { return $this->metadataReaderWriter->parseFormat($format, $binaryChunk); - } catch (InvalidImageMetadataException $exception) { + } catch (InvalidImageMetadataException) { return []; } } diff --git a/src/Metadata/AbstractFormat.php b/src/Metadata/AbstractFormat.php index 1ad66c6..8755efb 100644 --- a/src/Metadata/AbstractFormat.php +++ b/src/Metadata/AbstractFormat.php @@ -19,9 +19,7 @@ public function toReadable(array $data): array $data = $this->prefixIntKeys($data, static::NAME.'_'); return array_map( - function ($value) { - return $this->ensureStringList($value); - }, + fn ($value) => $this->ensureStringList($value), $data ); } @@ -88,7 +86,7 @@ protected function prefixIntKeys(array $data, string $prefix): array /** * @return list */ - protected function ensureStringList($value): array + protected function ensureStringList(mixed $value): array { $value = array_map( function ($value) { @@ -104,9 +102,7 @@ function ($value) { return array_values( array_filter( $value, - static function ($value) { - return '' !== $value; - } + static fn ($value) => '' !== $value ) ); } diff --git a/src/Metadata/ExifFormat.php b/src/Metadata/ExifFormat.php index f990e25..e3c5e97 100644 --- a/src/Metadata/ExifFormat.php +++ b/src/Metadata/ExifFormat.php @@ -17,8 +17,8 @@ class ExifFormat extends AbstractFormat { - public const NAME = 'exif'; - public const DEFAULT_PRESERVE_KEYS = [ + final public const NAME = 'exif'; + final public const DEFAULT_PRESERVE_KEYS = [ 'IFD0' => ['Copyright', 'Artist'], ]; diff --git a/src/Metadata/GifFormat.php b/src/Metadata/GifFormat.php index a0ac101..4e4f47a 100644 --- a/src/Metadata/GifFormat.php +++ b/src/Metadata/GifFormat.php @@ -14,8 +14,8 @@ class GifFormat extends AbstractFormat { - public const NAME = 'gif'; - public const DEFAULT_PRESERVE_KEYS = ['Comment']; + final public const NAME = 'gif'; + final public const DEFAULT_PRESERVE_KEYS = ['Comment']; public function serialize(ImageMetadata $metadata, array $preserveKeys): string { @@ -68,12 +68,12 @@ private function buildChunks(array $metadata): string $gifChunks .= "\x21\xFE"; - while (\strlen($item) > 255) { - $gifChunks .= "\xFF".substr($item, 0, 255); - $item = substr($item, 255); + while (\strlen((string) $item) > 255) { + $gifChunks .= "\xFF".substr((string) $item, 0, 255); + $item = substr((string) $item, 255); } - $gifChunks .= \chr(\strlen($item)).$item."\x00"; + $gifChunks .= \chr(\strlen((string) $item)).$item."\x00"; } } diff --git a/src/Metadata/ImageMetadata.php b/src/Metadata/ImageMetadata.php index fea2bd1..d798be8 100644 --- a/src/Metadata/ImageMetadata.php +++ b/src/Metadata/ImageMetadata.php @@ -14,17 +14,11 @@ final class ImageMetadata { - /** - * @var array - */ - private $byFormat; - /** * @param array $byFormat */ - public function __construct(array $byFormat) + public function __construct(private readonly array $byFormat) { - $this->byFormat = $byFormat; } public function getFormat(string $format): array diff --git a/src/Metadata/IptcFormat.php b/src/Metadata/IptcFormat.php index d67e219..ec38fed 100644 --- a/src/Metadata/IptcFormat.php +++ b/src/Metadata/IptcFormat.php @@ -16,8 +16,8 @@ class IptcFormat extends AbstractFormat { - public const NAME = 'iptc'; - public const DEFAULT_PRESERVE_KEYS = ['2#116', '2#080', '2#115', '2#110']; + final public const NAME = 'iptc'; + final public const DEFAULT_PRESERVE_KEYS = ['2#116', '2#080', '2#115', '2#110']; public function serialize(ImageMetadata $metadata, array $preserveKeys): string { @@ -64,7 +64,7 @@ public function serialize(ImageMetadata $metadata, array $preserveKeys): string $filtered = []; foreach ($preserveKeys as $property) { - if (str_starts_with($property, '2#') && ($key = (int) substr($property, 2)) && isset($iptc[$key])) { + if (str_starts_with((string) $property, '2#') && ($key = (int) substr((string) $property, 2)) && isset($iptc[$key])) { $filtered[$key] = $iptc[$key]; } } @@ -88,79 +88,77 @@ public function toReadable(array $data): array unset($data['1#090'], $data['2#000']); $keys = array_map( - static function ($key) { - return [ - '2#003' => 'ObjectTypeReference', - '2#004' => 'ObjectAttributeReference', - '2#005' => 'ObjectName', - '2#007' => 'EditStatus', - '2#008' => 'EditorialUpdate', - '2#010' => 'Urgency', - '2#012' => 'SubjectReference', - '2#015' => 'Category', - '2#020' => 'SupplementalCategories', - '2#022' => 'FixtureIdentifier', - '2#025' => 'Keywords', - '2#026' => 'ContentLocationCode', - '2#027' => 'ContentLocationName', - '2#030' => 'ReleaseDate', - '2#035' => 'ReleaseTime', - '2#037' => 'ExpirationDate', - '2#038' => 'ExpirationTime', - '2#040' => 'SpecialInstructions', - '2#042' => 'ActionAdvised', - '2#045' => 'ReferenceService', - '2#047' => 'ReferenceDate', - '2#050' => 'ReferenceNumber', - '2#055' => 'DateCreated', - '2#060' => 'TimeCreated', - '2#062' => 'DigitalCreationDate', - '2#063' => 'DigitalCreationTime', - '2#065' => 'OriginatingProgram', - '2#070' => 'ProgramVersion', - '2#075' => 'ObjectCycle', - '2#080' => 'By-line', - '2#085' => 'By-lineTitle', - '2#090' => 'City', - '2#092' => 'Sub-location', - '2#095' => 'Province-State', - '2#100' => 'Country-PrimaryLocationCode', - '2#101' => 'Country-PrimaryLocationName', - '2#103' => 'OriginalTransmissionReference', - '2#105' => 'Headline', - '2#110' => 'Credit', - '2#115' => 'Source', - '2#116' => 'CopyrightNotice', - '2#118' => 'Contact', - '2#120' => 'Caption-Abstract', - '2#121' => 'LocalCaption', - '2#122' => 'Writer-Editor', - '2#125' => 'RasterizedCaption', - '2#130' => 'ImageType', - '2#131' => 'ImageOrientation', - '2#135' => 'LanguageIdentifier', - '2#150' => 'AudioType', - '2#151' => 'AudioSamplingRate', - '2#152' => 'AudioSamplingResolution', - '2#153' => 'AudioDuration', - '2#154' => 'AudioOutcue', - '2#184' => 'JobID', - '2#185' => 'MasterDocumentID', - '2#186' => 'ShortDocumentID', - '2#187' => 'UniqueDocumentID', - '2#188' => 'OwnerID', - '2#200' => 'ObjectPreviewFileFormat', - '2#201' => 'ObjectPreviewFileVersion', - '2#202' => 'ObjectPreviewData', - '2#221' => 'Prefs', - '2#225' => 'ClassifyState', - '2#228' => 'SimilarityIndex', - '2#230' => 'DocumentNotes', - '2#231' => 'DocumentHistory', - '2#232' => 'ExifCameraInfo', - '2#255' => 'CatalogSets', - ][$key] ?? $key; - }, + static fn ($key) => [ + '2#003' => 'ObjectTypeReference', + '2#004' => 'ObjectAttributeReference', + '2#005' => 'ObjectName', + '2#007' => 'EditStatus', + '2#008' => 'EditorialUpdate', + '2#010' => 'Urgency', + '2#012' => 'SubjectReference', + '2#015' => 'Category', + '2#020' => 'SupplementalCategories', + '2#022' => 'FixtureIdentifier', + '2#025' => 'Keywords', + '2#026' => 'ContentLocationCode', + '2#027' => 'ContentLocationName', + '2#030' => 'ReleaseDate', + '2#035' => 'ReleaseTime', + '2#037' => 'ExpirationDate', + '2#038' => 'ExpirationTime', + '2#040' => 'SpecialInstructions', + '2#042' => 'ActionAdvised', + '2#045' => 'ReferenceService', + '2#047' => 'ReferenceDate', + '2#050' => 'ReferenceNumber', + '2#055' => 'DateCreated', + '2#060' => 'TimeCreated', + '2#062' => 'DigitalCreationDate', + '2#063' => 'DigitalCreationTime', + '2#065' => 'OriginatingProgram', + '2#070' => 'ProgramVersion', + '2#075' => 'ObjectCycle', + '2#080' => 'By-line', + '2#085' => 'By-lineTitle', + '2#090' => 'City', + '2#092' => 'Sub-location', + '2#095' => 'Province-State', + '2#100' => 'Country-PrimaryLocationCode', + '2#101' => 'Country-PrimaryLocationName', + '2#103' => 'OriginalTransmissionReference', + '2#105' => 'Headline', + '2#110' => 'Credit', + '2#115' => 'Source', + '2#116' => 'CopyrightNotice', + '2#118' => 'Contact', + '2#120' => 'Caption-Abstract', + '2#121' => 'LocalCaption', + '2#122' => 'Writer-Editor', + '2#125' => 'RasterizedCaption', + '2#130' => 'ImageType', + '2#131' => 'ImageOrientation', + '2#135' => 'LanguageIdentifier', + '2#150' => 'AudioType', + '2#151' => 'AudioSamplingRate', + '2#152' => 'AudioSamplingResolution', + '2#153' => 'AudioDuration', + '2#154' => 'AudioOutcue', + '2#184' => 'JobID', + '2#185' => 'MasterDocumentID', + '2#186' => 'ShortDocumentID', + '2#187' => 'UniqueDocumentID', + '2#188' => 'OwnerID', + '2#200' => 'ObjectPreviewFileFormat', + '2#201' => 'ObjectPreviewFileVersion', + '2#202' => 'ObjectPreviewData', + '2#221' => 'Prefs', + '2#225' => 'ClassifyState', + '2#228' => 'SimilarityIndex', + '2#230' => 'DocumentNotes', + '2#231' => 'DocumentHistory', + '2#232' => 'ExifCameraInfo', + '2#255' => 'CatalogSets', + ][$key] ?? $key, array_keys($data) ); diff --git a/src/Metadata/IsobmffContainer.php b/src/Metadata/IsobmffContainer.php index af96e29..9df7e1e 100644 --- a/src/Metadata/IsobmffContainer.php +++ b/src/Metadata/IsobmffContainer.php @@ -16,20 +16,11 @@ abstract class IsobmffContainer extends AbstractContainer { - /** - * @var array - */ - private $metadata = []; + private array $metadata = []; - /** - * @var array - */ - private $items = []; + private array $items = []; - /** - * @var string - */ - private $idat = ''; + private string $idat = ''; public function apply($inputStream, $outputStream, ImageMetadata $metadata, array $preserveKeysByFormat): void { @@ -51,6 +42,9 @@ public function parse($stream): array } } + /** + * @param resource $stream + */ private function parseBoxList($stream, int $length, string $path = ''): void { while ($length > 0 && false !== $head = fread($stream, 8)) { @@ -196,7 +190,7 @@ private function parseIloc(string $content, int $version): void private function parseInfe(string $content, int $version): void { $itemID = unpack('n', substr($content, 0, 2))[1]; - //$itemProtectionIndex = unpack('n', substr($content, 2, 2))[1]; + // $itemProtectionIndex = unpack('n', substr($content, 2, 2))[1]; $content = substr($content, 4); $itemType = ''; @@ -217,6 +211,9 @@ private function parseInfe(string $content, int $version): void $this->items[$itemID]['encoding'] = $contentEncoding; } + /** + * @param resource $stream + */ private function parseItems($stream): void { foreach ($this->items as $item) { diff --git a/src/Metadata/JpegContainer.php b/src/Metadata/JpegContainer.php index 5b8156a..c47d8f2 100644 --- a/src/Metadata/JpegContainer.php +++ b/src/Metadata/JpegContainer.php @@ -111,9 +111,9 @@ public function parse($stream): array return array_merge(...$metadata); } - private function buildMarkerSegment($marker, $content): string + private function buildMarkerSegment(string $marker, string $content): string { - $size = pack('n', \strlen($content) + 2); + $size = pack('n', \strlen((string) $content) + 2); return "\xFF$marker$size$content"; } diff --git a/src/Metadata/MetadataReaderWriter.php b/src/Metadata/MetadataReaderWriter.php index 208baa7..576d335 100644 --- a/src/Metadata/MetadataReaderWriter.php +++ b/src/Metadata/MetadataReaderWriter.php @@ -24,12 +24,12 @@ class MetadataReaderWriter /** * @var list */ - private $containers; + private array $containers; /** * @var array */ - private $formats; + private array|null $formats = null; /** * @param iterable $formats @@ -47,8 +47,7 @@ public function __construct(iterable $formats = [], iterable $containers = []) $this->containers = \is_array($containers) ? array_values($containers) - : iterator_to_array($containers, false) - ; + : iterator_to_array($containers, false); $this->containers[] = new JpegContainer($this); $this->containers[] = new PngContainer($this); @@ -157,7 +156,7 @@ public function toReadable(ImageMetadata $metadata): array /** * @param resource $stream */ - private function findContainer($stream): ?ImageContainerInterface + private function findContainer($stream): ImageContainerInterface|null { foreach ($this->containers as $container) { $magicBytes = $container->getMagicBytes(); diff --git a/src/Metadata/PngFormat.php b/src/Metadata/PngFormat.php index 7960072..012d079 100644 --- a/src/Metadata/PngFormat.php +++ b/src/Metadata/PngFormat.php @@ -14,8 +14,8 @@ class PngFormat extends AbstractFormat { - public const NAME = 'png'; - public const DEFAULT_PRESERVE_KEYS = ['Copyright', 'Author', 'Source', 'Disclaimer']; + final public const NAME = 'png'; + final public const DEFAULT_PRESERVE_KEYS = ['Copyright', 'Author', 'Source', 'Disclaimer']; public function serialize(ImageMetadata $metadata, array $preserveKeys): string { diff --git a/src/Metadata/WebpContainer.php b/src/Metadata/WebpContainer.php index f8b7fe8..9144cef 100644 --- a/src/Metadata/WebpContainer.php +++ b/src/Metadata/WebpContainer.php @@ -94,9 +94,9 @@ public function parse($stream): array return $metadata; } - private function buildChunk($type, $content): string + private function buildChunk(string $type, string $content): string { - $size = \strlen($content); + $size = \strlen((string) $content); // RIFF chunks are padded to an even number if ($size % 2) { diff --git a/src/Metadata/XmpFormat.php b/src/Metadata/XmpFormat.php index dea9b62..d5de0e0 100644 --- a/src/Metadata/XmpFormat.php +++ b/src/Metadata/XmpFormat.php @@ -16,9 +16,9 @@ class XmpFormat extends AbstractFormat { - public const NAME = 'xmp'; + final public const NAME = 'xmp'; - public const DEFAULT_PRESERVE_KEYS = [ + final public const DEFAULT_PRESERVE_KEYS = [ 'http://purl.org/dc/elements/1.1/' => ['rights', 'creator'], 'http://ns.adobe.com/photoshop/1.0/' => ['Source', 'Credit'], ]; @@ -273,10 +273,7 @@ private function buildXmp(array $metadata): string return "$xmp"; } - /** - * @param string|\DOMElement $value - */ - private function parseValue(string $namespace, string $attr, $value): array + private function parseValue(string $namespace, string $attr, \DOMElement|string $value): array { $values = []; diff --git a/src/Picture.php b/src/Picture.php index 51902ab..8791a10 100644 --- a/src/Picture.php +++ b/src/Picture.php @@ -17,69 +17,50 @@ class Picture implements PictureInterface { /** - * @var array + * @param array{src:ImageInterface,srcset:list,width?:int,height?:int,sizes?:string} $img + * @param list,sizes?:string,media?:string,type?:string}> $sources */ - private $img; - - /** - * @var array - */ - private $sources; - - public function __construct(array $img, array $sources) - { + public function __construct( + private readonly array $img, + private readonly array $sources, + ) { $this->validateSrcAttribute($img); $this->validateSrcsetAttribute($img); foreach ($sources as $source) { $this->validateSrcsetAttribute($source); } - - $this->img = $img; - $this->sources = $sources; } - /** - * {@inheritdoc} - */ - public function getImg(string $rootDir = null, string $prefix = ''): array + public function getImg(string $rootDir, string $prefix = ''): array { - if (null === $rootDir) { - if ('' !== $prefix) { - throw new InvalidArgumentException(sprintf('Prefix must no be specified if rootDir is null, given "%s"', $prefix)); - } - - return $this->img; - } - return $this->buildUrls($this->img, $rootDir, $prefix); } - /** - * {@inheritdoc} - */ - public function getSources(string $rootDir = null, string $prefix = ''): array + public function getRawImg(): array { - if (null === $rootDir) { - if ('' !== $prefix) { - throw new InvalidArgumentException(sprintf('Prefix must no be specified if rootDir is null, given "%s"', $prefix)); - } - - return $this->sources; - } + return $this->img; + } + public function getSources(string $rootDir, string $prefix = ''): array + { return array_map( - function ($source) use ($rootDir, $prefix) { - return $this->buildUrls($source, $rootDir, $prefix); - }, + fn ($source) => $this->buildUrls($source, $rootDir, $prefix), $this->sources ); } + public function getRawSources(): array + { + return $this->sources; + } + /** * Converts image objects in an attributes array to URLs. * - * @param array{src:ImageInterface|null, srcset:list} $img + * @param array{src?:ImageInterface,srcset:list} $img + * + * @return array{src?:string,srcset:string} */ private function buildUrls(array $img, string $rootDir, string $prefix): array { diff --git a/src/PictureConfiguration.php b/src/PictureConfiguration.php index 4c63c09..fc3869a 100644 --- a/src/PictureConfiguration.php +++ b/src/PictureConfiguration.php @@ -16,22 +16,19 @@ class PictureConfiguration { - public const FORMAT_DEFAULT = '.default'; + final public const FORMAT_DEFAULT = '.default'; - /** - * @var PictureConfigurationItem - */ - private $size; + private PictureConfigurationItem|null $size = null; /** * @var array */ - private $sizeItems = []; + private array $sizeItems = []; /** * @var array */ - private $formats = []; + private array $formats = []; public function getSize(): PictureConfigurationItem { @@ -42,7 +39,7 @@ public function getSize(): PictureConfigurationItem return $this->size; } - public function setSize(PictureConfigurationItem $size): self + public function setSize(PictureConfigurationItem $size): static { $this->size = $size; @@ -60,7 +57,7 @@ public function getSizeItems(): array /** * @param array $sizeItems */ - public function setSizeItems(array $sizeItems): self + public function setSizeItems(array $sizeItems): static { foreach ($sizeItems as $sizeItem) { if (!$sizeItem instanceof PictureConfigurationItem) { @@ -84,7 +81,7 @@ public function getFormats(): array /** * @param array> $formats */ - public function setFormats(array $formats): self + public function setFormats(array $formats): static { if (!isset($formats[self::FORMAT_DEFAULT])) { $formats[self::FORMAT_DEFAULT] = [self::FORMAT_DEFAULT]; diff --git a/src/PictureConfigurationItem.php b/src/PictureConfigurationItem.php index 3ed64ed..9ab2c0c 100644 --- a/src/PictureConfigurationItem.php +++ b/src/PictureConfigurationItem.php @@ -14,36 +14,20 @@ class PictureConfigurationItem { - /** - * @var ResizeConfiguration - */ - private $resizeConfig; - - /** - * @var string - */ - private $sizes = ''; - - /** - * @var string - */ - private $densities = ''; - - /** - * @var string - */ - private $media = ''; + private ResizeConfiguration|null $resizeConfig = null; + + private string $sizes = ''; + + private string $densities = ''; + + private string $media = ''; public function getResizeConfig(): ResizeConfiguration { - if (null === $this->resizeConfig) { - $this->setResizeConfig(new ResizeConfiguration()); - } - - return $this->resizeConfig; + return $this->resizeConfig ??= new ResizeConfiguration(); } - public function setResizeConfig(ResizeConfiguration $resizeConfig): self + public function setResizeConfig(ResizeConfiguration $resizeConfig): static { $this->resizeConfig = $resizeConfig; @@ -55,7 +39,7 @@ public function getSizes(): string return $this->sizes; } - public function setSizes(string $sizes): self + public function setSizes(string $sizes): static { $this->sizes = $sizes; @@ -67,7 +51,7 @@ public function getDensities(): string return $this->densities; } - public function setDensities(string $densities): self + public function setDensities(string $densities): static { $this->densities = $densities; @@ -79,7 +63,7 @@ public function getMedia(): string return $this->media; } - public function setMedia(string $media): self + public function setMedia(string $media): static { $this->media = $media; diff --git a/src/PictureGenerator.php b/src/PictureGenerator.php index bfb0e11..93b55e3 100644 --- a/src/PictureGenerator.php +++ b/src/PictureGenerator.php @@ -16,34 +16,14 @@ class PictureGenerator implements PictureGeneratorInterface { - /** - * @var ResizerInterface - */ - private $resizer; - - /** - * @var ResizeCalculator - */ - private $calculator; - - /** - * @var ResizeOptions - */ - private $resizeOptions; - - public function __construct(ResizerInterface $resizer, ResizeCalculator $calculator = null) - { - if (null === $calculator) { - $calculator = new ResizeCalculator(); - } + private ResizeOptions $resizeOptions; - $this->resizer = $resizer; - $this->calculator = $calculator; + public function __construct( + private readonly ResizerInterface $resizer, + private readonly ResizeCalculator $calculator = new ResizeCalculator(), + ) { } - /** - * {@inheritdoc} - */ public function generate(ImageInterface $image, PictureConfiguration $config, ResizeOptions $options): PictureInterface { $this->resizeOptions = clone $options; @@ -93,7 +73,7 @@ private function generateSource(ImageInterface $image, PictureConfigurationItem $config->getDensities() && ($config->getResizeConfig()->getWidth() || $config->getResizeConfig()->getHeight()) ) { - if (!$sizesAttribute && false !== strpos($config->getDensities(), 'w')) { + if (!$sizesAttribute && str_contains($config->getDensities(), 'w')) { $sizesAttribute = '100vw'; } @@ -221,7 +201,7 @@ static function (array $item) use (&$usedPaths) { } )); - if (1 === \count($srcset) && isset($srcset[0][1]) && 'x' === substr($srcset[0][1], -1)) { + if (1 === \count($srcset) && isset($srcset[0][1]) && str_ends_with((string) $srcset[0][1], 'x')) { unset($srcset[0][1]); } @@ -236,9 +216,7 @@ private function getFormatsFromConfig(PictureConfiguration $config, string $sour $formatsConfig = $config->getFormats(); return array_map( - static function ($format) use ($config, $sourceFormat) { - return $format === $config::FORMAT_DEFAULT ? $sourceFormat : $format; - }, + static fn ($format) => $format === $config::FORMAT_DEFAULT ? $sourceFormat : $format, $formatsConfig[$sourceFormat] ?? $formatsConfig[$config::FORMAT_DEFAULT] ); } diff --git a/src/PictureInterface.php b/src/PictureInterface.php index 8a07964..ee92aea 100644 --- a/src/PictureInterface.php +++ b/src/PictureInterface.php @@ -16,11 +16,25 @@ interface PictureInterface { /** * Returns the image tag attributes. + * + * @return array{src:string,srcset:string,width?:int,height?:int,sizes?:string} */ - public function getImg(string $rootDir = null, string $prefix = ''): array; + public function getImg(string $rootDir, string $prefix = ''): array; + + /** + * @return array{src:ImageInterface,srcset:list,width?:int,height?:int,sizes?:string} + */ + public function getRawImg(): array; /** * Returns the source tags attributes. + * + * @return list + */ + public function getSources(string $rootDir, string $prefix = ''): array; + + /** + * @return list,sizes?:string,media?:string,type?:string}> */ - public function getSources(string $rootDir = null, string $prefix = ''): array; + public function getRawSources(): array; } diff --git a/src/ResizeCalculator.php b/src/ResizeCalculator.php index 1822360..c36644b 100644 --- a/src/ResizeCalculator.php +++ b/src/ResizeCalculator.php @@ -19,7 +19,7 @@ class ResizeCalculator { - public function calculate(ResizeConfiguration $config, ImageDimensions $dimensions, ImportantPart $importantPart = null): ResizeCoordinates + public function calculate(ResizeConfiguration $config, ImageDimensions $dimensions, ImportantPart $importantPart = new ImportantPart()): ResizeCoordinates { $zoom = max(0, min(1, $config->getZoomLevel() / 100)); $importantPartArray = $this->importantPartAsArray($dimensions, $importantPart); @@ -28,18 +28,11 @@ public function calculate(ResizeConfiguration $config, ImageDimensions $dimensio if ($config->getWidth() && $config->getHeight()) { $widthHeight = [$config->getWidth(), $config->getHeight()]; - switch ($config->getMode()) { - case ResizeConfiguration::MODE_CROP: - return $this->calculateCrop($widthHeight, $dimensions, $importantPartArray, $zoom); - - case ResizeConfiguration::MODE_PROPORTIONAL: - return $this->calculateProportional($widthHeight, $dimensions, $importantPartArray, $zoom); - - case ResizeConfiguration::MODE_BOX: - return $this->calculateBox($widthHeight, $dimensions, $importantPartArray, $zoom); - } - - throw new InvalidArgumentException(sprintf('Unsupported resize mode "%s"', $config->getMode())); + return match ($config->getMode()) { + ResizeConfiguration::MODE_CROP => $this->calculateCrop($widthHeight, $dimensions, $importantPartArray, $zoom), + ResizeConfiguration::MODE_BOX => $this->calculateBox($widthHeight, $dimensions, $importantPartArray, $zoom), + default => throw new InvalidArgumentException(sprintf('Unsupported resize mode "%s"', $config->getMode())), + }; } // If no dimensions are specified, use the zoomed important part @@ -103,24 +96,6 @@ private function calculateCrop(array $size, ImageDimensions $original, array $im return $this->buildCoordinates([$targetWidth, $targetHeight], [$targetX, $targetY], $size, $original); } - /** - * Calculates the resize coordinates for mode proportional. - * - * @param array $size - */ - private function calculateProportional(array $size, ImageDimensions $original, array $importantPart, float $zoom): ResizeCoordinates - { - $importantPart = $this->zoomImportantPart($importantPart, $zoom, $original->getSize()); - - if ($importantPart['width'] >= $importantPart['height']) { - $size[1] = 0; - } else { - $size[0] = 0; - } - - return $this->calculateSingleDimension($size, $original, $importantPart); - } - /** * Calculates the resize coordinates for mode box. * @@ -168,12 +143,8 @@ private function calculateSingleDimension(array $size, ImageDimensions $original * * @return array */ - private function importantPartAsArray(ImageDimensions $dimensions, ImportantPart $importantPart = null): array + private function importantPartAsArray(ImageDimensions $dimensions, ImportantPart $importantPart): array { - if (null === $importantPart) { - $importantPart = new ImportantPart(); - } - $imageWidth = $dimensions->getSize()->getWidth(); $imageHeight = $dimensions->getSize()->getHeight(); @@ -264,8 +235,7 @@ private function calculateLeastZoomed(array $size, BoxInterface $origSize, array if ($zoomed['width'] > $part['width']) { $zoomed['x'] = ($origSize->getWidth() - $zoomed['width']) * $part['x'] - / ($origSize->getWidth() - $part['width']) - ; + / ($origSize->getWidth() - $part['width']); } else { $zoomed['x'] = $part['x'] + (($part['width'] - $zoomed['width']) / 2); } @@ -275,8 +245,7 @@ private function calculateLeastZoomed(array $size, BoxInterface $origSize, array if ($zoomed['height'] > $part['height']) { $zoomed['y'] = ($origSize->getHeight() - $zoomed['height']) * $part['y'] - / ($origSize->getHeight() - $part['height']) - ; + / ($origSize->getHeight() - $part['height']); } else { $zoomed['y'] = $part['y'] + (($part['height'] - $zoomed['height']) / 2); } @@ -304,8 +273,7 @@ private function calculateMostZoomed(array $size, BoxInterface $origSize, array if ($origSize->getHeight() > $part['height']) { $zoomed['y'] -= ($zoomed['height'] - $part['height']) * $part['y'] - / ($origSize->getHeight() - $part['height']) - ; + / ($origSize->getHeight() - $part['height']); } } else { $zoomed['width'] = $size[0] * $zoomed['height'] / $size[1]; @@ -313,8 +281,7 @@ private function calculateMostZoomed(array $size, BoxInterface $origSize, array if ($origSize->getWidth() > $part['width']) { $zoomed['x'] -= ($zoomed['width'] - $part['width']) * $part['x'] - / ($origSize->getWidth() - $part['width']) - ; + / ($origSize->getWidth() - $part['width']); } } diff --git a/src/ResizeConfiguration.php b/src/ResizeConfiguration.php index 368cf22..46fe5bf 100644 --- a/src/ResizeConfiguration.php +++ b/src/ResizeConfiguration.php @@ -16,29 +16,25 @@ class ResizeConfiguration { - public const MODE_CROP = 'crop'; - public const MODE_BOX = 'box'; - public const MODE_PROPORTIONAL = 'proportional'; + final public const MODE_CROP = 'crop'; + final public const MODE_BOX = 'box'; /** - * @var int + * @var 0|positive-int */ - private $width = 0; + private int $width = 0; /** - * @var int + * @var 0|positive-int */ - private $height = 0; + private int $height = 0; /** - * @var string + * @var self::MODE_* */ - private $mode = self::MODE_CROP; + private string $mode = self::MODE_CROP; - /** - * @var int - */ - private $zoomLevel = 0; + private int $zoomLevel = 0; /** * Returns true if the resize would have no effect. @@ -48,12 +44,18 @@ public function isEmpty(): bool return 0 === $this->width && 0 === $this->height && 0 === $this->zoomLevel; } + /** + * @return 0|positive-int + */ public function getWidth(): int { return $this->width; } - public function setWidth(int $width): self + /** + * @param 0|positive-int $width + */ + public function setWidth(int $width): static { if ($width < 0) { throw new InvalidArgumentException('Width must not be negative'); @@ -64,12 +66,18 @@ public function setWidth(int $width): self return $this; } + /** + * @return 0|positive-int + */ public function getHeight(): int { return $this->height; } - public function setHeight(int $height): self + /** + * @param 0|positive-int $height + */ + public function setHeight(int $height): static { if ($height < 0) { throw new InvalidArgumentException('Height must not be negative'); @@ -81,7 +89,7 @@ public function setHeight(int $height): self } /** - * @return string One of the ResizeConfiguration::MODE_* constants + * @return self::MODE_* */ public function getMode(): string { @@ -89,11 +97,17 @@ public function getMode(): string } /** - * @param string $mode One of the ResizeConfiguration::MODE_* constants + * @param self::MODE_* $mode */ - public function setMode(string $mode): self + public function setMode(string $mode): static { - if (!\in_array($mode, [self::MODE_CROP, self::MODE_BOX, self::MODE_PROPORTIONAL], true)) { + if ('proportional' === $mode) { + trigger_deprecation('contao/image', '1.2', 'Using mode "proportional" has been deprecated and will no longer work in version 3.0. Use ResizeConfiguration::MODE_BOX instead.'); + + $mode = self::MODE_BOX; + } + + if (!\in_array($mode, [self::MODE_CROP, self::MODE_BOX], true)) { throw new InvalidArgumentException('Mode must be one of the '.self::class.'::MODE_* constants'); } @@ -102,12 +116,18 @@ public function setMode(string $mode): self return $this; } + /** + * @return int<0,100> + */ public function getZoomLevel(): int { return $this->zoomLevel; } - public function setZoomLevel(int $zoomLevel): self + /** + * @param int<0,100> $zoomLevel + */ + public function setZoomLevel(int $zoomLevel): static { if ($zoomLevel < 0 || $zoomLevel > 100) { throw new InvalidArgumentException('Zoom level must be between 0 and 100'); diff --git a/src/ResizeConfigurationInterface.php b/src/ResizeConfigurationInterface.php deleted file mode 100644 index 13999e1..0000000 --- a/src/ResizeConfigurationInterface.php +++ /dev/null @@ -1,26 +0,0 @@ -size = $size; - $this->cropStart = $cropStart; - $this->cropSize = $cropSize; + public function __construct( + private readonly BoxInterface $size, + private readonly PointInterface $cropStart, + private readonly BoxInterface $cropSize, + ) { } public function getSize(): BoxInterface @@ -70,27 +54,18 @@ public function getHash(): string /** * Compares the coordinates with another ResizeCoordinates or Box object. - * - * @param self|BoxInterface $coordinates */ - public function isEqualTo($coordinates): bool + public function isEqualTo(BoxInterface|self $coordinates): bool { - /** @var BoxInterface $coordinates */ if ($coordinates instanceof BoxInterface) { $coordinates = new self($coordinates, new Point(0, 0), $coordinates); } - if (!$coordinates instanceof self) { - throw new InvalidArgumentException(sprintf('$coordinates must be an instance of ResizeCoordinates or BoxInterface, "%s" given', \get_class($coordinates))); - } - - /** @var self $coordinates */ return $this->cropStart->getX() === $coordinates->getCropStart()->getX() && $this->cropStart->getY() === $coordinates->getCropStart()->getY() && $this->cropSize->getWidth() === $coordinates->getCropSize()->getWidth() && $this->cropSize->getHeight() === $coordinates->getCropSize()->getHeight() && $this->size->getWidth() === $coordinates->getSize()->getWidth() - && $this->size->getHeight() === $coordinates->getSize()->getHeight() - ; + && $this->size->getHeight() === $coordinates->getSize()->getHeight(); } } diff --git a/src/ResizeOptions.php b/src/ResizeOptions.php index 95668d2..81615ad 100644 --- a/src/ResizeOptions.php +++ b/src/ResizeOptions.php @@ -22,30 +22,15 @@ class ResizeOptions { - /** - * @var array - */ - private $imagineOptions = []; - - /** - * @var ?string - */ - private $targetPath; - - /** - * @var bool - */ - private $bypassCache = false; - - /** - * @var bool - */ - private $skipIfDimensionsMatch = false; - - /** - * @var array - */ - private $preserveCopyrightMetadata = [ + private array $imagineOptions = []; + + private string|null $targetPath = null; + + private bool $bypassCache = false; + + private bool $skipIfDimensionsMatch = false; + + private array $preserveCopyrightMetadata = [ XmpFormat::NAME => XmpFormat::DEFAULT_PRESERVE_KEYS, IptcFormat::NAME => IptcFormat::DEFAULT_PRESERVE_KEYS, ExifFormat::NAME => ExifFormat::DEFAULT_PRESERVE_KEYS, @@ -58,19 +43,19 @@ public function getImagineOptions(): array return $this->imagineOptions; } - public function setImagineOptions(array $imagineOptions): self + public function setImagineOptions(array $imagineOptions): static { $this->imagineOptions = $imagineOptions; return $this; } - public function getTargetPath(): ?string + public function getTargetPath(): string|null { return $this->targetPath; } - public function setTargetPath(?string $targetPath): self + public function setTargetPath(string|null $targetPath): static { if (null !== $targetPath && !(new Filesystem())->isAbsolutePath($targetPath)) { throw new InvalidArgumentException('"'.$targetPath.'" is not an absolute target path'); @@ -86,7 +71,7 @@ public function getBypassCache(): bool return $this->bypassCache; } - public function setBypassCache(bool $bypassCache): self + public function setBypassCache(bool $bypassCache): static { $this->bypassCache = $bypassCache; @@ -98,7 +83,7 @@ public function getSkipIfDimensionsMatch(): bool return $this->skipIfDimensionsMatch; } - public function setSkipIfDimensionsMatch(bool $skipIfDimensionsMatch): self + public function setSkipIfDimensionsMatch(bool $skipIfDimensionsMatch): static { $this->skipIfDimensionsMatch = $skipIfDimensionsMatch; @@ -110,7 +95,7 @@ public function getPreserveCopyrightMetadata(): array return $this->preserveCopyrightMetadata; } - public function setPreserveCopyrightMetadata(array $preserveCopyrightMetadata): self + public function setPreserveCopyrightMetadata(array $preserveCopyrightMetadata): static { $this->preserveCopyrightMetadata = $preserveCopyrightMetadata; diff --git a/src/Resizer.php b/src/Resizer.php index 4a8cb4d..a794e85 100644 --- a/src/Resizer.php +++ b/src/Resizer.php @@ -13,6 +13,7 @@ namespace Contao\Image; use Contao\Image\Exception\InvalidArgumentException; +use Contao\Image\Exception\JsonException; use Contao\Image\Metadata\ImageMetadata; use Contao\Image\Metadata\MetadataReaderWriter; use Imagine\Exception\InvalidArgumentException as ImagineInvalidArgumentException; @@ -22,106 +23,37 @@ use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Path; -/** - * @method __construct(string $cacheDir, string $secret, ResizeCalculator $calculator = null, Filesystem $filesystem = null, MetadataReaderWriter $metadataReaderWriter = null) - */ class Resizer implements ResizerInterface { - /** - * @var Filesystem - * - * @internal - */ - protected $filesystem; + private readonly Filesystem $filesystem; - /** - * @var string - * - * @internal - */ - protected $cacheDir; + private readonly string $cacheDir; - /** - * @var ResizeCalculator - */ - private $calculator; + private readonly ResizeCalculator $calculator; - /** - * @var MetadataReaderWriter - */ - private $metadataReaderWriter; + private readonly MetadataReaderWriter $metadataReaderWriter; /** - * @var string|null + * @var non-empty-string */ - private $secret; + private readonly string $secret; /** - * @param string $cacheDir - * @param string $secret - * @param ResizeCalculator|null $calculator - * @param Filesystem|null $filesystem - * @param MetadataReaderWriter|null $metadataReaderWriter + * @param non-empty-string $secret */ - public function __construct(string $cacheDir/*, string $secret, ResizeCalculator $calculator = null, Filesystem $filesystem = null, MetadataReaderWriter $metadataReaderWriter = null*/) + public function __construct(string $cacheDir, string $secret, ResizeCalculator $calculator = null, Filesystem $filesystem = null, MetadataReaderWriter $metadataReaderWriter = null) { - if (\func_num_args() > 1 && \is_string(func_get_arg(1))) { - $secret = func_get_arg(1); - $calculator = \func_num_args() > 2 ? func_get_arg(2) : null; - $filesystem = \func_num_args() > 3 ? func_get_arg(3) : null; - $metadataReaderWriter = \func_num_args() > 4 ? func_get_arg(4) : null; - } else { - trigger_deprecation('contao/image', '1.2', 'Not passing a secret to "%s()" has been deprecated and will no longer work in version 2.0.', __METHOD__); - $secret = null; - $calculator = \func_num_args() > 1 ? func_get_arg(1) : null; - $filesystem = \func_num_args() > 2 ? func_get_arg(2) : null; - $metadataReaderWriter = \func_num_args() > 3 ? func_get_arg(3) : null; - } - - if (null === $calculator) { - $calculator = new ResizeCalculator(); - } - - if (null === $filesystem) { - $filesystem = new Filesystem(); - } - - if (null === $metadataReaderWriter) { - $metadataReaderWriter = new MetadataReaderWriter(); - } - - if (!$calculator instanceof ResizeCalculator) { - $type = \is_object($calculator) ? \get_class($calculator) : \gettype($calculator); - - throw new \TypeError(sprintf('%s(): Argument #3 ($calculator) must be of type ResizeCalculator|null, %s given', __METHOD__, $type)); - } - - if (!$filesystem instanceof Filesystem) { - $type = \is_object($filesystem) ? \get_class($filesystem) : \gettype($filesystem); - - throw new \TypeError(sprintf('%s(): Argument #4 ($filesystem) must be of type ResizeCalculator|null, %s given', __METHOD__, $type)); - } - - if (!$metadataReaderWriter instanceof MetadataReaderWriter) { - $type = \is_object($metadataReaderWriter) ? \get_class($metadataReaderWriter) : \gettype($metadataReaderWriter); - - throw new \TypeError(sprintf('%s(): Argument #5 ($metadataReaderWriter) must be of type MetadataReaderWriter|null, %s given', __METHOD__, $type)); - } - if ('' === $secret) { throw new InvalidArgumentException('$secret must not be empty'); } $this->cacheDir = $cacheDir; - $this->calculator = $calculator; - $this->filesystem = $filesystem; - $this->metadataReaderWriter = $metadataReaderWriter; + $this->calculator = $calculator ?? new ResizeCalculator(); + $this->filesystem = $filesystem ?? new Filesystem(); + $this->metadataReaderWriter = $metadataReaderWriter ?? new MetadataReaderWriter(); $this->secret = $secret; } - /** - * {@inheritdoc} - */ public function resize(ImageInterface $image, ResizeConfiguration $config, ResizeOptions $options): ImageInterface { if ( @@ -171,7 +103,7 @@ protected function executeResize(ImageInterface $image, ResizeCoordinates $coord if (isset($imagineOptions['interlace'])) { try { $imagineImage->interlace($imagineOptions['interlace']); - } catch (ImagineInvalidArgumentException|ImagineRuntimeException $e) { + } catch (ImagineInvalidArgumentException|ImagineRuntimeException) { // Ignore failed interlacing } } @@ -194,7 +126,7 @@ protected function executeResize(ImageInterface $image, ResizeCoordinates $coord try { $this->metadataReaderWriter->applyCopyrightToFile($tmpPath1, $tmpPath2, $metadata, $options->getPreserveCopyrightMetadata()); - } catch (\Throwable $exception) { + } catch (\Throwable) { $this->filesystem->rename($tmpPath1, $tmpPath2, true); } } else { @@ -209,12 +141,7 @@ protected function executeResize(ImageInterface $image, ResizeCoordinates $coord return $this->createImage($image, $path); } - /** - * Creates a new image instance for the specified path. - * - * @internal Do not call this method in your code; it will be made private in a future version - */ - protected function createImage(ImageInterface $image, string $path): ImageInterface + private function createImage(ImageInterface $image, string $path): ImageInterface { return new Image($path, $image->getImagine(), $this->filesystem); } @@ -237,20 +164,12 @@ protected function processResize(ImageInterface $image, ResizeConfiguration $con return $this->createImage($image, $image->getPath()); } - $cachePath = Path::join($this->cacheDir, $this->createCachePath($image->getPath(), $coordinates, $options, false)); + $cachePath = Path::join($this->cacheDir, $this->createCachePath($image->getPath(), $coordinates, $options)); if (!$options->getBypassCache()) { if ($this->filesystem->exists($cachePath)) { return $this->createImage($image, $cachePath); } - - $legacyCachePath = Path::join($this->cacheDir, $this->createCachePath($image->getPath(), $coordinates, $options, true)); - - if ($this->filesystem->exists($legacyCachePath)) { - trigger_deprecation('contao/image', '1.2', 'Reusing old cached images like "%s" from version 1.1 has been deprecated and will no longer work in version 2.0. Clear the image cache directory "%s" and regenerate all images to get rid of this message.', $legacyCachePath, $this->cacheDir); - - return $this->createImage($image, $legacyCachePath); - } } return $this->executeResize($image, $coordinates, $cachePath, $options); @@ -279,40 +198,35 @@ private function canSkipResize(ImageInterface $image, ResizeOptions $options): b /** * Returns the relative target cache path. */ - private function createCachePath(string $path, ResizeCoordinates $coordinates, ResizeOptions $options, bool $useLegacyHash): string + private function createCachePath(string $path, ResizeCoordinates $coordinates, ResizeOptions $options): string { $imagineOptions = $options->getImagineOptions(); ksort($imagineOptions); - $hashData = array_merge( - [ - Path::makeRelative($path, $this->cacheDir), - filemtime($path), - $coordinates->getHash(), - ], - array_keys($imagineOptions), - array_map( - static function ($value) { - return \is_array($value) ? implode(',', $value) : $value; - }, + $hashData = [ + Path::makeRelative($path, $this->cacheDir), + filemtime($path), + $coordinates->getHash(), + ...array_keys($imagineOptions), + ...array_map( + static fn ($value) => \is_array($value) ? implode(',', $value) : $value, array_values($imagineOptions) - ) - ); + ), + ]; $preserveMeta = $options->getPreserveCopyrightMetadata(); - if ($preserveMeta !== (new ResizeOptions())->getPreserveCopyrightMetadata()) { - ksort($preserveMeta, SORT_STRING); - $hashData[] = json_encode($preserveMeta); - } - - if ($useLegacyHash || null === $this->secret) { - $hash = substr(md5(implode('|', $hashData)), 0, 9); - } else { - $hash = hash_hmac('sha256', implode('|', $hashData), $this->secret, true); - $hash = substr($this->encodeBase32($hash), 0, 16); + try { + if ($preserveMeta !== (new ResizeOptions())->getPreserveCopyrightMetadata()) { + ksort($preserveMeta, SORT_STRING); + $hashData[] = json_encode($preserveMeta, JSON_THROW_ON_ERROR); + } + } catch (\JsonException $e) { + throw new JsonException($e->getMessage(), $e->getCode(), $e); } + $hash = hash_hmac('sha256', implode('|', $hashData), $this->secret, true); + $hash = substr($this->encodeBase32($hash), 0, 16); $pathinfo = pathinfo($path); $extension = $options->getImagineOptions()['format'] ?? strtolower($pathinfo['extension']); @@ -323,7 +237,7 @@ private function getMetadata(ImageInterface $image): ImageMetadata { try { return $this->metadataReaderWriter->parse($image->getPath()); - } catch (\Throwable $exception) { + } catch (\Throwable) { return new ImageMetadata([]); } } diff --git a/src/ResizerInterface.php b/src/ResizerInterface.php index c900753..755544e 100644 --- a/src/ResizerInterface.php +++ b/src/ResizerInterface.php @@ -14,8 +14,5 @@ interface ResizerInterface { - /** - * Resizes an Image object. - */ public function resize(ImageInterface $image, ResizeConfiguration $config, ResizeOptions $options): ImageInterface; } diff --git a/tests/DeferredImageStorageFilesystemTest.php b/tests/DeferredImageStorageFilesystemTest.php index 5ab9fde..72025ba 100644 --- a/tests/DeferredImageStorageFilesystemTest.php +++ b/tests/DeferredImageStorageFilesystemTest.php @@ -22,14 +22,8 @@ class DeferredImageStorageFilesystemTest extends TestCase { - /** - * @var string - */ - private $rootDir; + private string $rootDir; - /** - * {@inheritdoc} - */ protected function setUp(): void { parent::setUp(); @@ -37,9 +31,6 @@ protected function setUp(): void $this->rootDir = Path::canonicalize(__DIR__.'/tmp'); } - /** - * {@inheritdoc} - */ protected function tearDown(): void { parent::tearDown(); @@ -166,7 +157,7 @@ public function testInvalidUtf8Throws(): void /** * @dataProvider invalidKeys */ - public function testSetInvalidKeyThrows($key): void + public function testSetInvalidKeyThrows(string $key): void { $storage = new DeferredImageStorageFilesystem($this->rootDir); diff --git a/tests/DeferredResizerTest.php b/tests/DeferredResizerTest.php index cc5862a..43f1a75 100644 --- a/tests/DeferredResizerTest.php +++ b/tests/DeferredResizerTest.php @@ -36,14 +36,8 @@ class DeferredResizerTest extends TestCase { - /** - * @var string - */ - private $rootDir; - - /** - * {@inheritdoc} - */ + private string $rootDir; + protected function setUp(): void { parent::setUp(); @@ -51,9 +45,6 @@ protected function setUp(): void $this->rootDir = Path::canonicalize(__DIR__.'/tmp'); } - /** - * {@inheritdoc} - */ protected function tearDown(): void { parent::tearDown(); @@ -69,13 +60,11 @@ public function testResize(): void $calculator ->method('calculate') ->willReturnCallback( - static function (ResizeConfiguration $config, ImageDimensions $dimensions, ImportantPart $importantPart = null) { - return new ResizeCoordinates( - new Box($config->getWidth(), $config->getHeight()), - new Point(0, 0), - new Box($config->getWidth(), $config->getHeight()) - ); - } + static fn (ResizeConfiguration $config, ImageDimensions $dimensions, ImportantPart $importantPart = null) => new ResizeCoordinates( + new Box($config->getWidth(), $config->getHeight()), + new Point(0, 0), + new Box($config->getWidth(), $config->getHeight()) + ) ) ; diff --git a/tests/ImageTest.php b/tests/ImageTest.php index 8089db8..5f6e235 100644 --- a/tests/ImageTest.php +++ b/tests/ImageTest.php @@ -30,14 +30,8 @@ class ImageTest extends TestCase { - /** - * @var string - */ - private $rootDir; + private string $rootDir; - /** - * {@inheritdoc} - */ protected function setUp(): void { parent::setUp(); @@ -45,9 +39,6 @@ protected function setUp(): void $this->rootDir = Path::canonicalize(__DIR__.'/tmp'); } - /** - * {@inheritdoc} - */ protected function tearDown(): void { parent::tearDown(); diff --git a/tests/ImportantPartTest.php b/tests/ImportantPartTest.php index 3afc064..f11b31b 100644 --- a/tests/ImportantPartTest.php +++ b/tests/ImportantPartTest.php @@ -43,7 +43,7 @@ public function testInvalidValuesThrowsException(float $x, float $y, float $widt $this->expectException(CoordinatesOutOfBoundsException::class); if (method_exists($this, 'expectExceptionMessageRegExp')) { - $this->expectExceptionMessageRegExp('/'.$message.'/i'); + $this->expectExceptionMessageMatches('/'.$message.'/i'); } else { $this->expectExceptionMessageMatches('/'.$message.'/i'); } diff --git a/tests/Metadata/XmpFormatTest.php b/tests/Metadata/XmpFormatTest.php index cad2eda..087925b 100644 --- a/tests/Metadata/XmpFormatTest.php +++ b/tests/Metadata/XmpFormatTest.php @@ -29,8 +29,7 @@ public function testParse(string $source, array $expected, array $expectedReadab .'' .$source .'' - .'' - ; + .''; if (!$expected) { $this->expectException(InvalidImageMetadataException::class); diff --git a/tests/PhpunitExtension/DeprecatedClasses.php b/tests/PhpunitExtension/DeprecatedClasses.php deleted file mode 100644 index 42a05e0..0000000 --- a/tests/PhpunitExtension/DeprecatedClasses.php +++ /dev/null @@ -1,26 +0,0 @@ - ['%sResizeConfigurationInterface%shas been deprecated%s'], - ]; - } -} diff --git a/tests/PictureTest.php b/tests/PictureTest.php index c0d8cf0..a10e261 100644 --- a/tests/PictureTest.php +++ b/tests/PictureTest.php @@ -26,7 +26,7 @@ public function testGetImg(): void { $picture = $this->createPicture(null, '/path/to/a/filename with special&<>"\'chars.jpeg'); - $this->assertInstanceOf(ImageInterface::class, $picture->getImg()['src']); + $this->assertInstanceOf(ImageInterface::class, $picture->getRawImg()['src']); $this->assertSame( 'path/to/a/filename%20with%20special%26%3C%3E%22%27chars.jpeg', @@ -53,7 +53,7 @@ public function testGetImg(): void $picture->getImg('/path/to', 'https://example.com/images/')['src'] ); - $this->assertInstanceOf(ImageInterface::class, $picture->getImg()['srcset'][0][0]); + $this->assertInstanceOf(ImageInterface::class, $picture->getRawImg()['srcset'][0][0]); $this->assertSame( 'path/to/a/filename%20with%20special%26%3C%3E%22%27chars.jpeg 1x', @@ -80,19 +80,15 @@ public function testGetImg(): void $picture->getImg('/path/to', 'https://example.com/images/')['srcset'] ); - $this->assertSame('custom attribute', $picture->getImg()['data-custom']); - $this->assertSame('custom attribute', $picture->getImg('/')['data-custom']); - - $this->expectException(InvalidArgumentException::class); - - $picture->getImg(null, 'https://example.com/images/'); + $this->assertSame('custom attribute', $picture->getRawImg()['data-custom'] ?? null); + $this->assertSame('custom attribute', $picture->getImg('/')['data-custom'] ?? null); } public function testGetSources(): void { $picture = $this->createPicture(null, '/path/to/a/filename with special&<>"\'chars.jpeg'); - $this->assertInstanceOf(ImageInterface::class, $picture->getSources()[0]['srcset'][0][0]); + $this->assertInstanceOf(ImageInterface::class, $picture->getRawSources()[0]['srcset'][0][0]); $this->assertSame( 'path/to/a/filename%20with%20special%26%3C%3E%22%27chars.jpeg 1x', @@ -119,18 +115,15 @@ public function testGetSources(): void $picture->getSources('/path/to', 'https://example.com/images/')[0]['srcset'] ); - $this->assertSame('custom attribute', $picture->getSources()[0]['data-custom']); - $this->assertSame('custom attribute', $picture->getSources('/')[0]['data-custom']); - - $this->expectException(InvalidArgumentException::class); - - $picture->getSources(null, 'https://example.com/images/'); + $this->assertSame('custom attribute', $picture->getRawSources()[0]['data-custom'] ?? null); + $this->assertSame('custom attribute', $picture->getSources('/')[0]['data-custom'] ?? null); } public function testMissingSrc(): void { $this->expectException(InvalidArgumentException::class); + /** @phpstan-ignore-next-line */ new Picture(['srcset' => []], []); } @@ -138,6 +131,7 @@ public function testInvalidSrc(): void { $this->expectException(InvalidArgumentException::class); + /** @phpstan-ignore-next-line */ new Picture(['src' => new \stdClass(), 'srcset' => []], []); } @@ -147,6 +141,7 @@ public function testMissingSrcset(): void $this->expectException(InvalidArgumentException::class); + /** @phpstan-ignore-next-line */ new Picture(['src' => $image], []); } @@ -156,6 +151,7 @@ public function testInvalidSrcset(): void $this->expectException(InvalidArgumentException::class); + /** @phpstan-ignore-next-line */ new Picture(['src' => $image, 'srcset' => [[$image, '1x'], [new \stdClass(), '2x']]], []); } diff --git a/tests/ResizeCalculatorTest.php b/tests/ResizeCalculatorTest.php index 5f6360f..e7730b7 100644 --- a/tests/ResizeCalculatorTest.php +++ b/tests/ResizeCalculatorTest.php @@ -41,9 +41,9 @@ public function testCalculateWithoutImportantPart(array $arguments, array $expec $dimensions = new ImageDimensions(new Box($arguments[2], $arguments[3]), !empty($arguments[5])); $importantPart = null; - if ($arguments[4] && 1 === substr_count($arguments[4], '_')) { + if ($arguments[4] && 1 === substr_count((string) $arguments[4], '_')) { $importantPart = ['x' => 0, 'y' => 0, 'width' => 1, 'height' => 1]; - $mode = explode('_', $arguments[4]); + $mode = explode('_', (string) $arguments[4]); if ('left' === $mode[0]) { $importantPart['width'] = 0; @@ -73,7 +73,7 @@ public function testCalculateWithoutImportantPart(array $arguments, array $expec $config->setMode($arguments[4]); } - $this->assertSameCoordinates($expected, $calculator->calculate($config, $dimensions, $importantPart)); + $this->assertSameCoordinates($expected, $calculator->calculate($config, $dimensions, $importantPart ?? new ImportantPart())); if (null !== $importantPart) { return; @@ -222,42 +222,6 @@ public function getCalculateDataWithoutImportantPart(): \Generator ], ]; - yield 'Mode proportional landscape' => [ - [100, 10, 100, 50, 'proportional'], - [ - 'width' => 100, - 'height' => 50, - 'target_x' => 0, - 'target_y' => 0, - 'target_width' => 100, - 'target_height' => 50, - ], - ]; - - yield 'Mode proportional portrait' => [ - [10, 100, 50, 100, 'proportional'], - [ - 'width' => 50, - 'height' => 100, - 'target_x' => 0, - 'target_y' => 0, - 'target_width' => 50, - 'target_height' => 100, - ], - ]; - - yield 'Mode proportional square' => [ - [100, 50, 100, 100, 'proportional'], - [ - 'width' => 100, - 'height' => 100, - 'target_x' => 0, - 'target_y' => 0, - 'target_width' => 100, - 'target_height' => 100, - ], - ]; - yield 'Mode box landscape 1' => [ [100, 100, 100, 50, 'box'], [ diff --git a/tests/ResizeConfigurationInterfaceTest.php b/tests/ResizeConfigurationInterfaceTest.php deleted file mode 100644 index 3cd549a..0000000 --- a/tests/ResizeConfigurationInterfaceTest.php +++ /dev/null @@ -1,31 +0,0 @@ -assertSame(ResizeConfiguration::MODE_CROP, ResizeConfigurationInterface::MODE_CROP); - $this->assertSame(ResizeConfiguration::MODE_BOX, ResizeConfigurationInterface::MODE_BOX); - $this->assertSame(ResizeConfiguration::MODE_PROPORTIONAL, ResizeConfigurationInterface::MODE_PROPORTIONAL); - } -} diff --git a/tests/ResizeConfigurationTest.php b/tests/ResizeConfigurationTest.php index 061fe0e..d615eae 100644 --- a/tests/ResizeConfigurationTest.php +++ b/tests/ResizeConfigurationTest.php @@ -15,9 +15,12 @@ use Contao\Image\Exception\InvalidArgumentException; use Contao\Image\ResizeConfiguration; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; class ResizeConfigurationTest extends TestCase { + use ExpectDeprecationTrait; + public function testIsEmpty(): void { $config = new ResizeConfiguration(); @@ -28,10 +31,6 @@ public function testIsEmpty(): void $this->assertTrue($config->isEmpty()); - $config->setMode(ResizeConfiguration::MODE_PROPORTIONAL); - - $this->assertTrue($config->isEmpty()); - $config->setMode(ResizeConfiguration::MODE_BOX); $this->assertTrue($config->isEmpty()); @@ -55,6 +54,13 @@ public function testIsEmpty(): void $config->setWidth(0)->setHeight(0)->setZoomLevel(0); $this->assertTrue($config->isEmpty()); + + $this->expectDeprecation('Using mode "proportional" has been deprecated%s'); + + /** @phpstan-ignore-next-line */ + $config->setMode('proportional'); + + $this->assertTrue($config->isEmpty()); } public function testSetWidth(): void @@ -67,6 +73,7 @@ public function testSetWidth(): void $this->expectException(InvalidArgumentException::class); + /** @phpstan-ignore-next-line */ $config->setWidth(-1); } @@ -80,6 +87,7 @@ public function testSetHeight(): void $this->expectException(InvalidArgumentException::class); + /** @phpstan-ignore-next-line */ $config->setHeight(-1); } @@ -93,6 +101,7 @@ public function testSetMode(): void $this->expectException(InvalidArgumentException::class); + /** @phpstan-ignore-next-line */ $config->setMode('invalid'); } @@ -106,6 +115,7 @@ public function testSetZoomLevel(): void $this->expectException(InvalidArgumentException::class); + /** @phpstan-ignore-next-line */ $config->setZoomLevel(-1); } @@ -115,6 +125,7 @@ public function testSetZoomLevelTooHigh(): void $this->expectException(InvalidArgumentException::class); + /** @phpstan-ignore-next-line */ $config->setZoomLevel(101); } } diff --git a/tests/ResizeCoordinatesTest.php b/tests/ResizeCoordinatesTest.php index e994661..50e832c 100644 --- a/tests/ResizeCoordinatesTest.php +++ b/tests/ResizeCoordinatesTest.php @@ -12,7 +12,6 @@ namespace Contao\Image\Tests; -use Contao\Image\Exception\InvalidArgumentException; use Contao\Image\ResizeCoordinates; use Imagine\Image\Box; use Imagine\Image\BoxInterface; @@ -70,8 +69,9 @@ public function testIsEqualTo(): void $this->assertTrue($coordinates->isEqualTo(new Box(100, 100))); - $this->expectException(InvalidArgumentException::class); + $this->expectException(\TypeError::class); + /** @phpstan-ignore-next-line */ $coordinates->isEqualTo(new \stdClass()); } } diff --git a/tests/ResizerTest.php b/tests/ResizerTest.php index 2cfe729..3efe7af 100644 --- a/tests/ResizerTest.php +++ b/tests/ResizerTest.php @@ -35,22 +35,13 @@ use Imagine\Imagick\Imagine as ImagickImagine; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Path; class ResizerTest extends TestCase { - use ExpectDeprecationTrait; + private string $rootDir; - /** - * @var string - */ - private $rootDir; - - /** - * {@inheritdoc} - */ protected function setUp(): void { parent::setUp(); @@ -60,9 +51,6 @@ protected function setUp(): void (new Filesystem())->mkdir($this->rootDir); } - /** - * {@inheritdoc} - */ protected function tearDown(): void { parent::tearDown(); @@ -138,17 +126,17 @@ public function testMetadataDifferentFormats(): void $this->assertExpectedArrayRecursive( ['xmp' => $xmpExpected, 'exif' => $exifExpected], - (new MetadataReaderWriter())->parse($resized->getSources()[0]['src']->getPath())->getAll() + (new MetadataReaderWriter())->parse($resized->getRawSources()[0]['srcset'][0][0]->getPath())->getAll() ); $this->assertExpectedArrayRecursive( ['xmp' => $xmpExpected, 'gif' => $gifExpected], - (new MetadataReaderWriter())->parse($resized->getSources()[1]['src']->getPath())->getAll() + (new MetadataReaderWriter())->parse($resized->getRawSources()[1]['srcset'][0][0]->getPath())->getAll() ); $this->assertExpectedArrayRecursive( ['xmp' => $xmpExpected, 'exif' => $exifExpected, 'iptc' => $iptcSource], - (new MetadataReaderWriter())->parse($resized->getImg()['src']->getPath())->getAll() + (new MetadataReaderWriter())->parse($resized->getRawImg()['src']->getPath())->getAll() ); (new Filesystem())->remove($path); @@ -163,7 +151,7 @@ public function testMetadataDifferentFormats(): void /** * @dataProvider getMetadata */ - public function testMetadataRoundtrip($imageFormat, ImageMetadata $metadata, array $expected): void + public function testMetadataRoundtrip(string $imageFormat, ImageMetadata $metadata, array $expected): void { $supportedFormat = false; @@ -351,10 +339,7 @@ public function getMetadata(): \Generator ]; } - /** - * @dataProvider getWithOrWithoutSecret - */ - public function testResizeIgnoresMetadataReaderWriterErrors(bool $withSecret): void + public function testResizeIgnoresMetadataReaderWriterErrors(): void { $metadataReaderWriter = $this->createMock(MetadataReaderWriter::class); $metadataReaderWriter @@ -368,7 +353,7 @@ public function testResizeIgnoresMetadataReaderWriterErrors(bool $withSecret): v $imagine->create(new Box(100, 100))->save($path); $resized = $this - ->createResizer($withSecret, null, null, null, $metadataReaderWriter) + ->createResizer(null, null, null, $metadataReaderWriter) ->resize( new Image($path, $imagine), (new ResizeConfiguration()) @@ -392,7 +377,7 @@ public function testResizeIgnoresMetadataReaderWriterErrors(bool $withSecret): v ; $resized = $this - ->createResizer($withSecret, null, null, null, $metadataReaderWriter) + ->createResizer(null, null, null, $metadataReaderWriter) ->resize( new Image($path, $imagine), (new ResizeConfiguration()) @@ -404,10 +389,7 @@ public function testResizeIgnoresMetadataReaderWriterErrors(bool $withSecret): v $this->assertSame(25, $resized->getDimensions()->getSize()->getWidth()); } - /** - * @dataProvider getWithOrWithoutSecret - */ - public function testResize(bool $withSecret): void + public function testResize(): void { $calculator = $this->createMock(ResizeCalculator::class); $calculator @@ -415,7 +397,7 @@ public function testResize(bool $withSecret): void ->willReturn(new ResizeCoordinates(new Box(100, 100), new Point(0, 0), new Box(100, 100))) ; - $resizer = $this->createResizer($withSecret, null, $calculator); + $resizer = $this->createResizer(null, $calculator); if (!is_dir($this->rootDir)) { (new Filesystem())->mkdir($this->rootDir); @@ -462,11 +444,7 @@ public function testResize(bool $withSecret): void $this->assertEquals(new ImageDimensions(new Box(100, 100)), $resizedImage->getDimensions()); - if ($withSecret) { - $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.jpg$)', $resizedImage->getPath()); - } else { - $this->assertMatchesRegularExpression('(/[0-9a-f]/dummy-[0-9a-f]{8}.jpg$)', $resizedImage->getPath()); - } + $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.jpg$)', $resizedImage->getPath()); $this->assertFilePermissions(0666, $resizedImage->getPath()); (new Filesystem())->remove($resizedImage->getPath()); @@ -503,10 +481,7 @@ public function testResize(bool $withSecret): void $this->assertFilePermissions(0666, $resizedImage->getPath()); } - /** - * @dataProvider getWithOrWithoutSecret - */ - public function testResizeSvg(bool $withSecret): void + public function testResizeSvg(): void { $xml = '' .''; @@ -523,7 +498,7 @@ public function testResizeSvg(bool $withSecret): void ->willReturn(new ResizeCoordinates(new Box(100, 100), new Point(0, 0), new Box(100, 100))) ; - $resizer = $this->createResizer($withSecret, null, $calculator); + $resizer = $this->createResizer(null, $calculator); $image = $this->createMock(Image::class); $image @@ -560,11 +535,7 @@ public function testResizeSvg(bool $withSecret): void $this->assertFalse($resizedImage->getDimensions()->isUndefined()); $this->assertFilePermissions(0666, $resizedImage->getPath()); - if ($withSecret) { - $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.svg)', $resizedImage->getPath()); - } else { - $this->assertMatchesRegularExpression('(/[0-9a-f]/dummy-[0-9a-f]{8}.svg$)', $resizedImage->getPath()); - } + $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.svg)', $resizedImage->getPath()); (new Filesystem())->remove($resizedImage->getPath()); @@ -584,10 +555,7 @@ public function testResizeSvg(bool $withSecret): void (new Filesystem())->remove($resizedImage->getPath()); } - /** - * @dataProvider getWithOrWithoutSecret - */ - public function testResizeCache(bool $withSecret): void + public function testResizeCache(): void { $calculator = $this->createMock(ResizeCalculator::class); $calculator @@ -595,7 +563,7 @@ public function testResizeCache(bool $withSecret): void ->willReturn(new ResizeCoordinates(new Box(100, 100), new Point(0, 0), new Box(100, 100))) ; - $resizer = $this->createResizer($withSecret, null, $calculator); + $resizer = $this->createResizer(null, $calculator); if (!is_dir($this->rootDir)) { (new Filesystem())->mkdir($this->rootDir); @@ -628,11 +596,7 @@ public function testResizeCache(bool $withSecret): void $this->assertEquals(new ImageDimensions(new Box(100, 100)), $resizedImage->getDimensions()); $this->assertFilePermissions(0666, $resizedImage->getPath()); - if ($withSecret) { - $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.jpg$)', $resizedImage->getPath()); - } else { - $this->assertMatchesRegularExpression('(/[0-9a-f]/dummy-[0-9a-f]{8}.jpg$)', $resizedImage->getPath()); - } + $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.jpg$)', $resizedImage->getPath()); $imagePath = $resizedImage->getPath(); @@ -671,7 +635,7 @@ public function testResizeCache(bool $withSecret): void (new Filesystem())->copy(Path::join($this->rootDir, 'dummy.jpg'), Path::join($subDir, 'dummy.jpg')); (new Filesystem())->touch(Path::join($subDir, 'dummy.jpg'), filemtime(Path::join($this->rootDir, 'dummy.jpg'))); - $subResizer = $this->createResizer($withSecret, $subDir, $calculator); + $subResizer = $this->createResizer($subDir, $calculator); $subImage = $this->createMock(Image::class); $subImage @@ -745,13 +709,10 @@ public function testResizeUndefinedSize(): void $this->assertSame($imagePath, $resizedImage->getPath()); } - /** - * @dataProvider getWithOrWithoutSecret - */ - public function testResizeEmptyConfig(bool $withSecret): void + public function testResizeEmptyConfig(): void { $imagePath = Path::join($this->rootDir, 'dummy.jpg'); - $resizer = $this->createResizer($withSecret); + $resizer = $this->createResizer(); if (!is_dir($this->rootDir)) { (new Filesystem())->mkdir($this->rootDir); @@ -787,11 +748,7 @@ public function testResizeEmptyConfig(bool $withSecret): void $resizedImage = $resizer->resize($image, $configuration, new ResizeOptions()); - if ($withSecret) { - $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.jpg$)', $resizedImage->getPath()); - } else { - $this->assertMatchesRegularExpression('(/[0-9a-f]/dummy-[0-9a-f]{8}.jpg$)', $resizedImage->getPath()); - } + $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.jpg$)', $resizedImage->getPath()); $this->assertNotSame($image, $resizedImage); } @@ -840,13 +797,10 @@ public function testResizeEmptyConfigSkipsMatchingDimensions(): void $this->assertNotSame($image, $resizedImage); } - /** - * @dataProvider getWithOrWithoutSecret - */ - public function testResizeEmptyConfigWithFormat(bool $withSecret): void + public function testResizeEmptyConfigWithFormat(): void { $imagePath = Path::join($this->rootDir, 'dummy.jpg'); - $resizer = $this->createResizer($withSecret); + $resizer = $this->createResizer(); if (!is_dir($this->rootDir)) { (new Filesystem())->mkdir($this->rootDir); @@ -888,11 +842,7 @@ public function testResizeEmptyConfigWithFormat(bool $withSecret): void ->setImagineOptions(['format' => 'png']) ); - if ($withSecret) { - $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.png$)', $resizedImage->getPath()); - } else { - $this->assertMatchesRegularExpression('(/[0-9a-f]/dummy-[0-9a-f]{8}.png$)', $resizedImage->getPath()); - } + $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.png$)', $resizedImage->getPath()); $this->assertNotSame($image, $resizedImage); } @@ -907,7 +857,7 @@ public function testResizeSameDimensions(): void ->willReturn(new ResizeCoordinates(new Box(100, 100), new Point(0, 0), new Box(100, 100))) ; - $resizer = $this->createResizer(true, null, $calculator); + $resizer = $this->createResizer(null, $calculator); if (!is_dir($this->rootDir)) { (new Filesystem())->mkdir($this->rootDir); @@ -956,10 +906,7 @@ public function testResizeSameDimensions(): void $this->assertSame(Path::join($this->rootDir, 'target-path.jpg'), $resizedImage->getPath()); } - /** - * @dataProvider getWithOrWithoutSecret - */ - public function testResizeSameDimensionsRelative(bool $withSecret): void + public function testResizeSameDimensionsRelative(): void { $xml = ''. ''; @@ -976,7 +923,7 @@ public function testResizeSameDimensionsRelative(bool $withSecret): void ->willReturn(new ResizeCoordinates(new Box(100, 100), new Point(0, 0), new Box(100, 100))) ; - $resizer = $this->createResizer($withSecret, null, $calculator); + $resizer = $this->createResizer(null, $calculator); $image = $this->createMock(Image::class); $image @@ -1001,22 +948,15 @@ public function testResizeSameDimensionsRelative(bool $withSecret): void $this->assertSame(100, $resizedImage->getDimensions()->getSize()->getHeight()); $this->assertFalse($resizedImage->getDimensions()->isRelative()); - if ($withSecret) { - $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.svg$)', $resizedImage->getPath()); - } else { - $this->assertMatchesRegularExpression('(/[0-9a-f]/dummy-[0-9a-f]{8}.svg$)', $resizedImage->getPath()); - } + $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.svg$)', $resizedImage->getPath()); (new Filesystem())->remove($resizedImage->getPath()); } - /** - * @dataProvider getWithOrWithoutSecret - */ - public function testResizeEmptyConfigRotatedImage(bool $withSecret): void + public function testResizeEmptyConfigRotatedImage(): void { $imagePath = Path::join($this->rootDir, 'dummy.jpg'); - $resizer = $this->createResizer($withSecret); + $resizer = $this->createResizer(); if (!is_dir($this->rootDir)) { (new Filesystem())->mkdir($this->rootDir); @@ -1052,22 +992,15 @@ public function testResizeEmptyConfigRotatedImage(bool $withSecret): void $resizedImage = $resizer->resize($image, $configuration, new ResizeOptions()); - if ($withSecret) { - $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.jpg$)', $resizedImage->getPath()); - } else { - $this->assertMatchesRegularExpression('(/[0-9a-f]/dummy-[0-9a-f]{8}.jpg$)', $resizedImage->getPath()); - } + $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.jpg$)', $resizedImage->getPath()); $this->assertNotSame($image, $resizedImage); } - /** - * @dataProvider getWithOrWithoutSecret - */ - public function testResizeEmptyConfigNoSkip(bool $withSecret): void + public function testResizeEmptyConfigNoSkip(): void { $imagePath = Path::join($this->rootDir, 'dummy.jpg'); - $resizer = $this->createResizer($withSecret); + $resizer = $this->createResizer(); if (!is_dir($this->rootDir)) { (new Filesystem())->mkdir($this->rootDir); @@ -1103,21 +1036,11 @@ public function testResizeEmptyConfigNoSkip(bool $withSecret): void $resizedImage = $resizer->resize($image, $configuration, new ResizeOptions()); - if ($withSecret) { - $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.jpg$)', $resizedImage->getPath()); - } else { - $this->assertMatchesRegularExpression('(/[0-9a-f]/dummy-[0-9a-f]{8}.jpg$)', $resizedImage->getPath()); - } + $this->assertMatchesRegularExpression('(/[0-9a-z]/dummy-[0-9a-z]{15}.jpg$)', $resizedImage->getPath()); $this->assertNotSame($image, $resizedImage); } - public function getWithOrWithoutSecret(): \Generator - { - yield [true]; - yield [false]; - } - /** * @dataProvider getBase32 */ @@ -1177,19 +1100,13 @@ private function assertExpectedArrayRecursive(array $expected, array $actual): v } } - private function createResizer(bool $withSecret = true, string $cacheDir = null, ResizeCalculator $calculator = null, Filesystem $filesystem = null, MetadataReaderWriter $metadataReaderWriter = null): Resizer + private function createResizer(string $cacheDir = null, ResizeCalculator $calculator = null, Filesystem $filesystem = null, MetadataReaderWriter $metadataReaderWriter = null): Resizer { if (null === $cacheDir) { $cacheDir = $this->rootDir; } - if ($withSecret) { - return new Resizer($cacheDir, 'secret', $calculator, $filesystem, $metadataReaderWriter); - } - - $this->expectDeprecation('Not passing a secret%s'); - - return new Resizer($cacheDir, $calculator, $filesystem, $metadataReaderWriter); + return new Resizer($cacheDir, 'secret', $calculator, $filesystem, $metadataReaderWriter); } private function assertFilePermissions(int $expectedPermissions, string $path): void diff --git a/tools/ecs/composer.json b/tools/ecs/composer.json index 20b3c1e..6acf459 100644 --- a/tools/ecs/composer.json +++ b/tools/ecs/composer.json @@ -1,6 +1,6 @@ { "require": { - "contao/easy-coding-standard": "^5.0" + "contao/easy-coding-standard": "^6.1" }, "config": { "allow-plugins": { diff --git a/tools/ecs/config/default.php b/tools/ecs/config/default.php index c2027f2..ba96632 100644 --- a/tools/ecs/config/default.php +++ b/tools/ecs/config/default.php @@ -10,27 +10,14 @@ * @license LGPL-3.0-or-later */ -use Contao\EasyCodingStandard\Fixer\TypeHintOrderFixer; use PhpCsFixer\Fixer\Comment\HeaderCommentFixer; use PhpCsFixer\Fixer\ControlStructure\EmptyLoopBodyFixer; -use PhpCsFixer\Fixer\FunctionNotation\UseArrowFunctionsFixer; -use PhpCsFixer\Fixer\Phpdoc\NoSuperfluousPhpdocTagsFixer; -use PhpCsFixer\Fixer\PhpUnit\PhpUnitExpectationFixer; use Symplify\EasyCodingStandard\Config\ECSConfig; use Symplify\EasyCodingStandard\ValueObject\Option; return static function (ECSConfig $ecsConfig): void { $ecsConfig->sets([__DIR__.'/../vendor/contao/easy-coding-standard/config/contao.php']); - $ecsConfig->skip([ - PhpUnitExpectationFixer::class => [ - 'tests/ImportantPartTest.php', - ], - UseArrowFunctionsFixer::class => ['*'], - NoSuperfluousPhpdocTagsFixer::class => ['*'], - TypeHintOrderFixer::class => ['*'], - ]); - $ecsConfig->ruleWithConfiguration(HeaderCommentFixer::class, [ 'header' => "This file is part of Contao.\n\n(c) Leo Feyer\n\n@license LGPL-3.0-or-later", ]);