Skip to content

Commit

Permalink
Merge pull request #674 from graundas/master
Browse files Browse the repository at this point in the history
Flysystem support added.
  • Loading branch information
makasim committed Jan 14, 2016
2 parents bf3f931 + 4dfc6b6 commit 22d625e
Show file tree
Hide file tree
Showing 11 changed files with 350 additions and 1 deletion.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ before_install:
- sh -c 'if [ "${TRAVIS_PHP_VERSION}" != "hhvm" ]; then echo "memory_limit = -1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; fi;'
- sh -c 'if [ "${TRAVIS_PHP_VERSION}" != "hhvm" && "${TRAVIS_PHP_VERSION}" != "7.0" ]; then yes "" | pecl -q install -f mongo; fi;'
- sh -c 'if [ "${TRAVIS_PHP_VERSION}" != "hhvm" && "${TRAVIS_PHP_VERSION}" != "7.0" ]; then composer require --dev doctrine/mongodb-odm:~1.0 --no-update; fi;'
- sh -c 'if [ "${TRAVIS_PHP_VERSION}" != "hhvm" && "${TRAVIS_PHP_VERSION}" >= "5.4" ]; then composer require --dev league/flysystem:~1.0 --no-update; fi;'
- composer self-update
- if [ "$SYMFONY_VERSION" != "" ]; then composer require "symfony/symfony:${SYMFONY_VERSION}" --no-update; fi;

Expand Down
47 changes: 47 additions & 0 deletions Binary/Loader/FlysystemLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace Liip\ImagineBundle\Binary\Loader;

use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesserInterface;
use Liip\ImagineBundle\Model\Binary;
use Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException;
use League\Flysystem\FilesystemInterface;

class FlysystemLoader implements LoaderInterface
{
/**
* @var FilesystemInterface
*/
protected $filesystem;

/**
* @var ExtensionGuesserInterface
*/
protected $extensionGuesser;

public function __construct(
ExtensionGuesserInterface $extensionGuesser,
FilesystemInterface $filesystem)
{
$this->extensionGuesser = $extensionGuesser;
$this->filesystem = $filesystem;
}

/**
* {@inheritdoc}
*/
public function find($path)
{
if ($this->filesystem->has($path) === false) {
throw new NotLoadableException(sprintf('Source image "%s" not found.', $path));
}

$mimeType = $this->filesystem->getMimetype($path);

return new Binary(
$this->filesystem->read($path),
$mimeType,
$this->extensionGuesser->guess($mimeType)
);
}
}
48 changes: 48 additions & 0 deletions DependencyInjection/Factory/Loader/FlysystemLoaderFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace Liip\ImagineBundle\DependencyInjection\Factory\Loader;

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

class FlysystemLoaderFactory implements LoaderFactoryInterface
{
/**
* {@inheritdoc}
*/
public function create(ContainerBuilder $container, $loaderName, array $config)
{
$loaderDefinition = new DefinitionDecorator('liip_imagine.binary.loader.prototype.flysystem');
$loaderDefinition->replaceArgument(1, new Reference($config['filesystem_service']));
$loaderDefinition->addTag('liip_imagine.binary.loader', array(
'loader' => $loaderName,
));
$loaderId = 'liip_imagine.binary.loader.'.$loaderName;

$container->setDefinition($loaderId, $loaderDefinition);

return $loaderId;
}

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

/**
* {@inheritdoc}
*/
public function addConfiguration(ArrayNodeDefinition $builder)
{
$builder
->children()
->scalarNode('filesystem_service')->isRequired()->cannotBeEmpty()->end()
->end()
;
}
}
2 changes: 2 additions & 0 deletions LiipImagineBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Liip\ImagineBundle\DependencyInjection\Compiler\ResolversCompilerPass;
use Liip\ImagineBundle\DependencyInjection\Factory\Loader\FileSystemLoaderFactory;
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\WebPathResolverFactory;
use Liip\ImagineBundle\DependencyInjection\LiipImagineExtension;
Expand Down Expand Up @@ -36,5 +37,6 @@ public function build(ContainerBuilder $container)

$extension->addLoaderFactory(new StreamLoaderFactory());
$extension->addLoaderFactory(new FileSystemLoaderFactory());
$extension->addLoaderFactory(new FlysystemLoaderFactory());
}
}
6 changes: 6 additions & 0 deletions Resources/config/imagine.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@

<parameter key="liip_imagine.binary.loader.filesystem.class">Liip\ImagineBundle\Binary\Loader\FileSystemLoader</parameter>
<parameter key="liip_imagine.binary.loader.stream.class">Liip\ImagineBundle\Binary\Loader\StreamLoader</parameter>
<parameter key="liip_imagine.binary.loader.flysystem.class">Liip\ImagineBundle\Binary\Loader\FlysystemLoader</parameter>

<!-- Cache resolvers' classes -->

Expand Down Expand Up @@ -205,6 +206,11 @@
<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>
</service>

<!-- Cache resolver -->

Expand Down
35 changes: 35 additions & 0 deletions Resources/doc/data-loader/flysystem.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
FlysystemLoader
===============

