Skip to content

Commit

Permalink
Merge pull request #922 from rpkamp/image-service
Browse files Browse the repository at this point in the history
Introduce FilterService as abstraction for creating images
  • Loading branch information
makasim committed Nov 27, 2017
2 parents 057aa61 + 270c250 commit b272ae3
Show file tree
Hide file tree
Showing 13 changed files with 438 additions and 321 deletions.
37 changes: 9 additions & 28 deletions Async/ResolveCacheProcessor.php
Expand Up @@ -19,47 +19,38 @@
use Interop\Queue\PsrMessage;
use Interop\Queue\PsrProcessor;
use Enqueue\Util\JSON;
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Liip\ImagineBundle\Imagine\Data\DataManager;
use Liip\ImagineBundle\Imagine\Filter\FilterManager;
use Liip\ImagineBundle\Service\FilterService;

final class ResolveCacheProcessor implements PsrProcessor, CommandSubscriberInterface, QueueSubscriberInterface
{
/**
* @var CacheManager
*/
private $cacheManager;

/**
* @var FilterManager
*/
private $filterManager;

/**
* @var DataManager
* @var FilterService
*/
private $dataManager;
private $filterService;

/**
* @var ProducerInterface
*/
private $producer;

/**
* @param CacheManager $cacheManager
* @param FilterManager $filterManager
* @param DataManager $dataManager
* @param FilterService $filterService
* @param ProducerInterface $producer
*/
public function __construct(
CacheManager $cacheManager,
FilterManager $filterManager,
DataManager $dataManager,
FilterService $filterService,
ProducerInterface $producer
) {
$this->cacheManager = $cacheManager;
$this->filterManager = $filterManager;
$this->dataManager = $dataManager;
$this->filterService = $filterService;
$this->producer = $producer;
}

Expand All @@ -75,20 +66,11 @@ public function process(PsrMessage $psrMessage, PsrContext $psrContext)
$path = $message->getPath();
$results = [];
foreach ($filters as $filter) {
if ($this->cacheManager->isStored($path, $filter) && $message->isForce()) {
$this->cacheManager->remove($path, $filter);
if ($message->isForce()) {
$this->filterService->bustCache($path, $filter);
}

if (false == $this->cacheManager->isStored($path, $filter)) {
$binary = $this->dataManager->find($filter, $path);
$this->cacheManager->store(
$this->filterManager->applyFilter($binary, $filter),
$path,
$filter
);
}

$results[$filter] = $this->cacheManager->resolve($path, $filter);
$results[$filter] = $this->filterService->getUrlOfFilteredImage($path, $filter);
}

$this->producer->sendEvent(Topics::CACHE_RESOLVED, new CacheResolved($path, $results));
Expand All @@ -97,7 +79,6 @@ public function process(PsrMessage $psrMessage, PsrContext $psrContext)
'status' => true,
'results' => $results,
])));

} catch (\Exception $e) {
return Result::reply($psrContext->createMessage(JSON::encode([
'status' => false,
Expand Down
24 changes: 6 additions & 18 deletions Command/ResolveCacheCommand.php
Expand Up @@ -11,9 +11,8 @@

namespace Liip\ImagineBundle\Command;

use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Liip\ImagineBundle\Imagine\Data\DataManager;
use Liip\ImagineBundle\Imagine\Filter\FilterManager;
use Liip\ImagineBundle\Service\FilterService;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -63,30 +62,19 @@ protected function execute(InputInterface $input, OutputInterface $output)
$paths = $input->getArgument('paths');
$filters = $input->getOption('filters');

/* @var FilterManager filterManager */
/* @var FilterManager $filterManager */
$filterManager = $this->getContainer()->get('liip_imagine.filter.manager');
/* @var CacheManager cacheManager */
$cacheManager = $this->getContainer()->get('liip_imagine.cache.manager');
/* @var DataManager dataManager */
$dataManager = $this->getContainer()->get('liip_imagine.data.manager');

/* @var FilterService $filterService */
$filterService = $this->getContainer()->get('liip_imagine.service.filter');

if (empty($filters)) {
$filters = array_keys($filterManager->getFilterConfiguration()->all());
}

foreach ($paths as $path) {
foreach ($filters as $filter) {
if (!$cacheManager->isStored($path, $filter)) {
$binary = $dataManager->find($filter, $path);

$cacheManager->store(
$filterManager->applyFilter($binary, $filter),
$path,
$filter
);
}

$output->writeln($cacheManager->resolve($path, $filter));
$output->writeln($filterService->getUrlOfFilteredImage($path, $filter));
}
}
}
Expand Down
151 changes: 49 additions & 102 deletions Controller/ImagineController.php
Expand Up @@ -14,11 +14,9 @@
use Imagine\Exception\RuntimeException;
use Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException;
use Liip\ImagineBundle\Exception\Imagine\Filter\NonExistingFilterException;
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Liip\ImagineBundle\Imagine\Cache\SignerInterface;
use Liip\ImagineBundle\Imagine\Data\DataManager;
use Liip\ImagineBundle\Imagine\Filter\FilterManager;
use Psr\Log\LoggerInterface;
use Liip\ImagineBundle\Service\FilterService;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
Expand All @@ -27,165 +25,114 @@
class ImagineController
{
/**
* @var DataManager
*/
protected $dataManager;

/**
* @var FilterManager
* @var FilterService
*/
protected $filterManager;
private $filterService;

/**
* @var CacheManager
* @var DataManager
*/
protected $cacheManager;
private $dataManager;

/**
* @var SignerInterface
*/
protected $signer;

/**
* @var LoggerInterface
*/
protected $logger;
private $signer;

/**
* @param FilterService $filterService
* @param DataManager $dataManager
* @param FilterManager $filterManager
* @param CacheManager $cacheManager
* @param SignerInterface $signer
*/
public function __construct(
DataManager $dataManager,
FilterManager $filterManager,
CacheManager $cacheManager,
SignerInterface $signer,
LoggerInterface $logger = null
) {
public function __construct(FilterService $filterService, DataManager $dataManager, SignerInterface $signer)
{
$this->filterService = $filterService;
$this->dataManager = $dataManager;
$this->filterManager = $filterManager;
$this->cacheManager = $cacheManager;
$this->signer = $signer;
$this->logger = $logger;
}

/**
* This action applies a given filter to a given image, optionally saves the image and outputs it to the browser at the same time.
* This action applies a given filter to a given image, saves the image and redirects the browser to the stored
* image.
*
* The resulting image is cached so subsequent requests will redirect to the cached image instead applying the
* filter and storing the image again.
*
* @param Request $request
* @param string $path
* @param string $filter
*
* @throws \RuntimeException
* @throws BadRequestHttpException
* @throws RuntimeException
* @throws NotFoundHttpException
*
* @return RedirectResponse
*/
public function filterAction(Request $request, $path, $filter)
{
// decoding special characters and whitespaces from path obtained from url
$path = urldecode($path);
$resolver = $request->get('resolver');

try {
if (!$this->cacheManager->isStored($path, $filter, $resolver)) {
try {
$binary = $this->dataManager->find($filter, $path);
} catch (NotLoadableException $e) {
if ($defaultImageUrl = $this->dataManager->getDefaultImageUrl($filter)) {
return new RedirectResponse($defaultImageUrl);
}

throw new NotFoundHttpException('Source image could not be found', $e);
}

$this->cacheManager->store(
$this->filterManager->applyFilter($binary, $filter),
$path,
$filter,
$resolver
);
return new RedirectResponse($this->filterService->getUrlOfFilteredImage($path, $filter, $resolver), 301);
} catch (NotLoadableException $e) {
if ($this->dataManager->getDefaultImageUrl($filter) !== null) {
return new RedirectResponse($this->dataManager->getDefaultImageUrl($filter));
}

return new RedirectResponse($this->cacheManager->resolve($path, $filter, $resolver), 301);
throw new NotFoundHttpException(sprintf('Source image for path "%s" could not be found', $path));
} catch (NonExistingFilterException $e) {
$message = sprintf('Could not locate filter "%s" for path "%s". Message was "%s"', $filter, $path, $e->getMessage());

if (null !== $this->logger) {
$this->logger->debug($message);
}

throw new NotFoundHttpException($message, $e);
throw new NotFoundHttpException(sprintf('Requested non-existing filter "%s"', $filter));
} catch (RuntimeException $e) {
throw new \RuntimeException(sprintf('Unable to create image for path "%s" and filter "%s". Message was "%s"', $path, $filter, $e->getMessage()), 0, $e);
}
}

/**
* This action applies a given filter to a given image, optionally saves the image and outputs it to the browser at the same time.
* This action applies a given filter -merged with additional runtime filters- to a given image, saves the image and
* redirects the browser to the stored image.
*
* The resulting image is cached so subsequent requests will redirect to the cached image instead applying the
* filter and storing the image again.
*
* @param Request $request
* @param string $hash
* @param string $path
* @param string $filter
*
* @throws \RuntimeException
* @throws RuntimeException
* @throws BadRequestHttpException
* @throws NotFoundHttpException
*
* @return RedirectResponse
*/
public function filterRuntimeAction(Request $request, $hash, $path, $filter)
{
$resolver = $request->get('resolver');
$runtimeConfig = $request->query->get('filters', []);

try {
$filters = $request->query->get('filters', []);

if (!is_array($filters)) {
throw new NotFoundHttpException(sprintf('Filters must be an array. Value was "%s"', $filters));
}

if (true !== $this->signer->check($hash, $path, $filters)) {
throw new BadRequestHttpException(sprintf(
'Signed url does not pass the sign check for path "%s" and filter "%s" and runtime config %s',
$path,
$filter,
json_encode($filters)
));
}

try {
$binary = $this->dataManager->find($filter, $path);
} catch (NotLoadableException $e) {
if ($defaultImageUrl = $this->dataManager->getDefaultImageUrl($filter)) {
return new RedirectResponse($defaultImageUrl);
}

throw new NotFoundHttpException(sprintf('Source image could not be found for path "%s" and filter "%s"', $path, $filter), $e);
}

$rcPath = $this->cacheManager->getRuntimePath($path, $filters);
if (!is_array($runtimeConfig)) {
throw new NotFoundHttpException(sprintf('Filters must be an array. Value was "%s"', $runtimeConfig));
}

$this->cacheManager->store(
$this->filterManager->applyFilter($binary, $filter, [
'filters' => $filters,
]),
$rcPath,
if (true !== $this->signer->check($hash, $path, $runtimeConfig)) {
throw new BadRequestHttpException(sprintf(
'Signed url does not pass the sign check for path "%s" and filter "%s" and runtime config %s',
$path,
$filter,
$resolver
);

return new RedirectResponse($this->cacheManager->resolve($rcPath, $filter, $resolver), 301);
} catch (NonExistingFilterException $e) {
$message = sprintf('Could not locate filter "%s" for path "%s". Message was "%s"', $filter, $hash.'/'.$path, $e->getMessage());
json_encode($runtimeConfig)
));
}

if (null !== $this->logger) {
$this->logger->debug($message);
try {
return new RedirectResponse($this->filterService->getUrlOfFilteredImageWithRuntimeFilters($path, $filter, $runtimeConfig, $resolver), 301);
} catch (NotLoadableException $e) {
if ($this->dataManager->getDefaultImageUrl($filter) !== null) {
return new RedirectResponse($this->dataManager->getDefaultImageUrl($filter));
}

throw new NotFoundHttpException($message, $e);
throw new NotFoundHttpException(sprintf('Source image for path "%s" could not be found', $path));
} catch (NonExistingFilterException $e) {
throw new NotFoundHttpException(sprintf('Requested non-existing filter "%s"', $filter));
} catch (RuntimeException $e) {
throw new \RuntimeException(sprintf('Unable to create image for path "%s" and filter "%s". Message was "%s"', $hash.'/'.$path, $filter, $e->getMessage()), 0, $e);
}
Expand Down
2 changes: 1 addition & 1 deletion Imagine/Data/DataManager.php
Expand Up @@ -149,7 +149,7 @@ public function find($filter, $path)
*
* @param string $filter
*
* @return string
* @return string|null
*/
public function getDefaultImageUrl($filter)
{
Expand Down

0 comments on commit b272ae3

Please sign in to comment.