Skip to content

Commit

Permalink
Merge pull request #715 from cedricziel/flysystemResolver
Browse files Browse the repository at this point in the history
Add Flysystem resolver
  • Loading branch information
lsmith77 authored Jul 12, 2016
2 parents 0136c13 + 8522ed7 commit 94aca9c
Show file tree
Hide file tree
Showing 10 changed files with 718 additions and 7 deletions.
4 changes: 2 additions & 2 deletions .scrutinizer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ before_commands:
# - "composer install --prefer-source --dev"

filter:
excluded_paths: [vendor/*, tests/*, bin/*]
excluded_paths: [vendor/*, Tests/*, bin/*]

tools:
php_sim: true
Expand All @@ -24,5 +24,5 @@ tools:
excluded_dirs: [vendor]
php_pdepend:
enabled: true
excluded_dirs: [vendor, tests, bin]
excluded_dirs: [vendor, Tests, bin]
# php_hhvm: true
52 changes: 52 additions & 0 deletions DependencyInjection/Factory/Resolver/FlysystemResolverFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Liip\ImagineBundle\DependencyInjection\Factory\Resolver;

use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Reference;

class FlysystemResolverFactory implements ResolverFactoryInterface
{
/**
* {@inheritdoc}
*/
public function create(ContainerBuilder $container, $resolverName, array $config)
{
$resolverDefinition = new DefinitionDecorator('liip_imagine.cache.resolver.prototype.flysystem');
$resolverDefinition->replaceArgument(0, new Reference($config['filesystem_service']));
$resolverDefinition->replaceArgument(2, $config['root_url']);
$resolverDefinition->replaceArgument(3, $config['cache_prefix']);
$resolverDefinition->addTag('liip_imagine.cache.resolver', array(
'resolver' => $resolverName,
));
$resolverId = 'liip_imagine.cache.resolver.'.$resolverName;

$container->setDefinition($resolverId, $resolverDefinition);

return $resolverId;
}

/**
* {@inheritdoc}
*/
public function getName()
{
return 'flysystem';
}

/**
* {@inheritdoc}
*/
public function addConfiguration(ArrayNodeDefinition $builder)
{
$builder
->children()
->scalarNode('filesystem_service')->isRequired()->cannotBeEmpty()->end()
->scalarNode('cache_prefix')->defaultValue(null)->end()
->scalarNode('root_url')->isRequired()->cannotBeEmpty()->end()
->end()
;
}
}
152 changes: 152 additions & 0 deletions Imagine/Cache/Resolver/FlysystemResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
<?php

namespace Liip\ImagineBundle\Imagine\Cache\Resolver;

use League\Flysystem\Filesystem;
use Liip\ImagineBundle\Binary\BinaryInterface;
use Liip\ImagineBundle\Exception\Imagine\Cache\Resolver\NotResolvableException;
use Symfony\Component\Routing\RequestContext;

class FlysystemResolver implements ResolverInterface
{
/**
* @var Filesystem
*/
protected $flysystem;

/**
* @var RequestContext
*/
protected $requestContext;

/**
* @var string
*/
protected $webRoot;

/**
* @var string
*/
protected $cachePrefix;

/**
* @var string
*/
protected $cacheRoot;

/**
* FlysystemResolver constructor.
*
* @param Filesystem $flysystem
* @param RequestContext $requestContext
* @param $rootUrl
* @param string $cachePrefix
*/
public function __construct(
Filesystem $flysystem,
RequestContext $requestContext,
$rootUrl,
$cachePrefix = 'media/cache'
) {
$this->flysystem = $flysystem;
$this->requestContext = $requestContext;

$this->webRoot = rtrim($rootUrl, '/');
$this->cachePrefix = ltrim(str_replace('//', '/', $cachePrefix), '/');
$this->cacheRoot = $this->cachePrefix;
}

/**
* Checks whether the given path is stored within this Resolver.
*
* @param string $path
* @param string $filter
*
* @return bool
*/
public function isStored($path, $filter)
{
return $this->flysystem->has($this->getFilePath($path, $filter));
}

/**
* {@inheritdoc}
*/
protected function getFilePath($path, $filter)
{
return $this->getFileUrl($path, $filter);
}

/**
* {@inheritdoc}
*/
protected function getFileUrl($path, $filter)
{
// crude way of sanitizing URL scheme ("protocol") part
$path = str_replace('://', '---', $path);

return $this->cachePrefix.'/'.$filter.'/'.ltrim($path, '/');
}

/**
* Resolves filtered path for rendering in the browser.
*
* @param string $path The path where the original file is expected to be.
* @param string $filter The name of the imagine filter in effect.
*
* @return string The absolute URL of the cached image.
*
* @throws NotResolvableException
*/
public function resolve($path, $filter)
{
return sprintf(
'%s/%s',
$this->webRoot,
$this->getFileUrl($path, $filter)
);
}

/**
* Stores the content of the given binary.
*
* @param BinaryInterface $binary The image binary to store.
* @param string $path The path where the original file is expected to be.
* @param string $filter The name of the imagine filter in effect.
*/
public function store(BinaryInterface $binary, $path, $filter)
{
$this->flysystem->put(
$this->getFilePath($path, $filter),
$binary->getContent()
);
}

/**
* @param string[] $paths The paths where the original files are expected to be.
* @param string[] $filters The imagine filters in effect.
*/
public function remove(array $paths, array $filters)
{
if (empty($paths) && empty($filters)) {
return;
}

if (empty($paths)) {
foreach ($filters as $filter) {
$filterCacheDir = $this->cacheRoot.'/'.$filter;
$this->flysystem->deleteDir($filterCacheDir);
}

return;
}

foreach ($paths as $path) {
foreach ($filters as $filter) {
if ($this->flysystem->has($this->getFilePath($path, $filter))) {
$this->flysystem->delete($this->getFilePath($path, $filter));
}
}
}
}
}
2 changes: 2 additions & 0 deletions LiipImagineBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Liip\ImagineBundle\DependencyInjection\Factory\Loader\StreamLoaderFactory;
use Liip\ImagineBundle\DependencyInjection\Factory\Loader\FlysystemLoaderFactory;
use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\AwsS3ResolverFactory;
use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\FlysystemResolverFactory;
use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\WebPathResolverFactory;
use Liip\ImagineBundle\DependencyInjection\LiipImagineExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand All @@ -34,6 +35,7 @@ public function build(ContainerBuilder $container)

