Skip to content

Commit

Permalink
Persistence improvements
Browse files Browse the repository at this point in the history
- improved image persistence - if the source image has not really been modified, the original is used, thus avoiding the increase in filesize
- methods `LinkGeneratorInterface::srcSet()` and `ImageStorageInterface::srcSet()` now returns object of type `SrcSet` instead of string
- fixed Imagick installations in Dockerfile
- added Docker image for PHP 8.3
  • Loading branch information
tg666 committed Jul 27, 2024
1 parent 0fd9e9c commit 335b892
Show file tree
Hide file tree
Showing 44 changed files with 875 additions and 209 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/coding-style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:
with:
php-version: 8.1
tools: composer:v2
extensions: imagick

- name: Install dependencies
run: composer update --no-progress --prefer-dist --prefer-stable --optimize-autoloader --quiet
Expand All @@ -42,6 +43,7 @@ jobs:
with:
php-version: 8.1
tools: composer:v2
extensions: imagick

- name: Install dependencies
run: composer update --no-progress --prefer-dist --prefer-stable --optimize-autoloader --quiet
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
with:
php-version: 8.1
coverage: none
extensions: tokenizer
extensions: imagick, tokenizer
tools: composer:v2

- name: Install dependencies
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: ['8.1', '8.2']
php-versions: ['8.1', '8.2', '8.3']
steps:
- name: Checkout
uses: actions/checkout@v3
Expand All @@ -26,6 +26,7 @@ jobs:
with:
php-version: ${{ matrix.php-versions }}
tools: composer:v2
extensions: imagick

- name: Install dependencies
run: composer update --no-progress --prefer-dist --prefer-stable --optimize-autoloader --quiet
Expand Down
72 changes: 63 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,78 @@ WORKDIR /var/www/html
RUN apk add --no-cache --update git
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN apk add --no-cache ${PHPIZE_DEPS} \
&& apk add --no-cache imagemagick imagemagick-dev \
&& pecl install imagick \
&& docker-php-ext-enable imagick
RUN set -ex \
# Build dependencies
&& apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
&& apk add --no-cache \
libgomp \
freetype-dev \
libjpeg-turbo-dev \
libwebp-dev \
libpng-dev \
libavif-dev \
imagemagick \
imagemagick-dev \
&& pecl install imagick-3.7.0 \
&& docker-php-ext-enable \
imagick \
&& apk del .build-deps

CMD tail -f /dev/null

FROM php:8.2.0RC6-cli-alpine3.16 AS php82
FROM php:8.2.21-cli-alpine3.20 AS php82

CMD ["/bin/sh"]
WORKDIR /var/www/html

RUN apk add --no-cache --update git
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN apk add --no-cache ${PHPIZE_DEPS} \
&& apk add --no-cache imagemagick imagemagick-dev \
&& pecl install imagick \
&& docker-php-ext-enable imagick
RUN set -ex \
# Build dependencies
&& apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
&& apk add --no-cache \
libgomp \
freetype-dev \
libjpeg-turbo-dev \
libwebp-dev \
libpng-dev \
libavif-dev \
imagemagick \
imagemagick-dev \
&& pecl install imagick-3.7.0 \
&& docker-php-ext-enable \
imagick \
&& apk del .build-deps

CMD tail -f /dev/null

FROM php:8.3.9-cli-alpine3.20 AS php83

CMD ["/bin/sh"]
WORKDIR /var/www/html

RUN apk add --no-cache --update git
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN set -ex \
# Build dependencies
&& apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
&& apk add --no-cache \
libgomp \
freetype-dev \
libjpeg-turbo-dev \
libwebp-dev \
libpng-dev \
libavif-dev \
imagemagick \
imagemagick-dev \
&& pecl install imagick-3.7.0 \
&& docker-php-ext-enable \
imagick \
&& apk del .build-deps

CMD tail -f /dev/null
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ restart:
tests.all:
PHP=81 make tests.run
PHP=82 make tests.run
PHP=83 make tests.run

