diff --git a/DependencyInjection/Factory/Resolver/AbstractWebPathResolverFactory.php b/DependencyInjection/Factory/Resolver/AbstractWebPathResolverFactory.php
new file mode 100644
index 000000000..fdab91c56
--- /dev/null
+++ b/DependencyInjection/Factory/Resolver/AbstractWebPathResolverFactory.php
@@ -0,0 +1,67 @@
+getChildResolverDefinition();
+ $pathResolverDefinition = new ChildDefinition('liip_imagine.util.resolver.prototype.path');
+ $pathResolverDefinition->replaceArgument(0, $config['web_root']);
+ $pathResolverDefinition->replaceArgument(1, $config['cache_prefix']);
+
+ $pathResolverServiceId = 'liip_imagine.util.resolver.path';
+ $container->setDefinition($pathResolverServiceId, $pathResolverDefinition);
+
+ $resolverDefinition->replaceArgument(1, new Reference($pathResolverServiceId));
+
+ $resolverDefinition->addTag(
+ 'liip_imagine.cache.resolver',
+ [
+ 'resolver' => $resolverName,
+ ]
+ );
+
+ $resolverId = 'liip_imagine.cache.resolver.';
+ $container->setDefinition($resolverId.$resolverName, $resolverDefinition);
+
+ return $resolverId;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addConfiguration(ArrayNodeDefinition $builder)
+ {
+ $builder
+ ->children()
+ ->scalarNode('web_root')
+ ->defaultValue(SymfonyFramework::getContainerResolvableRootWebPath())
+ ->cannotBeEmpty()
+ ->end()
+ ->scalarNode('cache_prefix')
+ ->defaultValue('media/cache')
+ ->cannotBeEmpty()
+ ->end()
+ ->end();
+ }
+}
diff --git a/DependencyInjection/Factory/Resolver/RelativeWebPathResolverFactory.php b/DependencyInjection/Factory/Resolver/RelativeWebPathResolverFactory.php
new file mode 100644
index 000000000..7c24cd416
--- /dev/null
+++ b/DependencyInjection/Factory/Resolver/RelativeWebPathResolverFactory.php
@@ -0,0 +1,23 @@
+getChildResolverDefinition();
- $resolverDefinition->replaceArgument(2, $config['web_root']);
- $resolverDefinition->replaceArgument(3, $config['cache_prefix']);
- $resolverDefinition->addTag('liip_imagine.cache.resolver', [
- 'resolver' => $resolverName,
- ]);
-
- $resolverId = 'liip_imagine.cache.resolver.';
- $container->setDefinition($resolverId.$resolverName, $resolverDefinition);
-
- return $resolverId;
- }
-
/**
* {@inheritdoc}
*/
@@ -42,22 +20,4 @@ public function getName()
{
return 'web_path';
}
-
- /**
- * {@inheritdoc}
- */
- public function addConfiguration(ArrayNodeDefinition $builder)
- {
- $builder
- ->children()
- ->scalarNode('web_root')
- ->defaultValue(SymfonyFramework::getContainerResolvableRootWebPath())
- ->cannotBeEmpty()
- ->end()
- ->scalarNode('cache_prefix')
- ->defaultValue('media/cache')
- ->cannotBeEmpty()
- ->end()
- ->end();
- }
}
diff --git a/Imagine/Cache/Resolver/AbstractWebPathResolver.php b/Imagine/Cache/Resolver/AbstractWebPathResolver.php
new file mode 100644
index 000000000..8da38efb7
--- /dev/null
+++ b/Imagine/Cache/Resolver/AbstractWebPathResolver.php
@@ -0,0 +1,100 @@
+filesystem = $filesystem;
+ $this->pathResolver = $pathResolver;
+ }
+
+ /**
+ * Checks whether the given path is stored within this Resolver.
+ *
+ * @param string $path
+ * @param string $filter
+ *
+ * @return bool
+ */
+ public function isStored($path, $filter)
+ {
+ return is_file($this->pathResolver->getFilePath($path, $filter));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function store(BinaryInterface $binary, $path, $filter)
+ {
+ $this->filesystem->dumpFile(
+ $this->pathResolver->getFilePath($path, $filter),
+ $binary->getContent()
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function remove(array $paths, array $filters)
+ {
+ if (empty($paths) && empty($filters)) {
+ return;
+ }
+
+ if (empty($paths)) {
+ $filtersCacheDir = [];
+ foreach ($filters as $filter) {
+ $filtersCacheDir[] = $this->pathResolver->getCacheRoot().'/'.$filter;
+ }
+
+ $this->filesystem->remove($filtersCacheDir);
+
+ return;
+ }
+
+ foreach ($paths as $path) {
+ foreach ($filters as $filter) {
+ $this->filesystem->remove($this->pathResolver->getFilePath($path, $filter));
+ }
+ }
+ }
+
+ /**
+ * @return PathResolverInterface
+ */
+ protected function getPathResolver()
+ {
+ return $this->pathResolver;
+ }
+}
diff --git a/Imagine/Cache/Resolver/RelativeWebPathResolver.php b/Imagine/Cache/Resolver/RelativeWebPathResolver.php
new file mode 100644
index 000000000..7b61bcf85
--- /dev/null
+++ b/Imagine/Cache/Resolver/RelativeWebPathResolver.php
@@ -0,0 +1,23 @@
+getPathResolver()->getFileUrl($path, $filter));
+ }
+}
diff --git a/Imagine/Cache/Resolver/WebPathResolver.php b/Imagine/Cache/Resolver/WebPathResolver.php
index a39c54907..d6d7f359e 100644
--- a/Imagine/Cache/Resolver/WebPathResolver.php
+++ b/Imagine/Cache/Resolver/WebPathResolver.php
@@ -11,56 +11,26 @@
namespace Liip\ImagineBundle\Imagine\Cache\Resolver;
-use Liip\ImagineBundle\Binary\BinaryInterface;
-use Liip\ImagineBundle\Imagine\Cache\Helper\PathHelper;
+use Liip\ImagineBundle\Utility\Path\PathResolverInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Routing\RequestContext;
-class WebPathResolver implements ResolverInterface
+class WebPathResolver extends AbstractWebPathResolver
{
- /**
- * @var Filesystem
- */
- protected $filesystem;
-
- /**
- * @var RequestContext
- */
- protected $requestContext;
-
- /**
- * @var string
- */
- protected $webRoot;
+ private $requestContext;
/**
- * @var string
- */
- protected $cachePrefix;
-
- /**
- * @var string
- */
- protected $cacheRoot;
-
- /**
- * @param Filesystem $filesystem
- * @param RequestContext $requestContext
- * @param string $webRootDir
- * @param string $cachePrefix
+ * @param Filesystem $filesystem
+ * @param PathResolverInterface $pathResolver
+ * @param RequestContext $requestContext
*/
public function __construct(
Filesystem $filesystem,
- RequestContext $requestContext,
- $webRootDir,
- $cachePrefix = 'media/cache'
+ PathResolverInterface $pathResolver,
+ RequestContext $requestContext
) {
- $this->filesystem = $filesystem;
+ parent::__construct($filesystem, $pathResolver);
$this->requestContext = $requestContext;
-
- $this->webRoot = rtrim(str_replace('//', '/', $webRootDir), '/');
- $this->cachePrefix = ltrim(str_replace('//', '/', $cachePrefix), '/');
- $this->cacheRoot = $this->webRoot.'/'.$this->cachePrefix;
}
/**
@@ -68,74 +38,13 @@ public function __construct(
*/
public function resolve($path, $filter)
{
- return sprintf('%s/%s',
+ return sprintf(
+ '%s/%s',
rtrim($this->getBaseUrl(), '/'),
- ltrim($this->getFileUrl($path, $filter), '/')
+ ltrim($this->getPathResolver()->getFileUrl($path, $filter), '/')
);
}
- /**
- * {@inheritdoc}
- */
- public function isStored($path, $filter)
- {
- return is_file($this->getFilePath($path, $filter));
- }
-
- /**
- * {@inheritdoc}
- */
- public function store(BinaryInterface $binary, $path, $filter)
- {
- $this->filesystem->dumpFile(
- $this->getFilePath($path, $filter),
- $binary->getContent()
- );
- }
-
- /**
- * {@inheritdoc}
- */
- public function remove(array $paths, array $filters)
- {
- if (empty($paths) && empty($filters)) {
- return;
- }
-
- if (empty($paths)) {
- $filtersCacheDir = [];
- foreach ($filters as $filter) {
- $filtersCacheDir[] = $this->cacheRoot.'/'.$filter;
- }
-
- $this->filesystem->remove($filtersCacheDir);
-
- return;
- }
-
- foreach ($paths as $path) {
- foreach ($filters as $filter) {
- $this->filesystem->remove($this->getFilePath($path, $filter));
- }
- }
- }
-
- /**
- * {@inheritdoc}
- */
- protected function getFilePath($path, $filter)
- {
- return $this->webRoot.'/'.$this->getFullPath($path, $filter);
- }
-
- /**
- * {@inheritdoc}
- */
- protected function getFileUrl($path, $filter)
- {
- return PathHelper::filePathToUrlPath($this->getFullPath($path, $filter));
- }
-
/**
* @return string
*/
@@ -156,19 +65,12 @@ protected function getBaseUrl()
}
$baseUrl = rtrim($baseUrl, '/\\');
- return sprintf('%s://%s%s%s',
+ return sprintf(
+ '%s://%s%s%s',
$this->requestContext->getScheme(),
$this->requestContext->getHost(),
$port,
$baseUrl
);
}
-
- private function getFullPath($path, $filter)
- {
- // crude way of sanitizing URL scheme ("protocol") part
- $path = str_replace('://', '---', $path);
-
- return $this->cachePrefix.'/'.$filter.'/'.ltrim($path, '/');
- }
}
diff --git a/LiipImagineBundle.php b/LiipImagineBundle.php
index 44072bdb4..50a52a1b4 100644
--- a/LiipImagineBundle.php
+++ b/LiipImagineBundle.php
@@ -25,6 +25,7 @@
use Liip\ImagineBundle\DependencyInjection\Factory\Loader\StreamLoaderFactory;
use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\AwsS3ResolverFactory;
use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\FlysystemResolverFactory;
+use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\RelativeWebPathResolverFactory;
use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\WebPathResolverFactory;
use Liip\ImagineBundle\DependencyInjection\LiipImagineExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -58,6 +59,7 @@ public function build(ContainerBuilder $container)
$extension->addResolverFactory(new WebPathResolverFactory());
$extension->addResolverFactory(new AwsS3ResolverFactory());
$extension->addResolverFactory(new FlysystemResolverFactory());
+ $extension->addResolverFactory(new RelativeWebPathResolverFactory());
$extension->addLoaderFactory(new StreamLoaderFactory());
$extension->addLoaderFactory(new FileSystemLoaderFactory());
diff --git a/Resources/config/imagine.xml b/Resources/config/imagine.xml
index e7aa74a54..4e037764b 100644
--- a/Resources/config/imagine.xml
+++ b/Resources/config/imagine.xml
@@ -139,6 +139,11 @@
+
+
+
+
+
@@ -300,14 +305,17 @@
-
-
+
+
+
+
+
-
-
+
+
diff --git a/Resources/doc/cache-resolver/relative_web_path.rst b/Resources/doc/cache-resolver/relative_web_path.rst
new file mode 100644
index 000000000..9b9708d3f
--- /dev/null
+++ b/Resources/doc/cache-resolver/relative_web_path.rst
@@ -0,0 +1,67 @@
+
+.. _cache-resolver-relative-web-path:
+
+Relative Web Path Resolver
+=================
+
+This cache resolver (``RelativeWebPathResolver``), as well as
+:ref:`web path cache resolver `, enables cache resolution for
+local, web-path-based setups. This means images will be cached on your
+local filesystem, within the web path of your Symfony application.
+The only difference between them is that first one generates relative url paths
+
+Configuration
+-------------
+.. code-block:: yaml
+
+ liip_imagine:
+ resolvers:
+ profile_photos:
+ relative_web_path:
+ # use %kernel.project_dir%/web for Symfony prior to 4.0.0
+ web_root: "%kernel.project_dir%/public"
+ cache_prefix: "media/cache"
+
+There are several configuration options available:
+
+* ``web_root`` - must be the absolute path to you application's web root. This
+ is used to determine where to put generated image files, so that apache
+ will pick them up before handing the request to Symfony next time they
+ are requested. The default value ends with ``web`` for Symfony prior to
+ version ``4.0.0``.
+ Default value: ``%kernel.project_dir%/(public|web)``
+* ``cache_prefix`` - this is also used in the path for image generation, so
+ as to not clutter your web root with cached images. For example by default,
+ the images would be written to the ``web/media/cache/`` directory.
+ Default value: ``/media/cache``
+
+Usage
+-----
+After configuring ``RelativeWebPathResolver``, you can set it as the default cache resolver
+for ``LiipImagineBundle`` using the following configuration.
+
+.. code-block:: yaml
+
+ # app/config/config.yml
+
+ liip_imagine:
+ cache: profile_photos
+
+
+Usage on a Specific Filter
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Alternatively, you can set ``RelativeWebPathResolver`` as the cache resolver for a specific
+filter set using the following configuration.
+
+.. code-block:: yaml
+
+ # app/config/config.yml
+
+ liip_imagine:
+ filter_sets:
+ cache: ~
+ my_thumb:
+ cache: profile_photos
+ filters:
+ # the filter list
diff --git a/Tests/DependencyInjection/Factory/Resolver/AbstractWebPathResolverTest.php b/Tests/DependencyInjection/Factory/Resolver/AbstractWebPathResolverTest.php
new file mode 100644
index 000000000..ed6c21db2
--- /dev/null
+++ b/Tests/DependencyInjection/Factory/Resolver/AbstractWebPathResolverTest.php
@@ -0,0 +1,158 @@
+getClassName());
+
+ $this->assertTrue($rc->implementsInterface(ResolverFactoryInterface::class));
+ }
+
+ public function testCouldBeConstructedWithoutAnyArguments(): void
+ {
+ $loader = $this->createResolver();
+
+ $this->assertInstanceOf($this->getClassName(), $loader);
+ }
+
+ public function testAbstractWebPathResolverFactoryImplementation(): void
+ {
+ $this->assertTrue(is_a($this->getClassName(), AbstractWebPathResolverFactory::class, true));
+ }
+
+ public function testCreateResolverDefinitionOnCreate(): void
+ {
+ $container = new ContainerBuilder();
+
+ $resolver = $this->createResolver();
+ $resolver->create(
+ $container,
+ 'the_resolver_name',
+ [
+ 'web_root' => 'theWebRoot',
+ 'cache_prefix' => 'theCachePrefix',
+ ]
+ );
+
+ $this->assertTrue($container->hasDefinition('liip_imagine.cache.resolver.the_resolver_name'));
+
+ $resolverDefinition = $container->getDefinition('liip_imagine.cache.resolver.the_resolver_name');
+ $this->assertInstanceOf(ChildDefinition::class, $resolverDefinition);
+ $this->assertSame(
+ sprintf('liip_imagine.cache.resolver.prototype.%s', $resolver->getName()),
+ $resolverDefinition->getParent()
+ );
+
+ $utilPathResolverReference = $resolverDefinition->getArgument(1);
+ $this->assertInstanceOf(Reference::class, $utilPathResolverReference);
+
+ $utilPathResolverServiceId = (string) $utilPathResolverReference;
+ $this->assertSame('liip_imagine.util.resolver.path', $utilPathResolverServiceId);
+ $this->assertTrue($container->hasDefinition($utilPathResolverServiceId));
+
+ $utilPathResolverDefinition = $container->getDefinition($utilPathResolverServiceId);
+ $this->assertInstanceOf(ChildDefinition::class, $utilPathResolverDefinition);
+ $this->assertSame('liip_imagine.util.resolver.prototype.path', $utilPathResolverDefinition->getParent());
+
+ $this->assertSame('theWebRoot', $utilPathResolverDefinition->getArgument(0));
+ $this->assertSame('theCachePrefix', $utilPathResolverDefinition->getArgument(1));
+ }
+
+ public function testProcessCorrectlyOptionsOnAddConfiguration(): void
+ {
+ $expectedWebPath = 'theWebPath';
+ $expectedCachePrefix = 'theCachePrefix';
+
+ $treeBuilder = new TreeBuilder('test_resolver_name');
+ $rootNode = method_exists(TreeBuilder::class, 'getRootNode')
+ ? $treeBuilder->getRootNode()
+ : $treeBuilder->root('test_resolver_name');
+
+ $resolver = $this->createResolver();
+ $resolver->addConfiguration($rootNode);
+
+ $config = $this->processConfigTree(
+ $treeBuilder,
+ [
+ $resolver->getName() => [
+ 'web_root' => $expectedWebPath,
+ 'cache_prefix' => $expectedCachePrefix,
+ ],
+ ]
+ );
+
+ $this->assertArrayHasKey('web_root', $config);
+ $this->assertSame($expectedWebPath, $config['web_root']);
+
+ $this->assertArrayHasKey('cache_prefix', $config);
+ $this->assertSame($expectedCachePrefix, $config['cache_prefix']);
+ }
+
+ public function testAddDefaultOptionsIfNotSetOnAddConfiguration(): void
+ {
+ $treeBuilder = new TreeBuilder('test_resolver_name');
+ $rootNode = method_exists(TreeBuilder::class, 'getRootNode')
+ ? $treeBuilder->getRootNode()
+ : $treeBuilder->root('test_resolver_name');
+
+ $resolver = $this->createResolver();
+ $resolver->addConfiguration($rootNode);
+
+ $config = $this->processConfigTree(
+ $treeBuilder,
+ [
+ $resolver->getName() => [],
+ ]
+ );
+
+ $this->assertArrayHasKey('web_root', $config);
+ $this->assertSame(SymfonyFramework::getContainerResolvableRootWebPath(), $config['web_root']);
+
+ $this->assertArrayHasKey('cache_prefix', $config);
+ $this->assertSame('media/cache', $config['cache_prefix']);
+ }
+
+ protected function processConfigTree(TreeBuilder $treeBuilder, array $configs): array
+ {
+ $processor = new Processor();
+
+ return $processor->process($treeBuilder->buildTree(), $configs);
+ }
+
+ /**
+ * @return string|ResolverFactoryInterface
+ */
+ abstract protected function getClassName();
+
+ private function createResolver()
+ {
+ $className = $this->getClassName();
+
+ return new $className();
+ }
+}
diff --git a/Tests/DependencyInjection/Factory/Resolver/RelativeWebPathResolverFactoryTest.php b/Tests/DependencyInjection/Factory/Resolver/RelativeWebPathResolverFactoryTest.php
new file mode 100644
index 000000000..89da238a9
--- /dev/null
+++ b/Tests/DependencyInjection/Factory/Resolver/RelativeWebPathResolverFactoryTest.php
@@ -0,0 +1,36 @@
+assertSame('relative_web_path', $resolver->getName());
+ }
+
+ /**
+ * @return string|ResolverFactoryInterface
+ */
+ protected function getClassName()
+ {
+ return RelativeWebPathResolverFactory::class;
+ }
+}
diff --git a/Tests/DependencyInjection/Factory/Resolver/WebPathResolverFactoryTest.php b/Tests/DependencyInjection/Factory/Resolver/WebPathResolverFactoryTest.php
index ce966277d..829a86393 100644
--- a/Tests/DependencyInjection/Factory/Resolver/WebPathResolverFactoryTest.php
+++ b/Tests/DependencyInjection/Factory/Resolver/WebPathResolverFactoryTest.php
@@ -13,118 +13,24 @@
use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\ResolverFactoryInterface;
use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\WebPathResolverFactory;
-use Liip\ImagineBundle\Utility\Framework\SymfonyFramework;
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Builder\TreeBuilder;
-use Symfony\Component\Config\Definition\Processor;
-use Symfony\Component\DependencyInjection\ChildDefinition;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* @covers \Liip\ImagineBundle\DependencyInjection\Factory\Resolver\WebPathResolverFactory
*/
-class WebPathResolverFactoryTest extends TestCase
+class WebPathResolverFactoryTest extends AbstractWebPathResolverTest
{
- public function testImplementsResolverFactoryInterface()
- {
- $rc = new \ReflectionClass(WebPathResolverFactory::class);
-
- $this->assertTrue($rc->implementsInterface(ResolverFactoryInterface::class));
- }
-
- public function testCouldBeConstructedWithoutAnyArguments()
- {
- $loader = new WebPathResolverFactory();
-
- $this->assertInstanceOf(WebPathResolverFactory::class, $loader);
- }
-
- public function testReturnExpectedName()
+ public function testReturnExpectedName(): void
{
$resolver = new WebPathResolverFactory();
$this->assertSame('web_path', $resolver->getName());
}
- public function testCreateResolverDefinitionOnCreate()
- {
- $container = new ContainerBuilder();
-
- $resolver = new WebPathResolverFactory();
-
- $resolver->create($container, 'the_resolver_name', [
- 'web_root' => 'theWebRoot',
- 'cache_prefix' => 'theCachePrefix',
- ]);
-
- $this->assertTrue($container->hasDefinition('liip_imagine.cache.resolver.the_resolver_name'));
-
- $resolverDefinition = $container->getDefinition('liip_imagine.cache.resolver.the_resolver_name');
- $this->assertInstanceOf(ChildDefinition::class, $resolverDefinition);
- $this->assertSame('liip_imagine.cache.resolver.prototype.web_path', $resolverDefinition->getParent());
-
- $this->assertSame('theWebRoot', $resolverDefinition->getArgument(2));
- $this->assertSame('theCachePrefix', $resolverDefinition->getArgument(3));
- }
-
- public function testProcessCorrectlyOptionsOnAddConfiguration()
- {
- $expectedWebPath = 'theWebPath';
- $expectedCachePrefix = 'theCachePrefix';
-
- $treeBuilder = new TreeBuilder('web_path');
- $rootNode = method_exists(TreeBuilder::class, 'getRootNode')
- ? $treeBuilder->getRootNode()
- : $treeBuilder->root('web_path');
-
- $resolver = new WebPathResolverFactory();
- $resolver->addConfiguration($rootNode);
-
- $config = $this->processConfigTree($treeBuilder, [
- 'web_path' => [
- 'web_root' => $expectedWebPath,
- 'cache_prefix' => $expectedCachePrefix,
- ],
- ]);
-
- $this->assertArrayHasKey('web_root', $config);
- $this->assertSame($expectedWebPath, $config['web_root']);
-
- $this->assertArrayHasKey('cache_prefix', $config);
- $this->assertSame($expectedCachePrefix, $config['cache_prefix']);
- }
-
- public function testAddDefaultOptionsIfNotSetOnAddConfiguration()
- {
- $treeBuilder = new TreeBuilder('web_path');
- $rootNode = method_exists(TreeBuilder::class, 'getRootNode')
- ? $treeBuilder->getRootNode()
- : $treeBuilder->root('web_path');
-
- $resolver = new WebPathResolverFactory();
- $resolver->addConfiguration($rootNode);
-
- $config = $this->processConfigTree($treeBuilder, [
- 'web_path' => [],
- ]);
-
- $this->assertArrayHasKey('web_root', $config);
- $this->assertSame(SymfonyFramework::getContainerResolvableRootWebPath(), $config['web_root']);
-
- $this->assertArrayHasKey('cache_prefix', $config);
- $this->assertSame('media/cache', $config['cache_prefix']);
- }
-
/**
- * @param TreeBuilder $treeBuilder
- * @param array $configs
- *
- * @return array
+ * @return string|ResolverFactoryInterface
*/
- protected function processConfigTree(TreeBuilder $treeBuilder, array $configs)
+ protected function getClassName()
{
- $processor = new Processor();
-
- return $processor->process($treeBuilder->buildTree(), $configs);
+ return WebPathResolverFactory::class;
}
}
diff --git a/Tests/Imagine/Cache/Resolver/RelativeWebPathResolverTest.php b/Tests/Imagine/Cache/Resolver/RelativeWebPathResolverTest.php
new file mode 100644
index 000000000..0ca0ed762
--- /dev/null
+++ b/Tests/Imagine/Cache/Resolver/RelativeWebPathResolverTest.php
@@ -0,0 +1,243 @@
+filesystem = $this->getMockBuilder(Filesystem::class)->getMock();
+ $this->pathResolverUtil = $this->getMockBuilder(PathResolverInterface::class)->getMock();
+ $this->relativeWebPathResolver = new RelativeWebPathResolver($this->filesystem, $this->pathResolverUtil);
+
+ $this->basePath = sys_get_temp_dir().'/aWebRoot';
+ }
+
+ public function testImplementsResolverInterface(): void
+ {
+ $this->assertInstanceOf(ResolverInterface::class, $this->relativeWebPathResolver);
+ }
+
+ public function testResolve(): void
+ {
+ $path = 'aPath';
+ $filter = 'aFilter';
+ $fileUrl = 'cacheDir/aFilter/aPath';
+
+ $this->pathResolverUtil
+ ->expects($this->once())
+ ->method('getFileUrl')
+ ->with($this->equalTo($path), $this->equalTo($filter))
+ ->willReturn($fileUrl);
+
+ $actualFileUrl = $this->relativeWebPathResolver->resolve($path, $filter);
+
+ $this->assertSame(sprintf('/%s', $fileUrl), $actualFileUrl);
+ }
+
+ public function testOnSameConstructorArguments(): void
+ {
+ $this->assertAttributeSame($this->filesystem, 'filesystem', $this->relativeWebPathResolver);
+ $this->assertAttributeSame($this->pathResolverUtil, 'pathResolver', $this->relativeWebPathResolver);
+ }
+
+ public function testFileIsStored(): void
+ {
+ $existingFile = $this->basePath.'/aCachePrefix/aFilter/existingPath';
+ $filesystem = new Filesystem();
+ $filesystem->mkdir(dirname($existingFile));
+ $filesystem->touch($existingFile);
+
+ $pathResolver = new PathResolver($this->basePath, 'aCachePrefix');
+ $resolver = new RelativeWebPathResolver(
+ $this->filesystem,
+ $pathResolver
+ );
+
+ $this->assertTrue($resolver->isStored('existingPath', 'aFilter'));
+ $filesystem->remove($this->basePath);
+ }
+
+ public function testFileIsNotStored(): void
+ {
+ $existingFile = $this->basePath.'/aCachePrefix/aFilter/existingPath';
+ $filesystem = new Filesystem();
+ $filesystem->mkdir(dirname($existingFile));
+ $filesystem->touch($existingFile);
+
+ $pathResolver = new PathResolver($this->basePath, 'aCachePrefix');
+ $resolver = new RelativeWebPathResolver(
+ $this->filesystem,
+ $pathResolver
+ );
+
+ $this->assertFalse($resolver->isStored('notExisting file', 'aFilter'));
+ $filesystem->remove($this->basePath);
+ }
+
+ public function testStore(): void
+ {
+ $path = 'aPath';
+ $filter = 'aFilter';
+ $filePath = '/rootDir/cacheDir/file';
+ $fileContent = 'theFileContent';
+
+ $binary = new Binary($fileContent, 'applivation/customFile', 'custom');
+
+ $this->pathResolverUtil
+ ->expects($this->once())
+ ->method('getFilePath')
+ ->with($this->equalTo($path), $this->equalTo($filter))
+ ->willReturn($filePath);
+
+ $this->filesystem
+ ->expects($this->once())
+ ->method('dumpFile')
+ ->with($this->equalTo($filePath), $this->equalTo($fileContent));
+
+ $this->relativeWebPathResolver->store($binary, $path, $filter);
+ }
+
+ public function testRemoveWithEmptyInputArrays(): void
+ {
+ $this->filesystem
+ ->expects($this->exactly(0))
+ ->method('remove');
+
+ $this->relativeWebPathResolver->remove([], []);
+ }
+
+ public function testRemoveWithEmptyPathsArrayAndSingleFilter(): void
+ {
+ $filter = 'aFilter';
+ $cacheRoot = '/root/cacheFolder';
+
+ $this->pathResolverUtil
+ ->expects($this->once())
+ ->method('getCacheRoot')
+ ->willReturn($cacheRoot);
+
+ $this->filesystem
+ ->expects($this->once())
+ ->method('remove')
+ ->with(
+ $this->equalTo(
+ [
+ sprintf('%s/%s', $cacheRoot, $filter),
+ ]
+ )
+ );
+
+ $this->relativeWebPathResolver->remove([], [$filter]);
+ }
+
+ public function testRemoveWithEmptyPathsArrayAndMultipleFilters(): void
+ {
+ $filterOne = 'aFilterOne';
+ $filterTwo = 'aFilterTwo';
+ $cacheRoot = '/root/cacheFolder';
+
+ $this->pathResolverUtil
+ ->expects($this->exactly(2))
+ ->method('getCacheRoot')
+ ->willReturn($cacheRoot);
+
+ $this->filesystem
+ ->expects($this->once())
+ ->method('remove')
+ ->with(
+ $this->equalTo(
+ [
+ sprintf('%s/%s', $cacheRoot, $filterOne),
+ sprintf('%s/%s', $cacheRoot, $filterTwo),
+ ]
+ )
+ );
+
+ $this->relativeWebPathResolver->remove([], [$filterOne, $filterTwo]);
+ }
+
+ public function testRemoveWithMultiplePathaAndFilters(): void
+ {
+ $filterOne = 'aFilterOne';
+ $filterTwo = 'aFilterTwo';
+ $pathOne = 'aPathOne';
+ $pathTwo = 'aPathTwo';
+ $cacheRoot = '/root/cacheFolder';
+
+ $this->pathResolverUtil
+ ->expects($this->exactly(0))
+ ->method('getCacheRoot');
+
+ $this->pathResolverUtil
+ ->method('getFilePath')
+ ->willReturnMap(
+ [
+ [$pathOne, $filterOne, sprintf('%s/%s/%s', $cacheRoot, $filterOne, $pathOne)],
+ [$pathOne, $filterTwo, sprintf('%s/%s/%s', $cacheRoot, $filterTwo, $pathOne)],
+ [$pathTwo, $filterOne, sprintf('%s/%s/%s', $cacheRoot, $filterOne, $pathTwo)],
+ [$pathTwo, $filterTwo, sprintf('%s/%s/%s', $cacheRoot, $filterTwo, $pathTwo)],
+ ]
+ );
+
+ $this->filesystem
+ ->expects($this->at(0))
+ ->method('remove')
+ ->with(sprintf('%s/%s/%s', $cacheRoot, $filterOne, $pathOne));
+ $this->filesystem
+ ->expects($this->at(1))
+ ->method('remove')
+ ->with(sprintf('%s/%s/%s', $cacheRoot, $filterTwo, $pathOne));
+ $this->filesystem
+ ->expects($this->at(2))
+ ->method('remove')
+ ->with(sprintf('%s/%s/%s', $cacheRoot, $filterOne, $pathTwo));
+ $this->filesystem
+ ->expects($this->at(3))
+ ->method('remove')
+ ->with(sprintf('%s/%s/%s', $cacheRoot, $filterTwo, $pathTwo));
+
+ $this->relativeWebPathResolver->remove(
+ [$pathOne, $pathTwo],
+ [$filterOne, $filterTwo]
+ );
+ }
+}
diff --git a/Tests/Imagine/Cache/Resolver/WebPathResolverTest.php b/Tests/Imagine/Cache/Resolver/WebPathResolverTest.php
index 0eb27b54a..28deee5fc 100644
--- a/Tests/Imagine/Cache/Resolver/WebPathResolverTest.php
+++ b/Tests/Imagine/Cache/Resolver/WebPathResolverTest.php
@@ -14,6 +14,8 @@
use Liip\ImagineBundle\Imagine\Cache\Resolver\ResolverInterface;
use Liip\ImagineBundle\Imagine\Cache\Resolver\WebPathResolver;
use Liip\ImagineBundle\Model\Binary;
+use Liip\ImagineBundle\Utility\Path\PathResolver;
+use Liip\ImagineBundle\Utility\Path\PathResolverInterface;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Routing\RequestContext;
@@ -62,83 +64,23 @@ public function testImplementsResolverInterface()
public function testCouldBeConstructedWithRequiredArguments()
{
$filesystemMock = $this->createFilesystemMock();
+ $pathResolver = $this->createPathResolverMock();
$requestContext = new RequestContext();
- $webRoot = 'theWebRoot';
- $resolver = new WebPathResolver($filesystemMock, $requestContext, $webRoot);
+ $resolver = new WebPathResolver($filesystemMock, $pathResolver, $requestContext);
$this->assertAttributeSame($filesystemMock, 'filesystem', $resolver);
+ $this->assertAttributeSame($pathResolver, 'pathResolver', $resolver);
$this->assertAttributeSame($requestContext, 'requestContext', $resolver);
- $this->assertAttributeSame($webRoot, 'webRoot', $resolver);
- }
-
- public function testCouldBeConstructedWithOptionalArguments()
- {
- $resolver = new WebPathResolver(
- $this->createFilesystemMock(),
- new RequestContext(),
- 'aWebRoot',
- 'theCachePrefix'
- );
-
- $this->assertAttributeSame('theCachePrefix', 'cachePrefix', $resolver);
- }
-
- public function testTrimRightSlashFromWebPathOnConstruct()
- {
- $resolver = new WebPathResolver(
- $this->createFilesystemMock(),
- new RequestContext(),
- 'aWebRoot/',
- 'theCachePrefix'
- );
-
- $this->assertAttributeSame('aWebRoot', 'webRoot', $resolver);
- }
-
- public function testRemoveDoubleSlashFromWebRootOnConstruct()
- {
- $resolver = new WebPathResolver(
- $this->createFilesystemMock(),
- new RequestContext(),
- 'aWeb//Root',
- '/aCachePrefix'
- );
-
- $this->assertAttributeSame('aWeb/Root', 'webRoot', $resolver);
- }
-
- public function testTrimRightSlashFromCachePrefixOnConstruct()
- {
- $resolver = new WebPathResolver(
- $this->createFilesystemMock(),
- new RequestContext(),
- 'aWebRoot',
- '/aCachePrefix'
- );
-
- $this->assertAttributeSame('aCachePrefix', 'cachePrefix', $resolver);
- }
-
- public function testRemoveDoubleSlashFromCachePrefixOnConstruct()
- {
- $resolver = new WebPathResolver(
- $this->createFilesystemMock(),
- new RequestContext(),
- 'aWebRoot',
- 'aCache//Prefix'
- );
-
- $this->assertAttributeSame('aCache/Prefix', 'cachePrefix', $resolver);
}
public function testReturnTrueIfFileExistsOnIsStored()
{
+ $pathResolver = new PathResolver($this->basePath, 'aCachePrefix');
$resolver = new WebPathResolver(
$this->createFilesystemMock(),
- new RequestContext(),
- $this->basePath,
- 'aCachePrefix'
+ $pathResolver,
+ new RequestContext()
);
$this->assertTrue($resolver->isStored('existingPath', 'aFilter'));
@@ -146,11 +88,11 @@ public function testReturnTrueIfFileExistsOnIsStored()
public function testReturnFalseIfFileNotExistsOnIsStored()
{
+ $pathResolver = new PathResolver($this->basePath, 'aCachePrefix');
$resolver = new WebPathResolver(
$this->createFilesystemMock(),
- new RequestContext(),
- $this->basePath,
- 'aCachePrefix'
+ $pathResolver,
+ new RequestContext()
);
$this->assertFalse($resolver->isStored('nonExistingPath', 'aFilter'));
@@ -158,11 +100,11 @@ public function testReturnFalseIfFileNotExistsOnIsStored()
public function testReturnFalseIfIsNotFile()
{
+ $pathResolver = new PathResolver($this->basePath, 'aCachePrefix');
$resolver = new WebPathResolver(
$this->createFilesystemMock(),
- new RequestContext(),
- $this->basePath,
- 'aCachePrefix'
+ $pathResolver,
+ new RequestContext()
);
$this->assertFalse($resolver->isStored('', 'aFilter'));
@@ -170,40 +112,61 @@ public function testReturnFalseIfIsNotFile()
public function testComposeSchemaHostAndFileUrlOnResolve()
{
+ $path = 'aPath';
+ $filter = 'aFilter';
+
$requestContext = new RequestContext();
$requestContext->setScheme('theSchema');
$requestContext->setHost('thehost');
+ $pathResolver = $this->createPathResolverMock();
+ $pathResolver
+ ->method('getFileUrl')
+ ->with(
+ $this->equalTo($path),
+ $this->equalTo($filter)
+ )
+ ->willReturn(
+ 'aCachePrefix/aFilter/aPath'
+ );
+
$resolver = new WebPathResolver(
- $this->createFilesystemMock(),
- $requestContext,
- '/aWebRoot',
- 'aCachePrefix'
+ $this->createFilesystemMock(), $pathResolver, $requestContext
);
$this->assertSame(
'theschema://thehost/aCachePrefix/aFilter/aPath',
- $resolver->resolve('aPath', 'aFilter')
+ $resolver->resolve($path, $filter)
);
}
public function testComposeSchemaHostAndBasePathWithPhpFileAndFileUrlOnResolve()
{
+ $path = 'aPath';
+ $filter = 'aFilter';
+
$requestContext = new RequestContext();
$requestContext->setScheme('theSchema');
$requestContext->setHost('thehost');
$requestContext->setBaseUrl('/theBasePath/app.php');
+ $pathResolver = $this->createPathResolverMock();
+ $pathResolver->method('getFileUrl')
+ ->with(
+ $this->equalTo($path),
+ $this->equalTo($filter)
+ )
+ ->willReturn(
+ 'aCachePrefix/aFilter/aPath'
+ );
+
$resolver = new WebPathResolver(
- $this->createFilesystemMock(),
- $requestContext,
- '/aWebRoot',
- 'aCachePrefix'
+ $this->createFilesystemMock(), $pathResolver, $requestContext
);
$this->assertSame(
'theschema://thehost/theBasePath/aCachePrefix/aFilter/aPath',
- $resolver->resolve('aPath', 'aFilter')
+ $resolver->resolve($path, $filter)
);
}
@@ -214,11 +177,12 @@ public function testResolveWithPrefixCacheEmpty()
$requestContext->setHost('thehost');
$requestContext->setBaseUrl('/theBasePath/app.php');
+ $pathResolver = new PathResolver('/aWebRoot', '');
+
$resolver = new WebPathResolver(
$this->createFilesystemMock(),
- $requestContext,
- '/aWebRoot',
- ''
+ $pathResolver,
+ $requestContext
);
$this->assertSame(
@@ -229,116 +193,173 @@ public function testResolveWithPrefixCacheEmpty()
public function testComposeSchemaHostAndBasePathWithDirsOnlyAndFileUrlOnResolve()
{
+ $path = 'aPath';
+ $filter = 'aFilter';
+
$requestContext = new RequestContext();
$requestContext->setScheme('theSchema');
$requestContext->setHost('thehost');
$requestContext->setBaseUrl('/theBasePath/theSubBasePath');
+ $pathResolver = $this->createPathResolverMock();
+ $pathResolver->method('getFileUrl')
+ ->with(
+ $this->equalTo($path),
+ $this->equalTo($filter)
+ )
+ ->willReturn(
+ 'aCachePrefix/aFilter/aPath'
+ );
+
$resolver = new WebPathResolver(
- $this->createFilesystemMock(),
- $requestContext,
- '/aWebRoot',
- 'aCachePrefix'
+ $this->createFilesystemMock(), $pathResolver, $requestContext
);
$this->assertSame(
'theschema://thehost/theBasePath/theSubBasePath/aCachePrefix/aFilter/aPath',
- $resolver->resolve('aPath', 'aFilter')
+ $resolver->resolve($path, $filter)
);
}
public function testComposeSchemaHostAndBasePathWithBackSplashOnResolve()
{
+ $path = 'aPath';
+ $filter = 'aFilter';
+ $fileUrl = 'aCachePrefix/aFilter/aPath';
+
$requestContext = new RequestContext();
$requestContext->setScheme('theSchema');
$requestContext->setHost('thehost');
$requestContext->setBaseUrl('\\');
+ $pathResolver = $this->createPathResolverMock();
+ $pathResolver->method('getFileUrl')
+ ->with(
+ $this->equalTo($path),
+ $this->equalTo($filter)
+ )
+ ->willReturn($fileUrl);
+
$resolver = new WebPathResolver(
$this->createFilesystemMock(),
- $requestContext,
- '/aWebRoot',
- 'aCachePrefix'
+ $pathResolver,
+ $requestContext
);
$this->assertSame(
- 'theschema://thehost/aCachePrefix/aFilter/aPath',
- $resolver->resolve('aPath', 'aFilter')
+ sprintf('theschema://thehost/%s', $fileUrl),
+ $resolver->resolve($path, $filter)
);
}
public function testComposeSchemaHttpAndCustomPortAndFileUrlOnResolve()
{
+ $path = 'aPath';
+ $filter = 'aFilter';
+ $fileUrl = 'aCachePrefix/aFilter/aPath';
+
$requestContext = new RequestContext();
$requestContext->setScheme('http');
$requestContext->setHost('thehost');
$requestContext->setHttpPort(88);
+ $pathResolver = $this->createPathResolverMock();
+ $pathResolver->method('getFileUrl')
+ ->with(
+ $this->equalTo($path),
+ $this->equalTo($filter)
+ )
+ ->willReturn($fileUrl);
+
$resolver = new WebPathResolver(
$this->createFilesystemMock(),
- $requestContext,
- '/aWebRoot',
- 'aCachePrefix'
+ $pathResolver,
+ $requestContext
);
$this->assertSame(
- 'http://thehost:88/aCachePrefix/aFilter/aPath',
- $resolver->resolve('aPath', 'aFilter')
+ sprintf('http://thehost:88/%s', $fileUrl),
+ $resolver->resolve($path, $filter)
);
}
public function testComposeSchemaHttpsAndCustomPortAndFileUrlOnResolve()
{
+ $path = 'aPath';
+ $filter = 'aFilter';
+ $fileUrl = 'aCachePrefix/aFilter/aPath';
+
$requestContext = new RequestContext();
$requestContext->setScheme('https');
$requestContext->setHost('thehost');
$requestContext->setHttpsPort(444);
+ $pathResolver = $this->createPathResolverMock();
+ $pathResolver->method('getFileUrl')
+ ->with(
+ $this->equalTo($path),
+ $this->equalTo($filter)
+ )
+ ->willReturn($fileUrl);
+
$resolver = new WebPathResolver(
$this->createFilesystemMock(),
- $requestContext,
- '/aWebRoot',
- 'aCachePrefix'
+ $pathResolver,
+ $requestContext
);
$this->assertSame(
- 'https://thehost:444/aCachePrefix/aFilter/aPath',
- $resolver->resolve('aPath', 'aFilter')
+ sprintf('https://thehost:444/%s', $fileUrl),
+ $resolver->resolve($path, $filter)
);
}
public function testDumpBinaryContentOnStore()
{
- $binary = new Binary('theContent', 'aMimeType', 'aFormat');
+ $path = 'aPath';
+ $filter = 'aFilter';
+ $fileUrl = '/aWebRoot/aCachePrefix/aFilter/aPath';
+ $fileContent = 'theContent';
+
+ $binary = new Binary($fileContent, 'aMimeType', 'aFormat');
$filesystemMock = $this->createFilesystemMock();
$filesystemMock
->expects($this->once())
->method('dumpFile')
- ->with('/aWebRoot/aCachePrefix/aFilter/aPath', 'theContent');
+ ->with(
+ $this->equalTo($fileUrl),
+ $this->equalTo($fileContent)
+ );
+
+ $pathResolver = $this->createPathResolverMock();
+ $pathResolver->method('getFilePath')
+ ->with(
+ $this->equalTo($path),
+ $this->equalTo($filter)
+ )
+ ->willReturn(
+ $fileUrl
+ );
$resolver = new WebPathResolver(
$filesystemMock,
- new RequestContext(),
- '/aWebRoot',
- 'aCachePrefix'
+ $pathResolver,
+ new RequestContext()
);
- $this->assertNull($resolver->store($binary, 'aPath', 'aFilter'));
+ $this->assertNull($resolver->store($binary, $path, $filter));
}
public function testDoNothingIfFiltersAndPathsEmptyOnRemove()
{
$filesystemMock = $this->createFilesystemMock();
- $filesystemMock
- ->expects($this->never())
- ->method('remove');
+ $filesystemMock->expects($this->never())->method('remove');
$resolver = new WebPathResolver(
$filesystemMock,
- new RequestContext(),
- '/aWebRoot',
- 'aCachePrefix'
+ $this->createPathResolverMock(),
+ new RequestContext()
);
$resolver->remove([], []);
@@ -346,17 +367,17 @@ public function testDoNothingIfFiltersAndPathsEmptyOnRemove()
public function testRemoveCacheForPathAndFilterOnRemove()
{
+ $filePath = '/aWebRoot/aCachePrefix/aFilter/aPath';
$filesystemMock = $this->createFilesystemMock();
- $filesystemMock
- ->expects($this->once())
- ->method('remove')
- ->with('/aWebRoot/aCachePrefix/aFilter/aPath');
+ $filesystemMock->expects($this->once())->method('remove')->with($filePath);
+
+ $pathResolver = $this->createPathResolverMock();
+ $pathResolver->method('getFilePath')->willReturn($filePath);
$resolver = new WebPathResolver(
$filesystemMock,
- new RequestContext(),
- '/aWebRoot',
- 'aCachePrefix'
+ $pathResolver,
+ new RequestContext()
);
$resolver->remove(['aPath'], ['aFilter']);
@@ -364,74 +385,124 @@ public function testRemoveCacheForPathAndFilterOnRemove()
public function testRemoveCacheForSomePathsAndFilterOnRemove()
{
+ $cacheRoot = '/aWebRoot/aCachePrefix';
+ $pathOne = 'aPathOne';
+ $pathTwo = 'aPathTwo';
+ $filter = 'aFilter';
+
$filesystemMock = $this->createFilesystemMock();
$filesystemMock
->expects($this->at(0))
->method('remove')
- ->with('/aWebRoot/aCachePrefix/aFilter/aPathOne');
+ ->with(
+ sprintf('%s/%s/%s', $cacheRoot, $filter, $pathOne)
+ );
$filesystemMock
->expects($this->at(1))
->method('remove')
- ->with('/aWebRoot/aCachePrefix/aFilter/aPathTwo');
+ ->with(
+ sprintf('%s/%s/%s', $cacheRoot, $filter, $pathTwo)
+ );
+
+ $pathResolver = $this->createPathResolverMock();
+ $pathResolver->method('getFilePath')
+ ->willReturnMap(
+ [
+ [$pathOne, $filter, sprintf('%s/%s/%s', $cacheRoot, $filter, $pathOne)],
+ [$pathTwo, $filter, sprintf('%s/%s/%s', $cacheRoot, $filter, $pathTwo)],
+ ]
+ );
$resolver = new WebPathResolver(
$filesystemMock,
- new RequestContext(),
- '/aWebRoot',
- 'aCachePrefix'
+ $pathResolver,
+ new RequestContext()
);
- $resolver->remove(['aPathOne', 'aPathTwo'], ['aFilter']);
+ $resolver->remove([$pathOne, $pathTwo], [$filter]);
}
public function testRemoveCacheForSomePathsAndSomeFiltersOnRemove()
{
+ $cacheRoot = '/aWebRoot/aCachePrefix';
+ $pathOne = 'aPathOne';
+ $pathTwo = 'aPathTwo';
+ $filterOne = 'aFilterOne';
+ $filterTwo = 'aFilterTwo';
+
$filesystemMock = $this->createFilesystemMock();
$filesystemMock
->expects($this->at(0))
->method('remove')
- ->with('/aWebRoot/aCachePrefix/aFilterOne/aPathOne');
+ ->with(
+ sprintf('%s/%s/%s', $cacheRoot, $filterOne, $pathOne)
+ );
$filesystemMock
->expects($this->at(1))
->method('remove')
- ->with('/aWebRoot/aCachePrefix/aFilterTwo/aPathOne');
+ ->with(
+ sprintf('%s/%s/%s', $cacheRoot, $filterTwo, $pathOne)
+ );
$filesystemMock
->expects($this->at(2))
->method('remove')
- ->with('/aWebRoot/aCachePrefix/aFilterOne/aPathTwo');
+ ->with(
+ sprintf('%s/%s/%s', $cacheRoot, $filterOne, $pathTwo)
+ );
$filesystemMock
->expects($this->at(3))
->method('remove')
- ->with('/aWebRoot/aCachePrefix/aFilterTwo/aPathTwo');
+ ->with(
+ sprintf('%s/%s/%s', $cacheRoot, $filterTwo, $pathTwo)
+ );
+
+ $pathResolver = $this->createPathResolverMock();
+ $pathResolver
+ ->method('getFilePath')
+ ->willReturnMap(
+ [
+ [$pathOne, $filterOne, sprintf('%s/%s/%s', $cacheRoot, $filterOne, $pathOne)],
+ [$pathOne, $filterTwo, sprintf('%s/%s/%s', $cacheRoot, $filterTwo, $pathOne)],
+ [$pathTwo, $filterOne, sprintf('%s/%s/%s', $cacheRoot, $filterOne, $pathTwo)],
+ [$pathTwo, $filterTwo, sprintf('%s/%s/%s', $cacheRoot, $filterTwo, $pathTwo)],
+ ]
+ );
$resolver = new WebPathResolver(
$filesystemMock,
- new RequestContext(),
- '/aWebRoot',
- 'aCachePrefix'
+ $pathResolver,
+ new RequestContext()
);
$resolver->remove(
- ['aPathOne', 'aPathTwo'],
- ['aFilterOne', 'aFilterTwo']
+ [$pathOne, $pathTwo],
+ [$filterOne, $filterTwo]
);
}
public function testRemoveCacheForFilterOnRemove()
{
+ $cacheRoot = '/aWebRoot/aCachePrefix';
+
$filesystemMock = $this->createFilesystemMock();
$filesystemMock
->expects($this->once())
->method('remove')
- ->with([
- '/aWebRoot/aCachePrefix/aFilter',
- ]);
+ ->with(
+ [
+ sprintf('%s/aFilter', $cacheRoot),
+ ]
+ );
+
+ $pathResolver = $this->createPathResolverMock();
+ $pathResolver
+ ->method('getCacheRoot')
+ ->willReturn($cacheRoot);
$resolver = new WebPathResolver(
$filesystemMock,
- new RequestContext(),
- '/aWebRoot',
- 'aCachePrefix'
+ $pathResolver,
+ new RequestContext()
);
$resolver->remove([], ['aFilter']);
@@ -439,59 +510,39 @@ public function testRemoveCacheForFilterOnRemove()
public function testRemoveCacheForSomeFiltersOnRemove()
{
+ $cacheRoot = '/aWebRoot/aCachePrefix';
+
$filesystemMock = $this->createFilesystemMock();
$filesystemMock
->expects($this->once())
->method('remove')
- ->with([
- '/aWebRoot/aCachePrefix/aFilterOne',
- '/aWebRoot/aCachePrefix/aFilterTwo',
- ]);
+ ->with(
+ [
+ sprintf('%s/aFilterOne', $cacheRoot),
+ sprintf('%s/aFilterTwo', $cacheRoot),
+ ]
+ );
+
+ $pathResolver = $this->createPathResolverMock();
+ $pathResolver
+ ->method('getCacheRoot')
+ ->willReturn($cacheRoot);
$resolver = new WebPathResolver(
$filesystemMock,
- new RequestContext(),
- '/aWebRoot',
- 'aCachePrefix'
+ $pathResolver,
+ new RequestContext()
);
$resolver->remove([], ['aFilterOne', 'aFilterTwo']);
}
- public function testShouldRemoveDoubleSlashInUrl()
- {
- $resolver = new WebPathResolver(
- $this->createFilesystemMock(),
- new RequestContext(),
- '/aWebRoot',
- 'aCachePrefix'
- );
-
- $rc = new \ReflectionClass($resolver);
- $method = $rc->getMethod('getFileUrl');
- $method->setAccessible(true);
-
- $result = $method->invokeArgs($resolver, ['/cats.jpg', 'some_filter']);
-
- $this->assertSame('aCachePrefix/some_filter/cats.jpg', $result);
- }
-
- public function testShouldSanitizeSeparatorBetweenSchemeAndAuthorityInUrl()
+ /**
+ * @return \PHPUnit\Framework\MockObject\MockObject|PathResolverInterface
+ */
+ public function createPathResolverMock()
{
- $resolver = new WebPathResolver(
- $this->createFilesystemMock(),
- new RequestContext(),
- '/aWebRoot',
- 'aCachePrefix'
- );
-
- $rc = new \ReflectionClass($resolver);
- $method = $rc->getMethod('getFileUrl');
- $method->setAccessible(true);
-
- $result = $method->invokeArgs($resolver, ['https://some.meme.com/cute/cats.jpg', 'some_filter']);
-
- $this->assertSame('aCachePrefix/some_filter/https---some.meme.com/cute/cats.jpg', $result);
+ return $this->getMockBuilder(PathResolverInterface::class)->getMock();
}
/**
diff --git a/Tests/LiipImagineBundleTest.php b/Tests/LiipImagineBundleTest.php
index 49cabb3e5..56a0ae930 100644
--- a/Tests/LiipImagineBundleTest.php
+++ b/Tests/LiipImagineBundleTest.php
@@ -21,6 +21,7 @@
use Liip\ImagineBundle\DependencyInjection\Factory\Loader\StreamLoaderFactory;
use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\AwsS3ResolverFactory;
use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\FlysystemResolverFactory;
+use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\RelativeWebPathResolverFactory;
use Liip\ImagineBundle\DependencyInjection\Factory\Resolver\WebPathResolverFactory;
use Liip\ImagineBundle\DependencyInjection\LiipImagineExtension;
use Liip\ImagineBundle\LiipImagineBundle;
@@ -146,8 +147,7 @@ public function testAddAwsS3ResolverFactoryOnBuild()
public function testAddFlysystemResolverFactoryOnBuild()
{
$extensionMock = $this->createLiipImagineExtensionMock();
- $extensionMock
- ->expects($this->at(2))
+ $extensionMock->expects($this->at(2))
->method('addResolverFactory')
->with($this->isInstanceOf(FlysystemResolverFactory::class));
@@ -156,25 +156,29 @@ public function testAddFlysystemResolverFactoryOnBuild()
->expects($this->atLeastOnce())
->method('getExtension')
->with('liip_imagine')
- ->willReturn($extensionMock);
+ ->willReturn(
+ $extensionMock
+ );
$bundle = new LiipImagineBundle();
$bundle->build($containerMock);
}
- public function testAddChainLoaderFactoryOnBuild()
+ public function testAddRelativeWebPAthResolverFactoryOnBuild()
{
$extensionMock = $this->createLiipImagineExtensionMock();
$extensionMock
- ->expects($this->at(6))
- ->method('addLoaderFactory')
- ->with($this->isInstanceOf(ChainLoaderFactory::class));
+ ->expects($this->at(3))
+ ->method('addResolverFactory')
+ ->with($this->isInstanceOf(RelativeWebPathResolverFactory::class));
+
$containerMock = $this->createContainerBuilderMock();
$containerMock
->expects($this->atLeastOnce())
->method('getExtension')
->with('liip_imagine')
->willReturn($extensionMock);
+
$bundle = new LiipImagineBundle();
$bundle->build($containerMock);
}
@@ -183,7 +187,7 @@ public function testAddStreamLoaderFactoryOnBuild()
{
$extensionMock = $this->createLiipImagineExtensionMock();
$extensionMock
- ->expects($this->at(3))
+ ->expects($this->at(4))
->method('addLoaderFactory')
->with($this->isInstanceOf(StreamLoaderFactory::class));
@@ -202,7 +206,7 @@ public function testAddFilesystemLoaderFactoryOnBuild()
{
$extensionMock = $this->createLiipImagineExtensionMock();
$extensionMock
- ->expects($this->at(4))
+ ->expects($this->at(5))
->method('addLoaderFactory')
->with($this->isInstanceOf(FileSystemLoaderFactory::class));
@@ -221,7 +225,7 @@ public function testAddFlysystemLoaderFactoryOnBuild()
{
$extensionMock = $this->createLiipImagineExtensionMock();
$extensionMock
- ->expects($this->at(5))
+ ->expects($this->at(6))
->method('addLoaderFactory')
->with($this->isInstanceOf(FlysystemLoaderFactory::class));
@@ -236,6 +240,23 @@ public function testAddFlysystemLoaderFactoryOnBuild()
$bundle->build($containerMock);
}
+ public function testAddChainLoaderFactoryOnBuild()
+ {
+ $extensionMock = $this->createLiipImagineExtensionMock();
+ $extensionMock
+ ->expects($this->at(7))
+ ->method('addLoaderFactory')
+ ->with($this->isInstanceOf(ChainLoaderFactory::class));
+ $containerMock = $this->createContainerBuilderMock();
+ $containerMock
+ ->expects($this->atLeastOnce())
+ ->method('getExtension')
+ ->with('liip_imagine')
+ ->willReturn($extensionMock);
+ $bundle = new LiipImagineBundle();
+ $bundle->build($containerMock);
+ }
+
/**
* @return \PHPUnit_Framework_MockObject_MockObject|ContainerBuilder
*/
@@ -249,10 +270,14 @@ protected function createContainerBuilderMock()
*/
protected function createLiipImagineExtensionMock()
{
- return $this->createObjectMock(LiipImagineExtension::class, [
- 'getNamespace',
- 'addResolverFactory',
- 'addLoaderFactory',
- ], false);
+ return $this->createObjectMock(
+ LiipImagineExtension::class,
+ [
+ 'getNamespace',
+ 'addResolverFactory',
+ 'addLoaderFactory',
+ ],
+ false
+ );
}
}
diff --git a/Tests/Utility/Path/PathResolverTest.php b/Tests/Utility/Path/PathResolverTest.php
new file mode 100644
index 000000000..74f7ea645
--- /dev/null
+++ b/Tests/Utility/Path/PathResolverTest.php
@@ -0,0 +1,221 @@
+assertTrue(is_a(PathResolver::class, PathResolverInterface::class, true));
+ }
+
+ public function testPropertiesForSameConstructorArguments(): void
+ {
+ $webRootDir = 'aWebRootDir';
+ $cachePrefix = 'aCachePrefix';
+ $pathResolver = new PathResolver($webRootDir, $cachePrefix);
+ $this->assertAttributeSame($webRootDir, 'webRoot', $pathResolver);
+ $this->assertAttributeSame($cachePrefix, 'cachePrefix', $pathResolver);
+ }
+
+ public function testWebRootPathNormalizer(): void
+ {
+ $pathResolver = new PathResolver('aWebRootDir/');
+ $this->assertAttributeSame('aWebRootDir', 'webRoot', $pathResolver);
+ }
+
+ public function testCachePrefixNormalizer(): void
+ {
+ $pathResolver = new PathResolver('aWebRootDir', '/cachePrefix');
+ $this->assertAttributeSame('cachePrefix', 'cachePrefix', $pathResolver);
+ }
+
+ public function testForDoubleSlashReplacing(): void
+ {
+ $pathResolver = new PathResolver(
+ 'aWebRootDir//subRootDir',
+ 'cachePrefix//subCacheDir'
+ );
+ $this->assertAttributeSame(
+ 'aWebRootDir/subRootDir',
+ 'webRoot',
+ $pathResolver
+ );
+ $this->assertAttributeSame(
+ 'cachePrefix/subCacheDir',
+ 'cachePrefix',
+ $pathResolver
+ );
+ }
+
+ public function testPathsNormalizerWithSubfolders(): void
+ {
+ $pathResolver = new PathResolver(
+ 'aWebRootDir/subRootDir',
+ 'cachePrefix/subCacheDir/anotherSubCacheDir'
+ );
+ $this->assertAttributeSame(
+ 'aWebRootDir/subRootDir',
+ 'webRoot',
+ $pathResolver
+ );
+ $this->assertAttributeSame(
+ 'cachePrefix/subCacheDir/anotherSubCacheDir',
+ 'cachePrefix',
+ $pathResolver
+ );
+ }
+
+ public function testCacheRootPathDirCreationWithoutInvalidSlashes(): void
+ {
+ $pathResolver = new PathResolver(
+ 'aWebRootDir/subRootDir',
+ 'cachePrefix/subCacheDir'
+ );
+ $this->assertAttributeSame(
+ 'aWebRootDir/subRootDir',
+ 'webRoot',
+ $pathResolver
+ );
+ $this->assertAttributeSame(
+ 'cachePrefix/subCacheDir',
+ 'cachePrefix',
+ $pathResolver
+ );
+ $this->assertAttributeSame(
+ 'aWebRootDir/subRootDir/cachePrefix/subCacheDir',
+ 'cacheRoot',
+ $pathResolver
+ );
+ }
+
+ public function testCacheRootPathDirCreationWithInvalidSlashes(): void
+ {
+ $pathResolver = new PathResolver(
+ 'aWebRootDir/subRootDir/',
+ '/cachePrefix/subCacheDir'
+ );
+ $this->assertAttributeSame(
+ 'aWebRootDir/subRootDir',
+ 'webRoot',
+ $pathResolver
+ );
+ $this->assertAttributeSame(
+ 'cachePrefix/subCacheDir',
+ 'cachePrefix',
+ $pathResolver
+ );
+ $this->assertAttributeSame(
+ 'aWebRootDir/subRootDir/cachePrefix/subCacheDir',
+ 'cacheRoot',
+ $pathResolver
+ );
+ }
+
+ public function testCacheRootPathDirCreationWithDoubledSlashes(): void
+ {
+ $pathResolver = new PathResolver(
+ 'aWebRootDir//subRootDir/',
+ '/cachePrefix//subCacheDir'
+ );
+ $this->assertAttributeSame(
+ 'aWebRootDir/subRootDir',
+ 'webRoot',
+ $pathResolver
+ );
+ $this->assertAttributeSame(
+ 'cachePrefix/subCacheDir',
+ 'cachePrefix',
+ $pathResolver
+ );
+ $this->assertAttributeSame(
+ 'aWebRootDir/subRootDir/cachePrefix/subCacheDir',
+ 'cacheRoot',
+ $pathResolver
+ );
+ }
+
+ public function testGetCacheRoot(): void
+ {
+ $pathResolver = new PathResolver(
+ 'aWebRootDir',
+ '/cachePrefix//subCacheDir'
+ );
+ $this->assertSame(
+ 'aWebRootDir/cachePrefix/subCacheDir',
+ $pathResolver->getCacheRoot()
+ );
+ }
+
+ public function testGetFileUrlWithSchemePath(): void
+ {
+ $path = 'https://path-to-no-where';
+ $filter = 'aFilter';
+ $cachePrefix = 'aCahcePrefix';
+
+ $pathResolver = new PathResolver('aWebRootDir', $cachePrefix);
+ $actualFileUrl = $pathResolver->getFileUrl($path, $filter);
+
+ $this->assertSame(sprintf('%s/%s/https---path-to-no-where', $cachePrefix, $filter), $actualFileUrl);
+ }
+
+ public function testGetFileUrlPathTrim(): void
+ {
+ $path = '/path-to-no-where';
+ $filter = 'aFilter';
+ $cachePrefix = 'aCahcePrefix';
+
+ $pathResolver = new PathResolver('aWebRootDir', $cachePrefix);
+ $actualFileUrl = $pathResolver->getFileUrl($path, $filter);
+
+ $this->assertSame(sprintf('%s/%s/path-to-no-where', $cachePrefix, $filter), $actualFileUrl);
+ }
+
+ public function testGetFilePathWithSchemePath(): void
+ {
+ $path = 'https://path-to-no-where';
+ $filter = 'aFilter';
+ $webRootDir = 'aWebRootDir';
+ $cachePrefix = 'aCahcePrefix';
+
+ $pathResolver = new PathResolver($webRootDir, $cachePrefix);
+ $actualFileUrl = $pathResolver->getFilePath($path, $filter);
+
+ $this->assertSame(
+ sprintf('%s/%s/%s/https---path-to-no-where', $webRootDir, $cachePrefix, $filter),
+ $actualFileUrl
+ );
+ }
+
+ public function testGetFilePathWithPathTrim(): void
+ {
+ $path = '/path-to-no-where';
+ $filter = 'aFilter';
+ $webRootDir = 'aWebRootDir';
+ $cachePrefix = 'aCahcePrefix';
+
+ $pathResolver = new PathResolver($webRootDir, $cachePrefix);
+ $actualFileUrl = $pathResolver->getFilePath($path, $filter);
+
+ $this->assertSame(
+ sprintf('%s/%s/%s/path-to-no-where', $webRootDir, $cachePrefix, $filter),
+ $actualFileUrl
+ );
+ }
+}
diff --git a/Utility/Path/PathResolver.php b/Utility/Path/PathResolver.php
new file mode 100644
index 000000000..8734cbde8
--- /dev/null
+++ b/Utility/Path/PathResolver.php
@@ -0,0 +1,73 @@
+webRoot = rtrim(str_replace('//', '/', $webRootDir), '/');
+ $this->cachePrefix = ltrim(str_replace('//', '/', $cachePrefix), '/');
+ $this->cacheRoot = $this->webRoot.'/'.$this->cachePrefix;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFilePath($path, $filter): string
+ {
+ return $this->webRoot.'/'.$this->getFullPath($path, $filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFileUrl($path, $filter): string
+ {
+ return PathHelper::filePathToUrlPath($this->getFullPath($path, $filter));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCacheRoot(): string
+ {
+ return $this->cacheRoot;
+ }
+
+ private function getFullPath($path, $filter): string
+ {
+ // crude way of sanitizing URL scheme ("protocol") part
+ $path = str_replace('://', '---', $path);
+
+ return $this->cachePrefix.'/'.$filter.'/'.ltrim($path, '/');
+ }
+}
diff --git a/Utility/Path/PathResolverInterface.php b/Utility/Path/PathResolverInterface.php
new file mode 100644
index 000000000..4e227f928
--- /dev/null
+++ b/Utility/Path/PathResolverInterface.php
@@ -0,0 +1,29 @@
+