feat: Allow switching the ImageManager driver (#3195)

This commit is contained in:
Ian Morland 2021-12-12 21:34:10 +00:00 committed by GitHub
parent c718d4d4d6
commit e914deef6a
6 changed files with 81 additions and 12 deletions

View File

@ -28,15 +28,21 @@ class UploadFaviconController extends UploadImageController
*/ */
protected $translator; protected $translator;
/**
* @var ImageManager
*/
protected $imageManager;
/** /**
* @param SettingsRepositoryInterface $settings * @param SettingsRepositoryInterface $settings
* @param Factory $filesystemFactory * @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); parent::__construct($settings, $filesystemFactory);
$this->translator = $translator; $this->translator = $translator;
$this->imageManager = $imageManager;
} }
/** /**
@ -56,9 +62,7 @@ class UploadFaviconController extends UploadImageController
]); ]);
} }
$manager = new ImageManager(); $encodedImage = $this->imageManager->make($file->getStream())->resize(64, 64, function ($constraint) {
$encodedImage = $manager->make($file->getStream())->resize(64, 64, function ($constraint) {
$constraint->aspectRatio(); $constraint->aspectRatio();
$constraint->upsize(); $constraint->upsize();
})->encode('png'); })->encode('png');

View File

@ -9,6 +9,8 @@
namespace Flarum\Api\Controller; namespace Flarum\Api\Controller;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Contracts\Filesystem\Factory;
use Intervention\Image\Image; use Intervention\Image\Image;
use Intervention\Image\ImageManager; use Intervention\Image\ImageManager;
use Psr\Http\Message\UploadedFileInterface; use Psr\Http\Message\UploadedFileInterface;
@ -19,14 +21,24 @@ class UploadLogoController extends UploadImageController
protected $filenamePrefix = 'logo'; protected $filenamePrefix = 'logo';
/**
* @var ImageManager
*/
protected $imageManager;
public function __construct(SettingsRepositoryInterface $settings, Factory $filesystemFactory, ImageManager $imageManager)
{
parent::__construct($settings, $filesystemFactory);
$this->imageManager = $imageManager;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function makeImage(UploadedFileInterface $file): Image protected function makeImage(UploadedFileInterface $file): Image
{ {
$manager = new ImageManager(); $encodedImage = $this->imageManager->make($file->getStream())->heighten(60, function ($constraint) {
$encodedImage = $manager->make($file->getStream())->heighten(60, function ($constraint) {
$constraint->upsize(); $constraint->upsize();
})->encode('png'); })->encode('png');

View File

@ -10,13 +10,19 @@
namespace Flarum\Filesystem; namespace Flarum\Filesystem;
use Flarum\Foundation\AbstractServiceProvider; use Flarum\Foundation\AbstractServiceProvider;
use Flarum\Foundation\Config;
use Flarum\Foundation\Paths; use Flarum\Foundation\Paths;
use Flarum\Http\UrlGenerator; use Flarum\Http\UrlGenerator;
use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Container\Container;
use Illuminate\Filesystem\Filesystem; use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Arr;
use Intervention\Image\ImageManager;
use RuntimeException;
class FilesystemServiceProvider extends AbstractServiceProvider class FilesystemServiceProvider extends AbstractServiceProvider
{ {
protected const INTERVENTION_DRIVERS = ['gd' => 'gd', 'imagick' => 'imagick'];
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -60,5 +66,26 @@ class FilesystemServiceProvider extends AbstractServiceProvider
$container->make('flarum.filesystem.resolved_drivers') $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
]);
});
} }
} }

View File

@ -11,10 +11,12 @@ namespace Flarum\User;
use Flarum\Foundation\AbstractValidator; use Flarum\Foundation\AbstractValidator;
use Flarum\Foundation\ValidationException; use Flarum\Foundation\ValidationException;
use Illuminate\Validation\Factory;
use Intervention\Image\Exception\NotReadableException; use Intervention\Image\Exception\NotReadableException;
use Intervention\Image\ImageManager; use Intervention\Image\ImageManager;
use Psr\Http\Message\UploadedFileInterface; use Psr\Http\Message\UploadedFileInterface;
use Symfony\Component\Mime\MimeTypes; use Symfony\Component\Mime\MimeTypes;
use Symfony\Contracts\Translation\TranslatorInterface;
class AvatarValidator extends AbstractValidator class AvatarValidator extends AbstractValidator
{ {
@ -23,6 +25,18 @@ class AvatarValidator extends AbstractValidator
*/ */
protected $laravelValidator; 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. * Throw an exception if a model is not valid.
* *
@ -73,7 +87,7 @@ class AvatarValidator extends AbstractValidator
} }
try { try {
(new ImageManager)->make($file->getStream()); $this->imageManager->make($file->getStream());
} catch (NotReadableException $_e) { } catch (NotReadableException $_e) {
$this->raise('image'); $this->raise('image');
} }

View File

@ -49,19 +49,25 @@ class RegisterUserHandler
*/ */
private $validator; private $validator;
/**
* @var ImageManager
*/
protected $imageManager;
/** /**
* @param Dispatcher $events * @param Dispatcher $events
* @param SettingsRepositoryInterface $settings * @param SettingsRepositoryInterface $settings
* @param UserValidator $validator * @param UserValidator $validator
* @param AvatarUploader $avatarUploader * @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->events = $events;
$this->settings = $settings; $this->settings = $settings;
$this->userValidator = $userValidator; $this->userValidator = $userValidator;
$this->avatarUploader = $avatarUploader; $this->avatarUploader = $avatarUploader;
$this->validator = $validator; $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); 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); $this->avatarUploader->upload($user, $image);
} }

View File

@ -36,18 +36,24 @@ class UploadAvatarHandler
*/ */
protected $validator; protected $validator;
/**
* @var ImageManager
*/
protected $imageManager;
/** /**
* @param Dispatcher $events * @param Dispatcher $events
* @param UserRepository $users * @param UserRepository $users
* @param AvatarUploader $uploader * @param AvatarUploader $uploader
* @param AvatarValidator $validator * @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->events = $events;
$this->users = $users; $this->users = $users;
$this->uploader = $uploader; $this->uploader = $uploader;
$this->validator = $validator; $this->validator = $validator;
$this->imageManager = $imageManager;
} }
/** /**
@ -68,7 +74,7 @@ class UploadAvatarHandler
$this->validator->assertValid(['avatar' => $command->file]); $this->validator->assertValid(['avatar' => $command->file]);
$image = (new ImageManager)->make($command->file->getStream()); $image = $this->imageManager->make($command->file->getStream());
$this->events->dispatch( $this->events->dispatch(
new AvatarSaving($user, $actor, $image) new AvatarSaving($user, $actor, $image)