From 5b9a8f4055c0f02a9033b3586c58f2580f72369b Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Thu, 4 Jul 2013 17:31:42 +0200 Subject: [PATCH] Add XSenfFile mapping generator --- CHANGELOG.md | 8 +- bin/console | 2 + .../Command/Setup/XSendFileMappingDumper.php | 2 + .../Setup/XSendFileMappingGenerator.php | 94 +++++++++++++++++++ lib/Alchemy/Phrasea/Core/Version.php | 2 +- .../Http/XSendFile/XSendFileFactory.php | 10 -- lib/classes/patch/3816.php | 70 ++++++++++++++ .../Setup/XSendFileMappingGeneratorTest.php | 66 +++++++++++++ .../Provider/FileServeServiceProviderTest.php | 2 +- 9 files changed, 242 insertions(+), 14 deletions(-) create mode 100644 lib/Alchemy/Phrasea/Command/Setup/XSendFileMappingGenerator.php create mode 100644 lib/classes/patch/3816.php create mode 100644 tests/Alchemy/Tests/Phrasea/Command/Setup/XSendFileMappingGeneratorTest.php 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);