Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
15 changes: 6 additions & 9 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,25 @@
}
],
"require": {
"php": "^7.2 || ^8.0",
"php": "^8.1",
"ext-dom": "*",
"ext-gd": "*",
"ext-hash": "*",
"ext-json": "*",
"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"
Expand Down
16 changes: 5 additions & 11 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -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#'
4 changes: 0 additions & 4 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,4 @@
<directory>./src</directory>
</whitelist>
</filter>

<extensions>
<extension class="Contao\Image\Tests\PhpunitExtension\DeprecatedClasses"/>
</extensions>
</phpunit>
83 changes: 19 additions & 64 deletions src/DeferredImageStorageFilesystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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])) {
Expand All @@ -129,9 +98,6 @@ public function releaseLock(string $path): void
unset($this->locks[$path]);
}

/**
* {@inheritdoc}
*/
public function delete(string $path): void
{
try {
Expand All @@ -150,9 +116,6 @@ public function delete(string $path): void
}
}

/**
* {@inheritdoc}
*/
public function listPaths(): iterable
{
if (!$this->filesystem->exists($this->cacheDir)) {
Expand All @@ -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));
}
};
}
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/DeferredImageStorageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Loading