diff --git a/CHANGELOG.md b/CHANGELOG.md
index 63584aa72e..b967c7d18e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,7 +5,7 @@
- BC Break : Removed `bin/console check:config` command.
- BC Break : Removed `bin/console check:system` command, replaced by `bin/setup check:system`.
- BC Break : Removed `bin/console system:upgrade` command, replaced by `bin/setup system:upgrade`.
- - BC Break : Removed `bin/console check:ensure-production-settings` and `bin/console check:ensure-dev-settings`
+ - BC Break : Removed `bin/console check:ensure-production-settings` and `bin/console check:ensure-dev-settings`
commands, replaced by `bin/console check:config`.
- BC break : Configuration simplification, optimized for performances.
- BC Break : Time limits are now applied on templates application.
@@ -19,7 +19,6 @@
- Add bin/setup command utility, it is now recommanded to use `bin/setup system:install`
command to install Phraseanet.
- Lots of cleanup and code refactorisation.
- - Add task-manager logging to syslog.
- Add bin/console mail:test command to check email configuration.
- Admin databox structure fields editing redesigned.
- Refactor of the configuration tester.
@@ -38,6 +37,11 @@
- Add records sent-by-mail report.
- User time limit restrictions can now be set per databox.
- Add gzip/bzip2 options for DBs backup commandline tool.
+ - Add convenient XSendFile configuration tools in bin/console :
+ - bin/console xsendfile:configuration-generator that generates your
+ xsendfile mapping depending on databoxes configuration.
+ - bin/console xsendfile:configuration-dumper that dumps your virtual
+ host configuration depending on Phraseanet configuration
* 3.7.13 (2013-07-04)
diff --git a/bin/console b/bin/console
index fde0803660..b7ee8fbfaf 100755
--- a/bin/console
+++ b/bin/console
@@ -29,6 +29,7 @@ use Alchemy\Phrasea\Command\Plugin\AddPlugin;
use Alchemy\Phrasea\Command\Plugin\RemovePlugin;
use Alchemy\Phrasea\Command\CheckConfig;
use Alchemy\Phrasea\Command\Setup\XSendFileMappingDumper;
+use Alchemy\Phrasea\Command\Setup\XSendFileMappingGenerator;
require_once __DIR__ . '/../lib/autoload.php';
@@ -98,6 +99,7 @@ try {
$cli->command(new RemovePlugin());
$cli->command(new Configuration());
$cli->command(new XSendFileMappingDumper());
+ $cli->command(new XSendFileMappingGenerator());
call_user_func(function ($cli) {
require $cli['plugins.directory'] . '/commands.php';
diff --git a/lib/Alchemy/Phrasea/Command/Setup/XSendFileMappingDumper.php b/lib/Alchemy/Phrasea/Command/Setup/XSendFileMappingDumper.php
index aa61c2a83e..a06b9203c0 100644
--- a/lib/Alchemy/Phrasea/Command/Setup/XSendFileMappingDumper.php
+++ b/lib/Alchemy/Phrasea/Command/Setup/XSendFileMappingDumper.php
@@ -20,6 +20,8 @@ class XSendFileMappingDumper extends Command
{
public function __construct($name = null) {
parent::__construct('xsendfile:configuration-dumper');
+
+ $this->setDescription('Dump the virtual host configuration depending on Phraseanet configuration');
}
/**
diff --git a/lib/Alchemy/Phrasea/Command/Setup/XSendFileMappingGenerator.php b/lib/Alchemy/Phrasea/Command/Setup/XSendFileMappingGenerator.php
new file mode 100644
index 0000000000..27464f838b
--- /dev/null
+++ b/lib/Alchemy/Phrasea/Command/Setup/XSendFileMappingGenerator.php
@@ -0,0 +1,94 @@
+addOption('write', 'w', null, 'Writes the configuration')
+ ->addOption('enabled', 'e', null, 'Set the enable toggle to `true`')
+ ->addArgument('type', null, 'The configuration type, either `nginx` or `apache`')
+ ->setDescription('Generates Phraseanet xsendfile mapping configuration depending on databoxes configuration');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doExecute(InputInterface $input, OutputInterface $output)
+ {
+ $paths = $this->extractPath($this->container['phraseanet.appbox']);
+ $type = strtolower($input->getArgument('type'));
+ $enabled = $input->getOption('enabled');
+
+ if (!in_array($type, array('nginx', 'apache'))) {
+ throw new InvalidArgumentException('Invalid type %s, available types are `nginx` or `apache`');
+ }
+
+ $conf = array(
+ 'enabled' => $enabled,
+ 'type' => $type,
+ 'mapping' => $this->computeMapping($paths),
+ );
+
+ if ($input->getOption('write')) {
+ $output->write("Writing configuration ...");
+ $this->container['phraseanet.configuration']['xsendfile'] = $conf;
+ $output->writeln(" OK");
+ $output->writeln("");
+ $output->write("It now strongly recommended to use xsendfile:configuration-dumper 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('xsendfile' => $conf), 4));
+ }
+
+ return 0;
+ }
+
+ private function computeMapping($paths)
+ {
+ return array_merge(array(
+ array('mount-point' => 'lazaret', 'directory' => $this->container['root.path'] . '/tmp/lazaret'),
+ array('mount-point' => 'download', 'directory' => $this->container['root.path'] . '/tmp/download'),
+ ), array_map(array($this, 'pathsToConf'), array_unique($paths)));
+ }
+
+ private function pathsToConf($path)
+ {
+ static $n = 0;
+ $n++;
+
+ return array('mount-point' => 'protected_dir_'.$n, 'directory' => $path);
+ }
+
+ private function extractPath(\appbox $appbox)
+ {
+ foreach ($appbox->get_databoxes() as $databox) {
+ $paths[] = (string) $databox->get_sxml_structure()->path;
+ foreach ($databox->get_subdef_structure() as $group => $subdefs) {
+ foreach ($subdefs as $subdef) {
+ $paths[] = $subdef->get_path();
+ }
+ }
+ }
+
+ return array_unique($paths);
+ }
+}
diff --git a/lib/Alchemy/Phrasea/Core/Version.php b/lib/Alchemy/Phrasea/Core/Version.php
index 25cbf6b73d..5a26a347e8 100644
--- a/lib/Alchemy/Phrasea/Core/Version.php
+++ b/lib/Alchemy/Phrasea/Core/Version.php
@@ -18,7 +18,7 @@ namespace Alchemy\Phrasea\Core;
*/
class Version
{
- protected static $number = '3.8.0.a15';
+ protected static $number = '3.8.0.a16';
protected static $name = 'Carnosaurus';
public static function getNumber()
diff --git a/lib/Alchemy/Phrasea/Http/XSendFile/XSendFileFactory.php b/lib/Alchemy/Phrasea/Http/XSendFile/XSendFileFactory.php
index f8449fdc4e..b1b9b71d5d 100644
--- a/lib/Alchemy/Phrasea/Http/XSendFile/XSendFileFactory.php
+++ b/lib/Alchemy/Phrasea/Http/XSendFile/XSendFileFactory.php
@@ -56,16 +56,6 @@ class XSendFileFactory
$mapping = $conf['mapping'];
}
- $mapping[] = array(
- 'directory' => $app['root.path'] . '/tmp/download/',
- 'mount-point' => '/download/',
- );
-
- $mapping[] = array(
- 'directory' => $app['root.path'] . '/tmp/lazaret/',
- 'mount-point' => '/lazaret/',
- );
-
return new self($app['monolog'], $conf['enabled'], $conf['type'], $mapping);
}
diff --git a/lib/classes/patch/3816.php b/lib/classes/patch/3816.php
new file mode 100644
index 0000000000..2bd3840acb
--- /dev/null
+++ b/lib/classes/patch/3816.php
@@ -0,0 +1,70 @@
+release;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function require_all_upgrades()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function concern()
+ {
+ return $this->concern;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function apply(base $appbox, Application $app)
+ {
+ $xsendfile = $app['phraseanet.configuration']['xsendfile'];
+
+ if (!isset($xsendfile['mapping'])) {
+ $xsendfile['mapping'] = array();
+ }
+
+ $xsendfile['mapping'][] = array(
+ 'directory' => $app['root.path'] . '/tmp/lazaret/',
+ 'mount-point' => '/lazaret/',
+ );
+ $xsendfile['mapping'][] = array(
+ 'directory' => $app['root.path'] . '/tmp/download/',
+ 'mount-point' => '/download/',
+ );
+
+ $app['phraseanet.configuration']['xsendfile'] = $xsendfile;
+
+ return true;
+ }
+}
diff --git a/tests/Alchemy/Tests/Phrasea/Command/Setup/XSendFileMappingGeneratorTest.php b/tests/Alchemy/Tests/Phrasea/Command/Setup/XSendFileMappingGeneratorTest.php
new file mode 100644
index 0000000000..0b38c6c99d
--- /dev/null
+++ b/tests/Alchemy/Tests/Phrasea/Command/Setup/XSendFileMappingGeneratorTest.php
@@ -0,0 +1,66 @@
+getMock('Symfony\Component\Console\Input\InputInterface');
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $input->expects($this->any())
+ ->method('getArgument')
+ ->with('type')
+ ->will($this->returnValue('nginx'));
+
+ $input->expects($this->any())
+ ->method('getOption')
+ ->with($this->isType('string'))
+ ->will($this->returnValue($option));
+
+ $command = new XSendFileMappingGenerator();
+
+ self::$DI['app']['phraseanet.configuration'] = $this->getMock('Alchemy\Phrasea\Core\Configuration\ConfigurationInterface');
+ if ($option) {
+ self::$DI['app']['phraseanet.configuration']->expects($this->once())
+ ->method('offsetSet')
+ ->with('xsendfile');
+ } else {
+ self::$DI['app']['phraseanet.configuration']->expects($this->never())
+ ->method('offsetSet');
+ }
+ $command->setContainer(self::$DI['app']);
+
+ $this->assertEquals(0, $command->execute($input, $output));
+ }
+
+ public function testRunWithProblem()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $input->expects($this->any())
+ ->method('getArgument')
+ ->with('type')
+ ->will($this->returnValue(null));
+
+ $command = new XSendFileMappingGenerator();
+ $command->setContainer(self::$DI['app']);
+ $this->setExpectedException('Alchemy\Phrasea\Exception\InvalidArgumentException');
+ $command->execute($input, $output);
+ }
+
+ public function provideVariousOptions()
+ {
+ return array(
+ array(true),
+ array(false),
+ );
+ }
+}
\ No newline at end of file
diff --git a/tests/Alchemy/Tests/Phrasea/Core/Provider/FileServeServiceProviderTest.php b/tests/Alchemy/Tests/Phrasea/Core/Provider/FileServeServiceProviderTest.php
index 53d71d627e..ce19687235 100644
--- a/tests/Alchemy/Tests/Phrasea/Core/Provider/FileServeServiceProviderTest.php
+++ b/tests/Alchemy/Tests/Phrasea/Core/Provider/FileServeServiceProviderTest.php
@@ -36,7 +36,7 @@ class FileServeServiceProviderTest extends ServiceProviderTestCase
$app['phraseanet.configuration.config-path'] = __DIR__ . '/fixtures/config-mapping.yml';
$app['phraseanet.configuration.config-compiled-path'] = __DIR__ . '/fixtures/config-mapping.php';
$this->assertInstanceOf('Alchemy\Phrasea\Http\XSendFile\NginxMode', $app['phraseanet.xsendfile-factory']->getMode());
- $this->assertEquals(3, count($app['phraseanet.xsendfile-factory']->getMode()->getMapping()));
+ $this->assertEquals(1, count($app['phraseanet.xsendfile-factory']->getMode()->getMapping()));
unlink($app['phraseanet.configuration.config-compiled-path']);
unset($app);