$extension->addResolverFactory(new WebPathResolverFactory());
$extension->addResolverFactory(new AwsS3ResolverFactory());
$extension->addResolverFactory(new FlysystemResolverFactory());

$extension->addLoaderFactory(new StreamLoaderFactory());
$extension->addLoaderFactory(new FileSystemLoaderFactory());
Expand Down
10 changes: 9 additions & 1 deletion Resources/config/imagine.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
<parameter key="liip_imagine.cache.resolver.no_cache_web_path.class">Liip\ImagineBundle\Imagine\Cache\Resolver\NoCacheWebPathResolver</parameter>
<parameter key="liip_imagine.cache.resolver.aws_s3.class">Liip\ImagineBundle\Imagine\Cache\Resolver\AwsS3Resolver</parameter>
<parameter key="liip_imagine.cache.resolver.cache.class">Liip\ImagineBundle\Imagine\Cache\Resolver\CacheResolver</parameter>
<parameter key="liip_imagine.cache.resolver.flysystem.class">Liip\ImagineBundle\Imagine\Cache\Resolver\FlysystemResolver</parameter>
<parameter key="liip_imagine.cache.resolver.proxy.class">Liip\ImagineBundle\Imagine\Cache\Resolver\ProxyResolver</parameter>

<!-- Form types -->
Expand Down Expand Up @@ -214,7 +215,7 @@
<argument><!-- will be injected by StreamLoaderFactory --></argument>
<argument><!-- will be injected by StreamLoaderFactory --></argument>
</service>

<service id="liip_imagine.binary.loader.prototype.flysystem" class="%liip_imagine.binary.loader.flysystem.class%" abstract="true">
<argument type="service" id="liip_imagine.extension_guesser" />
<argument><!-- will be injected by FlysystemLoaderFactory --></argument>
Expand Down Expand Up @@ -242,6 +243,13 @@
<argument><!-- will be injected by a ResolverFactory --></argument>
</service>

<service id="liip_imagine.cache.resolver.prototype.flysystem" class="%liip_imagine.cache.resolver.flysystem.class%" public="true" abstract="true">
<argument><!-- will be injected by a ResolverFactory --></argument>
<argument type="service" id="router.request_context" />
<argument><!-- will be injected by a ResolverFactory --></argument>
<argument><!-- will be injected by a ResolverFactory --></argument>
</service>

<service id="liip_imagine.cache.resolver.prototype.proxy" class="%liip_imagine.cache.resolver.proxy.class%" public="true" abstract="true">
<argument><!-- will be injected by AwsS3ResolverFactory --></argument>
<argument><!-- will be injected by AwsS3ResolverFactory --></argument>
Expand Down
63 changes: 63 additions & 0 deletions Resources/doc/cache-resolver/flysystem.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
FlysystemResolver
=================

This resolver lets you load images onto `Flysystem`_ filesystem abstraction layer,
which can be used in Symfony projects by installing, for example, `OneupFlysystemBundle`_.

Value of ``filesystem_service`` property must be a service,
which returns an instance of League\\Flysystem\\Filesystem.

For implementation using `OneupFlysystemBundle`_ look below.

Create resolver
---------------

.. code-block:: yaml
liip_imagine:
resolvers:
profile_photos:
flysystem:
filesystem_service: oneup_flysystem.profile_photos_filesystem
root_url: http://images.example.com
cache_prefix: media/cache
oneup_flysystem:
adapters:
profile_photos:
local:
directory: "path/to/profile/photos"
filesystems:
profile_photos:
adapter: profile_photos
There are several configuration options available:

* ``root_url`` - must be a valid url to the target system the flysystem adapter
points to. This is used to determine how the url should be generated upon request.
Default value: ``null``
* ``cache_prefix`` - this is used for the image path generation. This will be the
prefix inside the given Flysystem.
Default value: ``media/cache``

Usage
-----

.. code-block:: yaml
liip_imagine:
cache: profile_photos
Usage on a specific filter
--------------------------

.. code-block:: yaml
liip_imagine:
filter_sets:
cache: ~
my_thumb:
cache: profile_photos
quality: 75
filters:
thumbnail: { size: [120, 90], mode: outbound }
Loading

0 comments on commit 94aca9c

Please sign in to comment.