diff --git a/bin/console b/bin/console
index 449afd50d7..4fb292526e 100755
--- a/bin/console
+++ b/bin/console
@@ -19,6 +19,8 @@ namespace KonsoleKommander;
use Alchemy\Phrasea\Command\Plugin\ListPlugin;
use Alchemy\Phrasea\Command\Setup\H264ConfigurationDumper;
use Alchemy\Phrasea\Command\Setup\H264MappingGenerator;
+use Alchemy\Phrasea\Command\Setup\StaticConfigurationDumper;
+use Alchemy\Phrasea\Command\Setup\StaticMappingGenerator;
use Alchemy\Phrasea\Core\Version;
use Alchemy\Phrasea\Command\BuildMissingSubdefs;
use Alchemy\Phrasea\Command\CreateCollection;
@@ -105,6 +107,9 @@ $cli->command(new H264MappingGenerator());
$cli->command(new XSendFileConfigurationDumper());
$cli->command(new XSendFileMappingGenerator());
+$cli->command(new StaticConfigurationDumper());
+$cli->command(new StaticMappingGenerator());
+
$cli->loadPlugins();
exit(is_int($cli->run()) ? : 1);
diff --git a/config/configuration.sample.yml b/config/configuration.sample.yml
index 8ea3bb4151..5402a00fe6 100644
--- a/config/configuration.sample.yml
+++ b/config/configuration.sample.yml
@@ -157,8 +157,12 @@ api_cors:
max_age: 0
hosts: []
session:
- idle: 0
- lifetime: 604800 # 1 week
+ idle: 0
+ lifetime: 604800 # 1 week
+static-file:
+ enabled: false
+ type: nginx
+ symlink-directory: ''
crossdomain:
site-control: 'master-only'
allow-access-from:
diff --git a/lib/Alchemy/Phrasea/Command/Setup/StaticConfigurationDumper.php b/lib/Alchemy/Phrasea/Command/Setup/StaticConfigurationDumper.php
new file mode 100644
index 0000000000..31c1ed223c
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Command/Setup/StaticConfigurationDumper.php
@@ -0,0 +1,60 @@
+setDescription('Dump the virtual host configuration depending on Phraseanet configuration');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doExecute(InputInterface $input, OutputInterface $output)
+ {
+ $output->writeln('');
+
+ if ($this->container['phraseanet.xsendfile-factory']->isXSendFileModeEnabled()) {
+ throw new \LogicException('XSendFile mode is already activated');
+ }
+
+ if (!$this->container['phraseanet.static-file-factory']->isStaticFileModeEnabled()) {
+ $output->writeln('Static file support is disabled');
+ $ret = 1;
+ } else {
+ $output->writeln('Static file support is enabled');
+ $ret = 0;
+ }
+
+ try {
+ $configuration = $this->container['phraseanet.static-file-factory']->getMode(true, true)->getVirtualHostConfiguration();
+ $output->writeln('Static file configuration seems OK');
+ $output->writeln($configuration);
+ } catch (RuntimeException $e) {
+ $output->writeln('Static file configuration seems invalid');
+ $ret = 1;
+ }
+
+ $output->writeln('');
+
+ return $ret;
+ }
+}
diff --git a/lib/Alchemy/Phrasea/Command/Setup/StaticMappingGenerator.php b/lib/Alchemy/Phrasea/Command/Setup/StaticMappingGenerator.php
new file mode 100644
index 0000000000..1ecaff8592
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Command/Setup/StaticMappingGenerator.php
@@ -0,0 +1,64 @@
+addOption('write', 'w', null, 'Writes the configuration')
+ ->addOption('enabled', 'e', null, 'Set the enable toggle to `true`')
+ ->addArgument('type', InputArgument::REQUIRED, 'The configuration type, either `nginx` or `apache`')
+ ->setDescription('Generates Phraseanet Static file configuration');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doExecute(InputInterface $input, OutputInterface $output)
+ {
+ $enabled = $input->getOption('enabled');
+ $type = strtolower($input->getArgument('type'));
+
+ $factory = new StaticFileFactory($this->container['monolog'], true, $type, $this->container['phraseanet.thumb-symlinker']);
+ $mode = $factory->getMode(true);
+
+ $conf = array(
+ 'enabled' => $enabled,
+ 'type' => $type,
+ 'mapping' => $mode->getMapping(),
+ );
+
+ if ($input->getOption('write')) {
+ $output->write("Writing configuration ...");
+ $this->container['phraseanet.configuration']['static-file'] = $conf;
+ $output->writeln(" OK");
+ $output->writeln("");
+ $output->write("It is now strongly recommended to use static-file:dump-configuration command to upgrade your virtual-host");
+ } else {
+ $output->writeln("Configuration will not be written, use --write option to write it");
+ $output->writeln("");
+ $output->writeln(Yaml::dump(array('static-file' => $conf), 4));
+ }
+
+ return 0;
+ }
+}
diff --git a/lib/Alchemy/Phrasea/Core/Provider/FileServeServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/FileServeServiceProvider.php
index a22ab5d29d..8ed200e297 100644
--- a/lib/Alchemy/Phrasea/Core/Provider/FileServeServiceProvider.php
+++ b/lib/Alchemy/Phrasea/Core/Provider/FileServeServiceProvider.php
@@ -14,6 +14,7 @@ namespace Alchemy\Phrasea\Core\Provider;
use Alchemy\Phrasea\Core\Event\Subscriber\XSendFileSubscriber;
use Alchemy\Phrasea\Http\H264PseudoStreaming\H264Factory;
use Alchemy\Phrasea\Http\ServeFileResponseFactory;
+use Alchemy\Phrasea\Http\StaticFile\StaticFileFactory;
use Alchemy\Phrasea\Http\XSendFile\XSendFileFactory;
use Silex\Application;
use Silex\ServiceProviderInterface;
@@ -33,10 +34,18 @@ class FileServeServiceProvider implements ServiceProviderInterface
return H264Factory::create($app);
});
+ $app['phraseanet.static-file-factory'] = $app->share(function ($app) {
+ return StaticFileFactory::create($app);
+ });
+
$app['phraseanet.h264'] = $app->share(function ($app) {
return $app['phraseanet.h264-factory']->createMode(false);
});
+ $app['phraseanet.static-file'] = $app->share(function ($app) {
+ return $app['phraseanet.static-file-factory']->getMode(false);
+ });
+
$app['phraseanet.file-serve'] = $app->share(function (Application $app) {
return ServeFileResponseFactory::create($app);
});
diff --git a/lib/Alchemy/Phrasea/Core/Provider/PhraseanetServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/PhraseanetServiceProvider.php
index 1719745b3a..7a4caaa0d6 100644
--- a/lib/Alchemy/Phrasea/Core/Provider/PhraseanetServiceProvider.php
+++ b/lib/Alchemy/Phrasea/Core/Provider/PhraseanetServiceProvider.php
@@ -11,6 +11,8 @@
namespace Alchemy\Phrasea\Core\Provider;
+use Alchemy\Phrasea\Http\StaticFile\Symlink\SymLinker;
+use Alchemy\Phrasea\Http\StaticFile\Symlink\SymLinkerEncoder;
use Alchemy\Phrasea\Metadata\PhraseanetMetadataReader;
use Alchemy\Phrasea\Metadata\PhraseanetMetadataSetter;
use Alchemy\Phrasea\Security\Firewall;
@@ -41,6 +43,14 @@ class PhraseanetServiceProvider implements ServiceProviderInterface
return $events;
});
+ $app['phraseanet.thumb-symlinker'] = $app->share(function (SilexApplication $app) {
+ return SymLinker::create($app);
+ });
+
+ $app['phraseanet.thumb-symlinker-encoder'] = $app->share(function (SilexApplication $app) {
+ return SymLinkerEncoder::create($app);
+ });
+
$app['phraseanet.metadata-reader'] = $app->share(function (SilexApplication $app) {
$reader = new PhraseanetMetadataReader();
diff --git a/lib/Alchemy/Phrasea/Core/Version.php b/lib/Alchemy/Phrasea/Core/Version.php
index 209e36a2e8..cdffc01ed5 100644
--- a/lib/Alchemy/Phrasea/Core/Version.php
+++ b/lib/Alchemy/Phrasea/Core/Version.php
@@ -11,14 +11,9 @@
namespace Alchemy\Phrasea\Core;
-/**
- *
- * @license http://opensource.org/licenses/gpl-3.0 GPLv3
- * @link www.phraseanet.com
- */
class Version
{
- protected static $number = '3.8.6-alpha.2';
+ protected static $number = '3.8.6-alpha.3';
protected static $name = 'Falcarius';
public static function getNumber()
diff --git a/lib/Alchemy/Phrasea/Http/StaticFile/AbstractStaticMode.php b/lib/Alchemy/Phrasea/Http/StaticFile/AbstractStaticMode.php
new file mode 100644
index 0000000000..a87237450c
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Http/StaticFile/AbstractStaticMode.php
@@ -0,0 +1,50 @@
+symlinker = $symlinker;
+
+ parent::__construct($mapping);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getUrl($pathFile)
+ {
+ $this->ensureSymlink($pathFile);
+
+ return Url::factory(sprintf('%s/%s', $this->mapping['mount-point'], $this->symlinker->getSymlinkBasePath($pathFile)));
+ }
+
+ /**
+ * Creates a link if it does not exists
+ *
+ * @param $pathFile
+ */
+ private function ensureSymlink($pathFile)
+ {
+ if (false === $this->symlinker->hasSymlink($pathFile)) {
+ $this->symlinker->symlink($pathFile);
+ }
+ }
+}
diff --git a/lib/Alchemy/Phrasea/Http/StaticFile/Apache.php b/lib/Alchemy/Phrasea/Http/StaticFile/Apache.php
new file mode 100644
index 0000000000..f200550987
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Http/StaticFile/Apache.php
@@ -0,0 +1,52 @@
+mapping = $mapping;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getVirtualHostConfiguration()
+ {
+ $output = "\n";
+ $output .= " Alias ".$this->mapping['mount-point']." ".$this->mapping['directory']."\n";
+ $output .= "\n";
+ $output .= " mapping['directory'].">\n";
+ $output .= " Order allow,deny\n";
+ $output .= " Allow from all\n";
+ $output .= " \n";
+ $output .= "\n";
+
+ return $output;
+ }
+}
diff --git a/lib/Alchemy/Phrasea/Http/StaticFile/Nginx.php b/lib/Alchemy/Phrasea/Http/StaticFile/Nginx.php
new file mode 100644
index 0000000000..a105f93336
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Http/StaticFile/Nginx.php
@@ -0,0 +1,48 @@
+mapping = $mapping;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getVirtualHostConfiguration()
+ {
+ $output = "\n";
+ $output .= " location " . $this->mapping['mount-point']. " {\n";
+ $output .= " alias ".$this->mapping['directory'].";\n";
+ $output .= " }\n";
+
+ return $output;
+ }
+}
diff --git a/lib/Alchemy/Phrasea/Http/StaticFile/NullMode.php b/lib/Alchemy/Phrasea/Http/StaticFile/NullMode.php
new file mode 100644
index 0000000000..9a9f40608c
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Http/StaticFile/NullMode.php
@@ -0,0 +1,30 @@
+logger = $logger;
+ $this->enabled = (Boolean) $enabled;
+ $this->type = strtolower($type);
+ $this->symlinker = $symlinker;
+
+ $this->mapping = array(
+ 'mount-point' => $symlinker->getDefaultAlias(),
+ 'directory' => $symlinker->getSymlinkDir()
+ );
+ }
+
+ /**
+ * Creates a new instance of StaticFileFactory Factory according to the application
+ * configuration.
+ *
+ * @param Application $app
+ * @return StaticFileFactory
+ */
+ public static function create(Application $app)
+ {
+ $conf = $app['phraseanet.configuration']['static-file'];
+
+ return new self($app['monolog'], $conf['enabled'], $conf['type'], $app['phraseanet.thumb-symlinker']);
+ }
+
+ /**
+ * Returns a new instance of ModeInterface
+ *
+ * @param bool $throwException
+ * @param bool $forceMode
+ *
+ * @return Apache|Nginx|NullMode
+ * @throws InvalidArgumentException
+ */
+ public function getMode($throwException = false, $forceMode = false)
+ {
+ if (false === $this->enabled && true !== $forceMode) {
+ return new NullMode();
+ }
+
+ switch ($this->type) {
+ case 'nginx':
+ return new Nginx($this->mapping, $this->symlinker);
+ break;
+ case 'apache':
+ case 'apache2':
+ return new Apache($this->mapping, $this->symlinker);
+ default:
+ $this->logger->error('Invalid static file configuration.');
+ if ($throwException) {
+ throw new InvalidArgumentException(sprintf(
+ 'Invalid static file type value "%s"',
+ $this->type
+ ));
+ }
+
+ return new NullMode();
+ }
+ }
+
+ /**
+ * @return bool
+ */
+ public function isStaticFileModeEnabled()
+ {
+ return $this->enabled;
+ }
+}
diff --git a/lib/Alchemy/Phrasea/Http/StaticFile/StaticFileModeInterface.php b/lib/Alchemy/Phrasea/Http/StaticFile/StaticFileModeInterface.php
new file mode 100644
index 0000000000..33a9ad31ee
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Http/StaticFile/StaticFileModeInterface.php
@@ -0,0 +1,25 @@
+encoder = $encoder;
+ $this->fs = $fs;
+ $this->symlinkDir = rtrim($symlinkDir, '/');
+ }
+
+ public function getSymlinkDir()
+ {
+ return $this->symlinkDir;
+ }
+
+ public function getDefaultAlias()
+ {
+ return sprintf('/%s', self::ALIAS);
+ }
+
+ public function symlink($pathFile)
+ {
+ $this->fs->symlink($pathFile, $this->getSymlinkPath($pathFile)) ;
+ }
+
+ public function getSymlink($pathFile)
+ {
+ return $this->encoder->encode($pathFile);
+ }
+
+ public function getSymlinkBasePath($pathFile)
+ {
+ $symlinkName = $this->getSymlink($pathFile);
+
+ return sprintf('%s/%s/%s',
+ substr($symlinkName, 0, 2),
+ substr($symlinkName, 2, 2),
+ substr($symlinkName, 4)
+ );
+ }
+
+ public function getSymlinkPath($pathFile)
+ {
+ return sprintf(
+ '%s/%s',
+ $this->symlinkDir,
+ $this->getSymlinkBasePath($pathFile)
+ );
+ }
+
+ public function hasSymlink($pathFile)
+ {
+ return file_exists($this->getSymlinkPath($pathFile));
+ }
+}
diff --git a/lib/Alchemy/Phrasea/Http/StaticFile/Symlink/SymLinkerEncoder.php b/lib/Alchemy/Phrasea/Http/StaticFile/Symlink/SymLinkerEncoder.php
new file mode 100644
index 0000000000..b659d4e912
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Http/StaticFile/Symlink/SymLinkerEncoder.php
@@ -0,0 +1,38 @@
+key = $key;
+ }
+
+ public function encode($pathFile)
+ {
+ return hash_hmac('sha512', $pathFile , $this->key);
+ }
+}
diff --git a/lib/classes/databox.php b/lib/classes/databox.php
index 51f7977a5a..fd2f61a2b3 100644
--- a/lib/classes/databox.php
+++ b/lib/classes/databox.php
@@ -445,6 +445,21 @@ class databox extends base
public function unmount_databox()
{
+ if ($this->app['phraseanet.static-file-factory']->isStaticFileModeEnabled()) {
+ $sql = "SELECT path, file FROM subdef WHERE `name`='thumbnail'";
+ $stmt = $this->get_connection()->prepare($sql);
+ $stmt->execute();
+ $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
+ $stmt->closeCursor();
+ foreach ($rows as $row) {
+ $pathfile = $this->app['phraseanet.thumb-symlinker']->getSymlinkPath(sprintf(
+ '%s/%s',
+ rtrim($row['path'], '/'),
+ $row['file']
+ ));
+ $this->app['filesystem']->remove($pathfile);
+ }
+ }
foreach ($this->get_collections() as $collection) {
$collection->unmount_collection($this->app);
}
diff --git a/lib/classes/media/subdef.php b/lib/classes/media/subdef.php
index 08e264ab71..563880e7dc 100644
--- a/lib/classes/media/subdef.php
+++ b/lib/classes/media/subdef.php
@@ -730,6 +730,10 @@ class media_subdef extends media_abstract implements cache_cacheableInterface
$subdef->get_permalink()->delete_data_from_cache();
}
+ if ($name === 'thumbnail' && $app['phraseanet.static-file-factory']->isStaticFileModeEnabled()) {
+ $app['phraseanet.thumb-symlinker']->symlink($subdef->get_pathfile());
+ }
+
unset($media);
return $subdef;
@@ -742,10 +746,18 @@ class media_subdef extends media_abstract implements cache_cacheableInterface
*/
protected function generate_url()
{
- if ( ! $this->is_physically_present()) {
+ if (!$this->is_physically_present()) {
return;
}
+ if ($this->get_name() === 'thumbnail') {
+ if ($this->app['phraseanet.static-file-factory']->isStaticFileModeEnabled() && null !== $url = $this->app['phraseanet.static-file']->getUrl($this->get_pathfile())) {
+ $this->url = $url;
+
+ return;
+ }
+ }
+
if ($this->app['phraseanet.h264-factory']->isH264Enabled() && in_array($this->mime, array('video/mp4'))) {
if (null !== $url = $this->app['phraseanet.h264']->getUrl($this->get_pathfile())) {
$this->url = $url;
@@ -758,6 +770,7 @@ class media_subdef extends media_abstract implements cache_cacheableInterface
. "/" . $this->record->get_record_id() . "/"
. $this->get_name() . "/");
+
return;
}
diff --git a/lib/classes/patch/386alpha3a.php b/lib/classes/patch/386alpha3a.php
new file mode 100644
index 0000000000..58350db477
--- /dev/null
+++ b/lib/classes/patch/386alpha3a.php
@@ -0,0 +1,65 @@
+release;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function require_all_upgrades()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function concern()
+ {
+ return $this->concern;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function apply(base $appbox, Application $app)
+ {
+ $config = $app['phraseanet.configuration']->getConfig();
+
+ $config['static-file'] = array(
+ 'enabled' => false,
+ 'type' => '',
+ 'symlink-directory' => '',
+ );
+
+ $app['phraseanet.configuration']->setConfig($config);
+
+ return true;
+ }
+}
diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php
index 31e528cfd0..03ebc4bde4 100644
--- a/lib/classes/record/adapter.php
+++ b/lib/classes/record/adapter.php
@@ -1514,6 +1514,10 @@ class record_adapter implements record_Interface, cache_cacheableInterface
if (!$subdef->is_physically_present())
continue;
+ if ($subdef->get_name() === 'thumbnail' && $this->app['phraseanet.static-file-factory']->isStaticFileModeEnabled()) {
+ $this->app['filesystem']->remove($this->app['phraseanet.thumb-symlinker']->getSymlinkPath($subdef->get_pathfile()));
+ }
+
$ftodel[] = $subdef->get_pathfile();
$watermark = $subdef->get_path() . 'watermark_' . $subdef->get_file();
if (file_exists($watermark))
diff --git a/lib/conf.d/configuration.yml b/lib/conf.d/configuration.yml
index d11f93caaf..3f5dfc2cac 100644
--- a/lib/conf.d/configuration.yml
+++ b/lib/conf.d/configuration.yml
@@ -163,6 +163,10 @@ session:
idle: 0
# 1 week
lifetime: 604800
+static-file:
+ enabled: false
+ type: nginx
+ symlink-directory: ''
crossdomain:
allow-access-from:
-
diff --git a/templates/web/prod/results/record.html.twig b/templates/web/prod/results/record.html.twig
index f2c96a2175..330df541f8 100644
--- a/templates/web/prod/results/record.html.twig
+++ b/templates/web/prod/results/record.html.twig
@@ -59,9 +59,10 @@
{% if rollover_gif %}
{% set extraclass = 'rollover-gif-out' %}
{% endif %}
- {{thumbnail.format(record.get_thumbnail(), th_size, th_size, extraclass, true, true)}}
+ {% set lazyload = not app['phraseanet.static-file-factory'].isStaticFileModeEnabled %}
+ {{thumbnail.format(record.get_thumbnail(), th_size, th_size, extraclass, true, lazyload)}}
{% if rollover_gif %}
- {{thumbnail.format(rollover_gif, th_size, th_size, 'rollover-gif-hover', true, true)}}
+ {{thumbnail.format(rollover_gif, th_size, th_size, 'rollover-gif-hover', true, lazyload)}}
{% endif %}
diff --git a/tests/Alchemy/Tests/Phrasea/Http/StaticFile/ApacheModeTest.php b/tests/Alchemy/Tests/Phrasea/Http/StaticFile/ApacheModeTest.php
new file mode 100644
index 0000000000..39a90c1a42
--- /dev/null
+++ b/tests/Alchemy/Tests/Phrasea/Http/StaticFile/ApacheModeTest.php
@@ -0,0 +1,37 @@
+ __DIR__,
+ 'mount-point' => '/thumbs'
+ ), self::$DI['app']['phraseanet.thumb-symlinker']);
+ $conf = $mode->getVirtualHostConfiguration();
+ $this->assertRegExp('#'.__DIR__ . '#', $conf);
+ }
+
+ /**
+ * @dataProvider provideMappings
+ * @expectedException Alchemy\Phrasea\Exception\InvalidArgumentException
+ */
+ public function testInvalidMapping($mapping)
+ {
+ new Apache($mapping, self::$DI['app']['phraseanet.thumb-symlinker']);
+ }
+
+ public function provideMappings()
+ {
+ return array(
+ array(array('Directory' => __DIR__)),
+ array(array('wrong-key' => __DIR__, 'mount-point' => '/')),
+ array(array('directory' => __DIR__, 'wrong-key' => '/')),
+ );
+ }
+}
diff --git a/tests/Alchemy/Tests/Phrasea/Http/StaticFile/NginxModeTest.php b/tests/Alchemy/Tests/Phrasea/Http/StaticFile/NginxModeTest.php
new file mode 100644
index 0000000000..1f89f488d0
--- /dev/null
+++ b/tests/Alchemy/Tests/Phrasea/Http/StaticFile/NginxModeTest.php
@@ -0,0 +1,37 @@
+ __DIR__,
+ 'mount-point' => '/thumbs'
+ ), self::$DI['app']['phraseanet.thumb-symlinker']);
+ $conf = $mode->getVirtualHostConfiguration();
+ $this->assertRegExp('#'.__DIR__ . '#', $conf);
+ }
+
+ /**
+ * @dataProvider provideMappings
+ * @expectedException Alchemy\Phrasea\Exception\InvalidArgumentException
+ */
+ public function testInvalidMapping($mapping)
+ {
+ new Nginx($mapping, self::$DI['app']['phraseanet.thumb-symlinker']);
+ }
+
+ public function provideMappings()
+ {
+ return array(
+ array(array('Directory' => __DIR__)),
+ array(array('wrong-key' => __DIR__, 'mount-point' => '/')),
+ array(array('directory' => __DIR__, 'wrong-key' => '/')),
+ );
+ }
+}
diff --git a/tests/Alchemy/Tests/Phrasea/Http/StaticFile/StaticFileFactoryTest.php b/tests/Alchemy/Tests/Phrasea/Http/StaticFile/StaticFileFactoryTest.php
new file mode 100644
index 0000000000..450ad0e7d2
--- /dev/null
+++ b/tests/Alchemy/Tests/Phrasea/Http/StaticFile/StaticFileFactoryTest.php
@@ -0,0 +1,54 @@
+assertInstanceOf('Alchemy\Phrasea\Http\StaticFile\StaticFileFactory', $factory);
+ }
+
+ public function testFactoryWithStaticFileEnable()
+ {
+ $logger = $this->getMock('Psr\Log\LoggerInterface');
+
+ $factory = new StaticFileFactory($logger, true, 'nginx', self::$DI['app']['phraseanet.thumb-symlinker']);
+ $this->assertInstanceOf('Alchemy\Phrasea\Http\StaticFile\AbstractStaticMode', $factory->getMode());
+ }
+
+ public function testFactoryWithStaticFileDisabled()
+ {
+ $logger = $this->getMock('Psr\Log\LoggerInterface');
+
+ $factory = new StaticFileFactory($logger, false, 'nginx', self::$DI['app']['phraseanet.thumb-symlinker']);
+ $this->assertInstanceOf('Alchemy\Phrasea\Http\StaticFile\NullMode', $factory->getMode());
+ $this->assertFalse($factory->isStaticFileModeEnabled());
+ }
+
+ /**
+ * @expectedException Alchemy\Phrasea\Exception\InvalidArgumentException
+ */
+ public function testFactoryWithWrongTypeThrowsAnExceptionIfRequired()
+ {
+ $logger = $this->getMock('Psr\Log\LoggerInterface');
+
+ $factory = new StaticFileFactory($logger, true, 'wrong-type', self::$DI['app']['phraseanet.thumb-symlinker']);
+ $factory->getMode(true);
+ }
+
+ public function testFactoryWithWrongTypeDoesNotThrowsAnException()
+ {
+ $logger = $this->getMock('Psr\Log\LoggerInterface');
+
+ $logger->expects($this->once())
+ ->method('error')
+ ->with($this->isType('string'));
+
+ $factory = new StaticFileFactory($logger, true, 'wrong-type', self::$DI['app']['phraseanet.thumb-symlinker']);
+ $this->assertInstanceOf('Alchemy\Phrasea\Http\StaticFile\NullMode', $factory->getMode(false));
+ }
+}