cs.fix:
PHP=81 make composer.update
Expand Down
9 changes: 9 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,12 @@ services:
container_name: 68publishers.image-storage.82
volumes:
- .:/var/www/html:cached

php83:
build:
context: .
dockerfile: Dockerfile
target: php83
container_name: 68publishers.image-storage.83
volumes:
- .:/var/www/html:cached
1 change: 0 additions & 1 deletion src/Bridge/Nette/DI/ImageStorageExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,6 @@ public function createFileStorage(string $name, FileStorageConfig $config): Serv
->setFactory(ImagePersister::class, [
new Reference($this->prefix('filesystem.' . $name)),
new Reference($this->prefix('config.' . $name)),
new Reference($this->prefix('modifier_facade.' . $name)),
])
->setAutowired(false);

Expand Down
3 changes: 2 additions & 1 deletion src/FileInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use SixtyEightPublishers\ImageStorage\LinkGenerator\LinkGeneratorInterface as ImageLinkGeneratorInterface;
use SixtyEightPublishers\ImageStorage\PathInfoInterface as ImagePathInfoInterface;
use SixtyEightPublishers\ImageStorage\Responsive\Descriptor\DescriptorInterface;
use SixtyEightPublishers\ImageStorage\Responsive\SrcSet;
use function assert;

final class FileInfo extends BaseFileInfo implements FileInfoInterface
Expand All @@ -19,7 +20,7 @@ public function __construct(ImageLinkGeneratorInterface $linkGenerator, PathInfo
parent::__construct($linkGenerator, $pathInfo, $imageStorageName);
}

public function srcSet(DescriptorInterface $descriptor): string
public function srcSet(DescriptorInterface $descriptor): SrcSet
{
assert($this->linkGenerator instanceof ImageLinkGeneratorInterface);

Expand Down
3 changes: 2 additions & 1 deletion src/FileInfoInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

use SixtyEightPublishers\FileStorage\FileInfoInterface as BaseFileInfoInterface;
use SixtyEightPublishers\ImageStorage\Responsive\Descriptor\DescriptorInterface;
use SixtyEightPublishers\ImageStorage\Responsive\SrcSet;

interface FileInfoInterface extends BaseFileInfoInterface, PathInfoInterface
{
public function srcSet(DescriptorInterface $descriptor): string;
public function srcSet(DescriptorInterface $descriptor): SrcSet;
}
3 changes: 2 additions & 1 deletion src/ImageStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use SixtyEightPublishers\ImageStorage\PathInfoInterface as ImagePathInfoInterface;
use SixtyEightPublishers\ImageStorage\Persistence\ImagePersisterInterface;
use SixtyEightPublishers\ImageStorage\Responsive\Descriptor\DescriptorInterface;
use SixtyEightPublishers\ImageStorage\Responsive\SrcSet;
use SixtyEightPublishers\ImageStorage\Security\SignatureStrategyInterface;
use function assert;

Expand Down Expand Up @@ -89,7 +90,7 @@ public function resolveNoImage(string $path): ImagePathInfoInterface
return $this->noImageResolver->resolveNoImage($path);
}

public function srcSet(ImagePathInfoInterface $info, DescriptorInterface $descriptor): string
public function srcSet(ImagePathInfoInterface $info, DescriptorInterface $descriptor): SrcSet
{
assert($this->linkGenerator instanceof ImageLinkGeneratorInterface);

Expand Down
3 changes: 2 additions & 1 deletion src/LinkGenerator/LinkGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use SixtyEightPublishers\ImageStorage\Modifier\Facade\ModifierFacadeInterface;
use SixtyEightPublishers\ImageStorage\PathInfoInterface as ImagePathInfoInterface;
use SixtyEightPublishers\ImageStorage\Responsive\Descriptor\DescriptorInterface;
use SixtyEightPublishers\ImageStorage\Responsive\SrcSet;
use SixtyEightPublishers\ImageStorage\Responsive\SrcSetGenerator;
use SixtyEightPublishers\ImageStorage\Responsive\SrcSetGeneratorFactoryInterface;
use SixtyEightPublishers\ImageStorage\Security\SignatureStrategyInterface;
Expand Down Expand Up @@ -49,7 +50,7 @@ public function link(FilePathInfoInterface $pathInfo): string
return parent::link($pathInfo);
}

