From e914deef6ab4f736d4f6fdbd62dcf06e489ffc25 Mon Sep 17 00:00:00 2001 From: Ian Morland <16573496+imorland@users.noreply.github.com> Date: Sun, 12 Dec 2021 21:34:10 +0000 Subject: [PATCH] feat: Allow switching the ImageManager driver (#3195) --- .../Controller/UploadFaviconController.php | 12 ++++++--- .../Api/Controller/UploadLogoController.php | 18 ++++++++++--- .../Filesystem/FilesystemServiceProvider.php | 27 +++++++++++++++++++ framework/core/src/User/AvatarValidator.php | 16 ++++++++++- .../src/User/Command/RegisterUserHandler.php | 10 +++++-- .../src/User/Command/UploadAvatarHandler.php | 10 +++++-- 6 files changed, 81 insertions(+), 12 deletions(-) diff --git a/framework/core/src/Api/Controller/UploadFaviconController.php b/framework/core/src/Api/Controller/UploadFaviconController.php index 4469d82f6..525b39680 100644 --- a/framework/core/src/Api/Controller/UploadFaviconController.php +++ b/framework/core/src/Api/Controller/UploadFaviconController.php @@ -28,15 +28,21 @@ class UploadFaviconController extends UploadImageController */ protected $translator; + /** + * @var ImageManager + */ + protected $imageManager; + /** * @param SettingsRepositoryInterface $settings * @param Factory $filesystemFactory */ - public function __construct(SettingsRepositoryInterface $settings, Factory $filesystemFactory, TranslatorInterface $translator) + public function __construct(SettingsRepositoryInterface $settings, Factory $filesystemFactory, TranslatorInterface $translator, ImageManager $imageManager) { parent::__construct($settings, $filesystemFactory); $this->translator = $translator; + $this->imageManager = $imageManager; } /** @@ -56,9 +62,7 @@ class UploadFaviconController extends UploadImageController ]); } - $manager = new ImageManager(); - - $encodedImage = $manager->make($file->getStream())->resize(64, 64, function ($constraint) { + $encodedImage = $this->imageManager->make($file->getStream())->resize(64, 64, function ($constraint) { $constraint->aspectRatio(); $constraint->upsize(); })->encode('png'); diff --git a/framework/core/src/Api/Controller/UploadLogoController.php b/framework/core/src/Api/Controller/UploadLogoController.php index ba760b527..8da214d12 100644 --- a/framework/core/src/Api/Controller/UploadLogoController.php +++ b/framework/core/src/Api/Controller/UploadLogoController.php @@ -9,6 +9,8 @@ namespace Flarum\Api\Controller; +use Flarum\Settings\SettingsRepositoryInterface; +use Illuminate\Contracts\Filesystem\Factory; use Intervention\Image\Image; use Intervention\Image\ImageManager; use Psr\Http\Message\UploadedFileInterface; @@ -19,14 +21,24 @@ class UploadLogoController extends UploadImageController protected $filenamePrefix = 'logo'; + /** + * @var ImageManager + */ + protected $imageManager; + + public function __construct(SettingsRepositoryInterface $settings, Factory $filesystemFactory, ImageManager $imageManager) + { + parent::__construct($settings, $filesystemFactory); + + $this->imageManager = $imageManager; + } + /** * {@inheritdoc} */ protected function makeImage(UploadedFileInterface $file): Image { - $manager = new ImageManager(); - - $encodedImage = $manager->make($file->getStream())->heighten(60, function ($constraint) { + $encodedImage = $this->imageManager->make($file->getStream())->heighten(60, function ($constraint) { $constraint->upsize(); })->encode('png'); diff --git a/framework/core/src/Filesystem/FilesystemServiceProvider.php b/framework/core/src/Filesystem/FilesystemServiceProvider.php index 011204e28..0c3d2cb5b 100644 --- a/framework/core/src/Filesystem/FilesystemServiceProvider.php +++ b/framework/core/src/Filesystem/FilesystemServiceProvider.php @@ -10,13 +10,19 @@ namespace Flarum\Filesystem; use Flarum\Foundation\AbstractServiceProvider; +use Flarum\Foundation\Config; use Flarum\Foundation\Paths; use Flarum\Http\UrlGenerator; use Illuminate\Contracts\Container\Container; use Illuminate\Filesystem\Filesystem; +use Illuminate\Support\Arr; +use Intervention\Image\ImageManager; +use RuntimeException; class FilesystemServiceProvider extends AbstractServiceProvider { + protected const INTERVENTION_DRIVERS = ['gd' => 'gd', 'imagick' => 'imagick']; + /** * {@inheritdoc} */ @@ -60,5 +66,26 @@ class FilesystemServiceProvider extends AbstractServiceProvider $container->make('flarum.filesystem.resolved_drivers') ); }); + + $this->container->singleton(ImageManager::class, function (Container $container) { + /** @var Config $config */ + $config = $this->container->make(Config::class); + + $intervention = $config->offsetGet('intervention'); + $driver = Arr::get($intervention, 'driver', self::INTERVENTION_DRIVERS['gd']); + + // Check that the imagick library is actually available, else default back to gd. + if ($driver === self::INTERVENTION_DRIVERS['imagick'] && ! extension_loaded(self::INTERVENTION_DRIVERS['imagick'])) { + $driver = self::INTERVENTION_DRIVERS['gd']; + } + + if (! Arr::has(self::INTERVENTION_DRIVERS, $driver)) { + throw new RuntimeException("intervention/image: $driver is not valid"); + } + + return new ImageManager([ + 'driver' => $driver + ]); + }); } } diff --git a/framework/core/src/User/AvatarValidator.php b/framework/core/src/User/AvatarValidator.php index 5a0a1cad2..4bb55284d 100644 --- a/framework/core/src/User/AvatarValidator.php +++ b/framework/core/src/User/AvatarValidator.php @@ -11,10 +11,12 @@ namespace Flarum\User; use Flarum\Foundation\AbstractValidator; use Flarum\Foundation\ValidationException; +use Illuminate\Validation\Factory; use Intervention\Image\Exception\NotReadableException; use Intervention\Image\ImageManager; use Psr\Http\Message\UploadedFileInterface; use Symfony\Component\Mime\MimeTypes; +use Symfony\Contracts\Translation\TranslatorInterface; class AvatarValidator extends AbstractValidator { @@ -23,6 +25,18 @@ class AvatarValidator extends AbstractValidator */ protected $laravelValidator; + /** + * @var ImageManager + */ + protected $imageManager; + + public function __construct(Factory $validator, TranslatorInterface $translator, ImageManager $imageManager) + { + parent::__construct($validator, $translator); + + $this->imageManager = $imageManager; + } + /** * Throw an exception if a model is not valid. * @@ -73,7 +87,7 @@ class AvatarValidator extends AbstractValidator } try { - (new ImageManager)->make($file->getStream()); + $this->imageManager->make($file->getStream()); } catch (NotReadableException $_e) { $this->raise('image'); } diff --git a/framework/core/src/User/Command/RegisterUserHandler.php b/framework/core/src/User/Command/RegisterUserHandler.php index 4c3bef509..a9c9a872b 100644 --- a/framework/core/src/User/Command/RegisterUserHandler.php +++ b/framework/core/src/User/Command/RegisterUserHandler.php @@ -49,19 +49,25 @@ class RegisterUserHandler */ private $validator; + /** + * @var ImageManager + */ + protected $imageManager; + /** * @param Dispatcher $events * @param SettingsRepositoryInterface $settings * @param UserValidator $validator * @param AvatarUploader $avatarUploader */ - public function __construct(Dispatcher $events, SettingsRepositoryInterface $settings, UserValidator $userValidator, AvatarUploader $avatarUploader, Factory $validator) + public function __construct(Dispatcher $events, SettingsRepositoryInterface $settings, UserValidator $userValidator, AvatarUploader $avatarUploader, Factory $validator, ImageManager $imageManager) { $this->events = $events; $this->settings = $settings; $this->userValidator = $userValidator; $this->avatarUploader = $avatarUploader; $this->validator = $validator; + $this->imageManager = $imageManager; } /** @@ -160,7 +166,7 @@ class RegisterUserHandler throw new InvalidArgumentException("Provided avatar URL must have scheme http or https. Scheme provided was $scheme.", 503); } - $image = (new ImageManager)->make($url); + $image = $this->imageManager->make($url); $this->avatarUploader->upload($user, $image); } diff --git a/framework/core/src/User/Command/UploadAvatarHandler.php b/framework/core/src/User/Command/UploadAvatarHandler.php index f548498c6..45d334177 100644 --- a/framework/core/src/User/Command/UploadAvatarHandler.php +++ b/framework/core/src/User/Command/UploadAvatarHandler.php @@ -36,18 +36,24 @@ class UploadAvatarHandler */ protected $validator; + /** + * @var ImageManager + */ + protected $imageManager; + /** * @param Dispatcher $events * @param UserRepository $users * @param AvatarUploader $uploader * @param AvatarValidator $validator */ - public function __construct(Dispatcher $events, UserRepository $users, AvatarUploader $uploader, AvatarValidator $validator) + public function __construct(Dispatcher $events, UserRepository $users, AvatarUploader $uploader, AvatarValidator $validator, ImageManager $imageManager) { $this->events = $events; $this->users = $users; $this->uploader = $uploader; $this->validator = $validator; + $this->imageManager = $imageManager; } /** @@ -68,7 +74,7 @@ class UploadAvatarHandler $this->validator->assertValid(['avatar' => $command->file]); - $image = (new ImageManager)->make($command->file->getStream()); + $image = $this->imageManager->make($command->file->getStream()); $this->events->dispatch( new AvatarSaving($user, $actor, $image)