Add XSenfFile mapping generator

This commit is contained in:
Romain Neutron
2013-07-04 17:31:42 +02:00
parent 81c5411212
commit 5b9a8f4055
9 changed files with 242 additions and 14 deletions

View File

@@ -19,7 +19,6 @@
- Add bin/setup command utility, it is now recommanded to use `bin/setup system:install` - Add bin/setup command utility, it is now recommanded to use `bin/setup system:install`
command to install Phraseanet. command to install Phraseanet.
- Lots of cleanup and code refactorisation. - Lots of cleanup and code refactorisation.
- Add task-manager logging to syslog.
- Add bin/console mail:test command to check email configuration. - Add bin/console mail:test command to check email configuration.
- Admin databox structure fields editing redesigned. - Admin databox structure fields editing redesigned.
- Refactor of the configuration tester. - Refactor of the configuration tester.
@@ -38,6 +37,11 @@
- Add records sent-by-mail report. - Add records sent-by-mail report.
- User time limit restrictions can now be set per databox. - User time limit restrictions can now be set per databox.
- Add gzip/bzip2 options for DBs backup commandline tool. - 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) * 3.7.13 (2013-07-04)

View File

@@ -29,6 +29,7 @@ use Alchemy\Phrasea\Command\Plugin\AddPlugin;
use Alchemy\Phrasea\Command\Plugin\RemovePlugin; use Alchemy\Phrasea\Command\Plugin\RemovePlugin;
use Alchemy\Phrasea\Command\CheckConfig; use Alchemy\Phrasea\Command\CheckConfig;
use Alchemy\Phrasea\Command\Setup\XSendFileMappingDumper; use Alchemy\Phrasea\Command\Setup\XSendFileMappingDumper;
use Alchemy\Phrasea\Command\Setup\XSendFileMappingGenerator;
require_once __DIR__ . '/../lib/autoload.php'; require_once __DIR__ . '/../lib/autoload.php';
@@ -98,6 +99,7 @@ try {
$cli->command(new RemovePlugin()); $cli->command(new RemovePlugin());
$cli->command(new Configuration()); $cli->command(new Configuration());
$cli->command(new XSendFileMappingDumper()); $cli->command(new XSendFileMappingDumper());
$cli->command(new XSendFileMappingGenerator());
call_user_func(function ($cli) { call_user_func(function ($cli) {
require $cli['plugins.directory'] . '/commands.php'; require $cli['plugins.directory'] . '/commands.php';

View File

@@ -20,6 +20,8 @@ class XSendFileMappingDumper extends Command
{ {
public function __construct($name = null) { public function __construct($name = null) {
parent::__construct('xsendfile:configuration-dumper'); parent::__construct('xsendfile:configuration-dumper');
$this->setDescription('Dump the virtual host configuration depending on Phraseanet configuration');
} }
/** /**

View File

@@ -0,0 +1,94 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2013 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Command\Setup;
use Alchemy\Phrasea\Command\Command;
use Alchemy\Phrasea\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Yaml\Yaml;
class XSendFileMappingGenerator extends Command
{
public function __construct($name = null) {
parent::__construct('xsendfile:configuration-generator');
$this->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(" <info>OK</info>");
$output->writeln("");
$output->write("It now strongly recommended to use <info>xsendfile:configuration-dumper</info> command to upgrade your virtual-host");
} else {
$output->writeln("Configuration will <info>not</info> be written, use <info>--write</info> 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);
}
}

View File

@@ -18,7 +18,7 @@ namespace Alchemy\Phrasea\Core;
*/ */
class Version class Version
{ {
protected static $number = '3.8.0.a15'; protected static $number = '3.8.0.a16';
protected static $name = 'Carnosaurus'; protected static $name = 'Carnosaurus';
public static function getNumber() public static function getNumber()

View File

@@ -56,16 +56,6 @@ class XSendFileFactory
$mapping = $conf['mapping']; $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); return new self($app['monolog'], $conf['enabled'], $conf['type'], $mapping);
} }

View File

@@ -0,0 +1,70 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2012 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Alchemy\Phrasea\Application;
class patch_3816 implements patchInterface
{
/** @var string */
private $release = '3.8.0.a16';
/** @var array */
private $concern = array(base::APPLICATION_BOX);
/**
* {@inheritdoc}
*/
public function get_release()
{
return $this->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;
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace Alchemy\Tests\Phrasea\Command;
use Alchemy\Phrasea\Command\Setup\XSendFileMappingGenerator;
class XSendFileMappingGeneratorTest extends \PhraseanetPHPUnitAbstract
{
/**
* @dataProvider provideVariousOptions
*/
public function testRunWithoutProblems($option)
{
$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('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),
);
}
}

View File

@@ -36,7 +36,7 @@ class FileServeServiceProviderTest extends ServiceProviderTestCase
$app['phraseanet.configuration.config-path'] = __DIR__ . '/fixtures/config-mapping.yml'; $app['phraseanet.configuration.config-path'] = __DIR__ . '/fixtures/config-mapping.yml';
$app['phraseanet.configuration.config-compiled-path'] = __DIR__ . '/fixtures/config-mapping.php'; $app['phraseanet.configuration.config-compiled-path'] = __DIR__ . '/fixtures/config-mapping.php';
$this->assertInstanceOf('Alchemy\Phrasea\Http\XSendFile\NginxMode', $app['phraseanet.xsendfile-factory']->getMode()); $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']); unlink($app['phraseanet.configuration.config-compiled-path']);
unset($app); unset($app);