Update intervention/image.

Changelogs summary:

 - intervention/gif installed in version 3.0.0
   Release notes: https://github.com/Intervention/gif/releases/tag/3.0.0

 - intervention/image updated from 2.7.2 to 3.0.2 major
   See changes: https://github.com/Intervention/image/compare/2.7.2...3.0.2
   Release notes: https://github.com/Intervention/image/releases/tag/3.0.2

No security vulnerability advisories found.
This commit is contained in:
Buster Neece 2023-12-15 07:26:14 -06:00
parent ea399e163b
commit 5a389bb55a
No known key found for this signature in database
10 changed files with 144 additions and 92 deletions

View File

@ -41,7 +41,7 @@
"gettext/php-scanner": "^1.3", "gettext/php-scanner": "^1.3",
"gettext/translator": "^1.1", "gettext/translator": "^1.1",
"guzzlehttp/guzzle": "^7.0", "guzzlehttp/guzzle": "^7.0",
"intervention/image": "^2.6", "intervention/image": "^3",
"james-heinrich/getid3": "v2.0.0-beta6", "james-heinrich/getid3": "v2.0.0-beta6",
"lbuchs/webauthn": "^2.1", "lbuchs/webauthn": "^2.1",
"league/csv": "^9.6", "league/csv": "^9.6",