public function srcSet(ImagePathInfoInterface $info, DescriptorInterface $descriptor): string
public function srcSet(ImagePathInfoInterface $info, DescriptorInterface $descriptor): SrcSet
{
if (null === $this->srcSetGenerator) {
$this->srcSetGenerator = $this->srcSetGeneratorFactory->create($this, $this->modifierFacade);
Expand Down
3 changes: 2 additions & 1 deletion src/LinkGenerator/LinkGeneratorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
use SixtyEightPublishers\FileStorage\LinkGenerator\LinkGeneratorInterface as BaseLinkGeneratorInterface;
use SixtyEightPublishers\ImageStorage\PathInfoInterface;
use SixtyEightPublishers\ImageStorage\Responsive\Descriptor\DescriptorInterface;
use SixtyEightPublishers\ImageStorage\Responsive\SrcSet;
use SixtyEightPublishers\ImageStorage\Security\SignatureStrategyInterface;

interface LinkGeneratorInterface extends BaseLinkGeneratorInterface
{
public function srcSet(PathInfoInterface $info, DescriptorInterface $descriptor): string;
public function srcSet(PathInfoInterface $info, DescriptorInterface $descriptor): SrcSet;

public function getSignatureStrategy(): ?SignatureStrategyInterface;
}
20 changes: 14 additions & 6 deletions src/Modifier/Applicator/Format.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace SixtyEightPublishers\ImageStorage\Modifier\Applicator;

use Imagick;
use Intervention\Image\Image;
use SixtyEightPublishers\FileStorage\Config\ConfigInterface;
use SixtyEightPublishers\FileStorage\PathInfoInterface;
Expand All @@ -12,17 +13,24 @@
use SixtyEightPublishers\ImageStorage\Helper\SupportedType;
use SixtyEightPublishers\ImageStorage\Modifier\Collection\ModifierValues;
use SixtyEightPublishers\ImageStorage\Modifier\Quality;
use function assert;
use function in_array;
use function is_int;

final class Format implements ModifierApplicatorInterface
{
public function apply(Image $image, PathInfoInterface $pathInfo, ModifierValues $values, ConfigInterface $config): Image
public function apply(Image $image, PathInfoInterface $pathInfo, ModifierValues $values, ConfigInterface $config): ?Image
{
$extension = $this->getFileExtension($image, $pathInfo);
$quality = $values->getOptional(Quality::class, $config[Config::ENCODE_QUALITY]);
assert(is_int($quality));
$quality = $values->getOptional(Quality::class);
$needEncode = null !== $quality || SupportedType::getTypeByExtension($extension) !== $image->mime();

if (!$needEncode && 'pjpg' === $extension) {
$core = $image->getCore();
$needEncode = !($core instanceof Imagick) || in_array($core->getInterlaceScheme(), [Imagick::INTERLACE_UNDEFINED, Imagick::INTERLACE_NO], true);
}

if (!$needEncode) {
return null;
}

if (in_array($extension, ['jpg', 'pjpg'], true)) {
$image = $image->getDriver()
Expand All @@ -35,7 +43,7 @@ public function apply(Image $image, PathInfoInterface $pathInfo, ModifierValues
}
}

return $image->encode($extension, $quality);
return $image->encode($extension, (int) ($quality ?? $config[Config::ENCODE_QUALITY]));
}

private function getFileExtension(Image $image, PathInfoInterface $pathInfo): string
Expand Down
5 changes: 4 additions & 1 deletion src/Modifier/Applicator/ModifierApplicatorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@

interface ModifierApplicatorInterface
{
public function apply(Image $image, PathInfoInterface $pathInfo, ModifierValues $values, ConfigInterface $config): Image;
/**
* Returns NULL of image is not modified
*/
public function apply(Image $image, PathInfoInterface $pathInfo, ModifierValues $values, ConfigInterface $config): ?Image;
}
16 changes: 13 additions & 3 deletions src/Modifier/Applicator/Orientation.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,24 @@

final class Orientation implements ModifierApplicatorInterface
{
public function apply(Image $image, PathInfoInterface $pathInfo, ModifierValues $values, ConfigInterface $config): Image
public function apply(Image $image, PathInfoInterface $pathInfo, ModifierValues $values, ConfigInterface $config): ?Image
{
$orientation = $values->getOptional(OrientationModifier::class);

if (!is_string($orientation) && !is_numeric($orientation)) {
return $image;
return null;
}

return ($orientation === 'auto') ? $image->orientate() : $image->rotate((float) $orientation);
if ('auto' === $orientation) {
$exifOrientation = $image->exif('Orientation');

if (2 <= $exifOrientation && 8 >= $exifOrientation) {
return $image->orientate();
}

return null;
}

return $image->rotate((float) $orientation);
}
}
4 changes: 2 additions & 2 deletions src/Modifier/Applicator/Resize.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

final class Resize implements ModifierApplicatorInterface
{
public function apply(Image $image, PathInfoInterface $pathInfo, ModifierValues $values, ConfigInterface $config): Image
public function apply(Image $image, PathInfoInterface $pathInfo, ModifierValues $values, ConfigInterface $config): ?Image
{
$width = $values->getOptional(Width::class);
$height = $values->getOptional(Height::class);
Expand Down Expand Up @@ -70,7 +70,7 @@ public function apply(Image $image, PathInfoInterface $pathInfo, ModifierValues
$height = (int) ($height * $pd);

if ($width === $imageWidth && $height === $imageHeight) {
return $image;
return null;
}

switch ($fit) {
Expand Down
16 changes: 13 additions & 3 deletions src/Modifier/Facade/ModifierFacade.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public function getCodec(): CodecInterface
return $this->codec;
}

public function modifyImage(Image $image, PathInfoInterface $info, string|array $modifiers): Image
public function modifyImage(Image $image, PathInfoInterface $info, string|array $modifiers): ModifyResult
{
if (!is_array($modifiers)) {
$modifiers = $this->getCodec()->decode(new PresetValue($modifiers));
Expand All @@ -118,10 +118,20 @@ public function modifyImage(Image $image, PathInfoInterface $info, string|array
$validator->validate($values, $this->config);
}

$modified = false;

foreach ($this->applicators as $applicator) {
$image = $applicator->apply($image, $info, $values, $this->config);
$modifiedImage = $applicator->apply($image, $info, $values, $this->config);

if (null !== $modifiedImage) {
$image = $modifiedImage;
$modified = true;
}
}

return $image;
return new ModifyResult(
image: $image,
modified: $modified,
);
}
}
2 changes: 1 addition & 1 deletion src/Modifier/Facade/ModifierFacadeInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,5 @@ public function getCodec(): CodecInterface;
/**
* @param string|array<string, string|numeric|bool> $modifiers
*/
public function modifyImage(Image $image, PathInfoInterface $info, string|array $modifiers): Image;
public function modifyImage(Image $image, PathInfoInterface $info, string|array $modifiers): ModifyResult;
}
15 changes: 15 additions & 0 deletions src/Modifier/Facade/ModifyResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace SixtyEightPublishers\ImageStorage\Modifier\Facade;

use Intervention\Image\Image;

final class ModifyResult
{
public function __construct(
public readonly Image $image,
public readonly bool $modified,
) {}
}
Loading

0 comments on commit 335b892

Please sign in to comment.