This loader lets you load images from `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.

Using factory
-------------

.. code-block:: yaml
liip_imagine:
loaders:
profile_photos:
flysystem:
filesystem_service: oneup_flysystem.profile_photos_filesystem
oneup_flysystem:
adapters:
profile_photos:
local:
directory: "path/to/profile/photos"
filesystems:
profile_photos:
adapter: profile_photos
.. _`Flysystem`: /~https://github.com/thephpleague/flysystem
.. _`OneupFlysystemBundle`: /~https://github.com/1up-lab/OneupFlysystemBundle
1 change: 1 addition & 0 deletions Resources/doc/data-loaders.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Built-In DataLoader
data-loader/filesystem
data-loader/gridfs
data-loader/stream
data-loader/flysystem

Other data loaders
------------------
Expand Down
73 changes: 73 additions & 0 deletions Tests/Binary/Loader/FlysystemLoaderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace Liip\ImagineBundle\Tests\Binary\Loader;

use Liip\ImagineBundle\Binary\Loader\FlysystemLoader;
use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
use Liip\ImagineBundle\Tests\AbstractTest;

/**
* @requires PHP 5.4
* @covers Liip\ImagineBundle\Binary\Loader\FlysystemLoader
*/
class FlysystemLoaderTest extends AbstractTest
{
private $flyFilesystem;

public function setUp()
{
parent::setUp();

if (!class_exists('\League\Flysystem\Filesystem')) {
$this->markTestSkipped(
'The league/flysystem PHP library is not available.'
);
}

$adapter = new \League\Flysystem\Adapter\Local($this->fixturesDir);
$this->flyFilesystem = new \League\Flysystem\Filesystem($adapter);
}

public function testShouldImplementLoaderInterface()
{
$rc = new \ReflectionClass('Liip\ImagineBundle\Binary\Loader\FlysystemLoader');

$this->assertTrue($rc->implementsInterface('Liip\ImagineBundle\Binary\Loader\LoaderInterface'));
}

public function testCouldBeConstructedWithExpectedArguments()
{
return new FlysystemLoader(
ExtensionGuesser::getInstance(),
$this->flyFilesystem
);
}

/**
* @depends testCouldBeConstructedWithExpectedArguments
*/
public function testReturnImageContentOnFind($loader)
{
$expectedContent = file_get_contents($this->fixturesDir.'/assets/cats.jpeg');

$this->assertSame(
$expectedContent,
$loader->find('assets/cats.jpeg')->getContent()
);
}

/**
* @depends testCouldBeConstructedWithExpectedArguments
*/
public function testThrowsIfInvalidPathGivenOnFind($loader)
{
$path = 'invalid.jpeg';

$this->setExpectedException(
'Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException',
sprintf('Source image "%s" not found.', $path)
);

$loader->find($path);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

namespace Liip\ImagineBundle\Tests\DependencyInjection\Factory\Loader;

use Liip\ImagineBundle\DependencyInjection\Factory\Loader\FlysystemLoaderFactory;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
* @requires PHP 5.4
* @covers Liip\ImagineBundle\DependencyInjection\Factory\Loader\FlysystemLoaderFactory<extended>
*/
class FlysystemLoaderFactoryTest extends \Phpunit_Framework_TestCase
{
public function setUp()
{
parent::setUp();

if (!class_exists('\League\Flysystem\Filesystem')) {
$this->markTestSkipped(
'The league/flysystem PHP library is not available.'
);
}
}

public function testImplementsLoaderFactoryInterface()
{
$rc = new \ReflectionClass('Liip\ImagineBundle\DependencyInjection\Factory\Loader\FlysystemLoaderFactory');

$this->assertTrue($rc->implementsInterface('Liip\ImagineBundle\DependencyInjection\Factory\Loader\LoaderFactoryInterface'));
}

public function testCouldBeConstructedWithoutAnyArguments()
{
new FlysystemLoaderFactory();
}

public function testReturnExpectedName()
{
$loader = new FlysystemLoaderFactory();

$this->assertEquals('flysystem', $loader->getName());
}

public function testCreateLoaderDefinitionOnCreate()
{
$container = new ContainerBuilder();

$loader = new FlysystemLoaderFactory();

$loader->create($container, 'theLoaderName', array(
'filesystem_service' => 'flyfilesystemservice',
));

$this->assertTrue($container->hasDefinition('liip_imagine.binary.loader.theloadername'));

$loaderDefinition = $container->getDefinition('liip_imagine.binary.loader.theloadername');
$this->assertInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $loaderDefinition);
$this->assertEquals('liip_imagine.binary.loader.prototype.flysystem', $loaderDefinition->getParent());

$reference = $loaderDefinition->getArgument(1);
$this->assertEquals('flyfilesystemservice', "$reference");
}

/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* @expectedExceptionMessage The child node "filesystem_service" at path "flysystem" must be configured.
*/
public function testThrowIfFileSystemServiceNotSetOnAddConfiguration()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('flysystem', 'array');

$resolver = new FlysystemLoaderFactory();
$resolver->addConfiguration($rootNode);

$this->processConfigTree($treeBuilder, array());
}

public function testProcessCorrectlyOptionsOnAddConfiguration()
{
$expectedService = 'theService';

$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('flysystem', 'array');

$loader = new FlysystemLoaderFactory();
$loader->addConfiguration($rootNode);

$config = $this->processConfigTree($treeBuilder, array(
'flysystem' => array(
'filesystem_service' => $expectedService,
),
));

$this->assertArrayHasKey('filesystem_service', $config);
$this->assertEquals($expectedService, $config['filesystem_service']);
}

/**
* @param TreeBuilder $treeBuilder
* @param array $configs
*
* @return array
*/
protected function processConfigTree(TreeBuilder $treeBuilder, array $configs)
{
$processor = new Processor();

return $processor->process($treeBuilder->buildTree(), $configs);
}
}
Loading

0 comments on commit 22d625e

Please sign in to comment.