107
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "7436fe8e498c7769c9f8c9135316a6c7", "content-hash": "937d84fd61dbb782e05b56a7d49ee79e",
"packages": [ "packages": [
{ {
"name": "aws/aws-crt-php", "name": "aws/aws-crt-php",
@ -2645,50 +2645,30 @@
"time": "2023-12-03T20:05:35+00:00" "time": "2023-12-03T20:05:35+00:00"
}, },
{ {
"name": "intervention/image", "name": "intervention/gif",
"version": "2.7.2", "version": "3.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Intervention/image.git", "url": "https://github.com/Intervention/gif.git",
"reference": "04be355f8d6734c826045d02a1079ad658322dad" "reference": "cfececc760862f075a52acf747031bad08c8301b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Intervention/image/zipball/04be355f8d6734c826045d02a1079ad658322dad", "url": "https://api.github.com/repos/Intervention/gif/zipball/cfececc760862f075a52acf747031bad08c8301b",
"reference": "04be355f8d6734c826045d02a1079ad658322dad", "reference": "cfececc760862f075a52acf747031bad08c8301b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-fileinfo": "*", "php": "^8.0"
"guzzlehttp/psr7": "~1.1 || ^2.0",
"php": ">=5.4.0"
}, },
"require-dev": { "require-dev": {
"mockery/mockery": "~0.9.2", "phpstan/phpstan": "^1",
"phpunit/phpunit": "^4.8 || ^5.7 || ^7.5.15" "phpunit/phpunit": "^9"
},
"suggest": {
"ext-gd": "to use GD library based image processing.",
"ext-imagick": "to use Imagick based image processing.",
"intervention/imagecache": "Caching extension for the Intervention Image library"
}, },
"type": "library", "type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.4-dev"
},
"laravel": {
"providers": [
"Intervention\\Image\\ImageServiceProvider"
],
"aliases": {
"Image": "Intervention\\Image\\Facades\\Image"
}
}
},
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Intervention\\Image\\": "src/Intervention/Image" "Intervention\\Gif\\": "src"
} }
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
@ -2702,19 +2682,74 @@
"homepage": "https://intervention.io/" "homepage": "https://intervention.io/"
} }
], ],
"description": "Image handling and manipulation library with support for Laravel integration", "description": "Native PHP GIF Encoder/Decoder",
"homepage": "http://image.intervention.io/", "homepage": "https://github.com/intervention/gif",
"keywords": [
"animation",
"gd",
"gif",
"image"
],
"support": {
"issues": "https://github.com/Intervention/gif/issues",
"source": "https://github.com/Intervention/gif/tree/3.0.0"
},
"time": "2023-11-27T18:54:30+00:00"
},
{
"name": "intervention/image",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/Intervention/image.git",
"reference": "ac9734129478be387c1914f1c2856d623341128c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Intervention/image/zipball/ac9734129478be387c1914f1c2856d623341128c",
"reference": "ac9734129478be387c1914f1c2856d623341128c",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"intervention/gif": "^3",
"php": "^8.1"
},
"require-dev": {
"mockery/mockery": "^1.6",
"phpstan/phpstan": "^1",
"phpunit/phpunit": "^9"
},
"type": "library",
"autoload": {
"psr-4": {
"Intervention\\Image\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Oliver Vogel",
"email": "oliver@intervention.io",
"homepage": "https://intervention.io/"
}
],
"description": "PHP image manipulation",
"homepage": "https://image.intervention.io/",
"keywords": [ "keywords": [
"gd", "gd",
"image", "image",
"imagick", "imagick",
"laravel", "resize",
"thumbnail", "thumbnail",
"watermark" "watermark"
], ],
"support": { "support": {
"issues": "https://github.com/Intervention/image/issues", "issues": "https://github.com/Intervention/image/issues",
"source": "https://github.com/Intervention/image/tree/2.7.2" "source": "https://github.com/Intervention/image/tree/3.0.2"
}, },
"funding": [ "funding": [
{ {
@ -2726,7 +2761,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2022-05-21T17:30:32+00:00" "time": "2023-12-14T13:17:13+00:00"
}, },
{ {
"name": "james-heinrich/getid3", "name": "james-heinrich/getid3",

View File

@ -4,13 +4,18 @@ declare(strict_types=1);
namespace App\Assets; namespace App\Assets;
use Intervention\Image\Interfaces\EncoderInterface;
abstract class AbstractMultiPatternCustomAsset extends AbstractCustomAsset abstract class AbstractMultiPatternCustomAsset extends AbstractCustomAsset
{ {
/**
* @return array<string, array{string, EncoderInterface}>
*/
abstract protected function getPatterns(): array; abstract protected function getPatterns(): array;
protected function getPattern(): string protected function getPattern(): string
{ {
return $this->getPatterns()['default']; return $this->getPatterns()['default'][0];
} }
protected function getPathForPattern(string $pattern): string protected function getPathForPattern(string $pattern): string
@ -22,26 +27,26 @@ abstract class AbstractMultiPatternCustomAsset extends AbstractCustomAsset
public function getPath(): string public function getPath(): string
{ {
$patterns = $this->getPatterns(); $patterns = $this->getPatterns();
foreach ($patterns as $pattern) { foreach ($patterns as [$pattern, $encoder]) {
$path = $this->getPathForPattern($pattern); $path = $this->getPathForPattern($pattern);
if (is_file($path)) { if (is_file($path)) {
return $path; return $path;
} }
} }
return $this->getPathForPattern($patterns['default']); return $this->getPathForPattern($patterns['default'][0]);
} }
public function delete(): void public function delete(): void
{ {
foreach ($this->getPatterns() as $pattern) { foreach ($this->getPatterns() as [$pattern, $encoder]) {
@unlink($this->getPathForPattern($pattern)); @unlink($this->getPathForPattern($pattern));
} }
} }
public function getUrl(): string public function getUrl(): string
{ {
foreach ($this->getPatterns() as $pattern) { foreach ($this->getPatterns() as [$pattern, $encoder]) {
$path = $this->getPathForPattern($pattern); $path = $this->getPathForPattern($pattern);
if (is_file($path)) { if (is_file($path)) {

View File

@ -4,17 +4,28 @@ declare(strict_types=1);
namespace App\Assets; namespace App\Assets;
use Intervention\Image\Constraint; use Intervention\Image\Encoders\JpegEncoder;
use Intervention\Image\Image; use Intervention\Image\Encoders\PngEncoder;
use Intervention\Image\Encoders\WebpEncoder;
use Intervention\Image\Interfaces\ImageInterface;
final class AlbumArtCustomAsset extends AbstractMultiPatternCustomAsset final class AlbumArtCustomAsset extends AbstractMultiPatternCustomAsset
{ {
protected function getPatterns(): array protected function getPatterns(): array
{ {
return [ return [
'default' => 'album_art%s.jpg', 'default' => [
'image/png' => 'album_art%s.png', 'album_art%s.jpg',
'image/webp' => 'album_art%s.webp', new JpegEncoder(90),
],
'image/png' => [
'album_art%s.png',
new PngEncoder(),
],
'image/webp' => [
'album_art%s.webp',
new WebpEncoder(90),
],
]; ];
} }
@ -23,23 +34,19 @@ final class AlbumArtCustomAsset extends AbstractMultiPatternCustomAsset
return $this->environment->getAssetUrl() . '/img/generic_song.jpg'; return $this->environment->getAssetUrl() . '/img/generic_song.jpg';
} }
public function upload(Image $image): void public function upload(ImageInterface $image, string $mimeType): void
{ {
$newImage = clone $image; $newImage = clone $image;
$newImage->resize(1500, 1500, function (Constraint $constraint) { $newImage->resizeDown(1500, 1500);
$constraint->upsize();
});
$this->delete(); $this->delete();
$patterns = $this->getPatterns(); $patterns = $this->getPatterns();
$mimeType = $newImage->mime(); [$pattern, $encoder] = $patterns[$mimeType] ?? $patterns['default'];
$pattern = $patterns[$mimeType] ?? $patterns['default'];
$destPath = $this->getPathForPattern($pattern); $destPath = $this->getPathForPattern($pattern);
$this->ensureDirectoryExists(dirname($destPath)); $this->ensureDirectoryExists(dirname($destPath));
$newImage->save($destPath, 90); $newImage->encode($encoder)->save($destPath);
} }
} }

View File

@ -4,17 +4,28 @@ declare(strict_types=1);
namespace App\Assets; namespace App\Assets;
use Intervention\Image\Constraint; use Intervention\Image\Encoders\JpegEncoder;
use Intervention\Image\Image; use Intervention\Image\Encoders\PngEncoder;
use Intervention\Image\Encoders\WebpEncoder;
use Intervention\Image\Interfaces\ImageInterface;
final class BackgroundCustomAsset extends AbstractMultiPatternCustomAsset final class BackgroundCustomAsset extends AbstractMultiPatternCustomAsset
{ {
protected function getPatterns(): array protected function getPatterns(): array
{ {
return [ return [
'default' => 'background%s.jpg', 'default' => [
'image/png' => 'background%s.png', 'background%s.jpg',
'image/webp' => 'background%s.webp', new JpegEncoder(90),
],
'image/png' => [
'background%s.png',
new PngEncoder(),
],
'image/webp' => [
'background%s.webp',
new WebpEncoder(90),
],
]; ];
} }
@ -23,23 +34,19 @@ final class BackgroundCustomAsset extends AbstractMultiPatternCustomAsset
return $this->environment->getAssetUrl() . '/img/hexbg.png'; return $this->environment->getAssetUrl() . '/img/hexbg.png';
} }
public function upload(Image $image): void public function upload(ImageInterface $image, string $mimeType): void
{ {
$newImage = clone $image; $newImage = clone $image;
$newImage->resize(3264, 2160, function (Constraint $constraint) { $newImage->resizeDown(3264, 2160);
$constraint->upsize();
});
$this->delete(); $this->delete();
$patterns = $this->getPatterns(); $patterns = $this->getPatterns();
$mimeType = $newImage->mime(); [$pattern, $encoder] = $patterns[$mimeType] ?? $patterns['default'];
$pattern = $patterns[$mimeType] ?? $patterns['default'];
$destPath = $this->getPathForPattern($pattern); $destPath = $this->getPathForPattern($pattern);
$this->ensureDirectoryExists(dirname($destPath)); $this->ensureDirectoryExists(dirname($destPath));
$newImage->save($destPath, 90); $newImage->encode($encoder)->save($destPath);
} }
} }

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\Assets; namespace App\Assets;
use Intervention\Image\Image; use Intervention\Image\Interfaces\ImageInterface;
use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Filesystem;
final class BrowserIconCustomAsset extends AbstractCustomAsset final class BrowserIconCustomAsset extends AbstractCustomAsset
@ -38,7 +38,7 @@ final class BrowserIconCustomAsset extends AbstractCustomAsset
return $assetUrl . '/icons/' . $this->environment->getAppEnvironmentEnum()->value . '/original.png'; return $assetUrl . '/icons/' . $this->environment->getAppEnvironmentEnum()->value . '/original.png';
} }
public function upload(Image $image): void public function upload(ImageInterface $image, string $mimeType): void
{ {
$this->delete(); $this->delete();
@ -47,12 +47,12 @@ final class BrowserIconCustomAsset extends AbstractCustomAsset
$newImage = clone $image; $newImage = clone $image;
$newImage->resize(256, 256); $newImage->resize(256, 256);
$newImage->save($uploadsDir . '/original.png'); $newImage->toPng()->save($uploadsDir . '/original.png');
foreach (self::ICON_SIZES as $iconSize) { foreach (self::ICON_SIZES as $iconSize) {
$newImage = clone $image; $newImage = clone $image;
$newImage->resize($iconSize, $iconSize); $newImage->resize($iconSize, $iconSize);
$newImage->save($uploadsDir . '/' . $iconSize . '.png'); $newImage->toPng()->save($uploadsDir . '/' . $iconSize . '.png');
} }
} }

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\Assets; namespace App\Assets;
use Intervention\Image\Image; use Intervention\Image\Interfaces\ImageInterface;
use Psr\Http\Message\UriInterface; use Psr\Http\Message\UriInterface;
interface CustomAssetInterface interface CustomAssetInterface
@ -19,7 +19,7 @@ interface CustomAssetInterface
public function getUri(): UriInterface; public function getUri(): UriInterface;
public function upload(Image $image): void; public function upload(ImageInterface $image, string $mimeType): void;
public function delete(): void; public function delete(): void;
} }

View File

@ -11,6 +11,7 @@ use App\Entity\Api\Status;
use App\Http\Response; use App\Http\Response;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Media\AlbumArt; use App\Media\AlbumArt;
use App\Media\MimeType;
use App\Service\Flow; use App\Service\Flow;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
@ -34,8 +35,10 @@ final class PostCustomAssetAction implements SingleActionInterface
} }
$imageContents = $flowResponse->readAndDeleteUploadedFile(); $imageContents = $flowResponse->readAndDeleteUploadedFile();
$customAsset->upload( $customAsset->upload(
AlbumArt::getImageManager()->make($imageContents) AlbumArt::getImageManager()->read($imageContents),
MimeType::getMimeTypeDetector()->detectMimeTypeFromBuffer($imageContents) ?? 'image/jpeg'
); );
return $response->withJson(Status::success()); return $response->withJson(Status::success());

View File

@ -11,6 +11,7 @@ use App\Entity\Api\Status;
use App\Http\Response; use App\Http\Response;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Media\AlbumArt; use App\Media\AlbumArt;
use App\Media\MimeType;
use App\Service\Flow; use App\Service\Flow;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
@ -38,7 +39,8 @@ final class PostCustomAssetAction implements SingleActionInterface
$imageContents = $flowResponse->readAndDeleteUploadedFile(); $imageContents = $flowResponse->readAndDeleteUploadedFile();
$customAsset->upload( $customAsset->upload(
AlbumArt::getImageManager()->make($imageContents) AlbumArt::getImageManager()->read($imageContents),
MimeType::getMimeTypeDetector()->detectMimeTypeFromBuffer($imageContents) ?? 'image/jpeg'
); );
return $response->withJson(Status::success()); return $response->withJson(Status::success());

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\Media; namespace App\Media;
use Intervention\Image\Constraint; use Intervention\Image\Drivers\Gd\Driver;
use Intervention\Image\ImageManager; use Intervention\Image\ImageManager;
final class AlbumArt final class AlbumArt
@ -17,28 +17,21 @@ final class AlbumArt
int $height = self::IMAGE_WIDTH, int $height = self::IMAGE_WIDTH,
bool $upsize = false, bool $upsize = false,
): string { ): string {
$newArtwork = self::getImageManager()->make($rawArtworkString); $newArtwork = self::getImageManager()->read($rawArtworkString);
$newArtwork->fit(
$width,
$height,
function (Constraint $constraint) use ($upsize) {
if (!$upsize) {
$constraint->upsize();
}
}
);
$newArtwork->encode('jpg'); if ($upsize) {
$newArtwork->cover($width, $height);
} else {
$newArtwork->coverDown($width, $height);
}
return $newArtwork->getEncoded(); return $newArtwork->toJpeg()->toString();
} }
public static function getImageManager(): ImageManager public static function getImageManager(): ImageManager
{ {
return new ImageManager( return new ImageManager(
[ new Driver()
'driver' => 'gd',
]
); );
} }
} }