From f59fc65d136cf5e0f3478c2e69b0047f979461d8 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Fri, 31 Jan 2014 15:05:57 +0100 Subject: [PATCH 1/6] Add task manager logs configuration --- config/configuration.sample.yml | 5 ++ lib/classes/module/console/schedulerStart.php | 18 +++++- lib/classes/module/console/taskrun.php | 17 ++++- lib/classes/patch/383alpha5a.php | 63 +++++++++++++++++++ lib/conf.d/configuration.yml | 5 ++ 5 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 lib/classes/patch/383alpha5a.php diff --git a/config/configuration.sample.yml b/config/configuration.sample.yml index 2224cf8115..6ffefd4003 100644 --- a/config/configuration.sample.yml +++ b/config/configuration.sample.yml @@ -26,6 +26,11 @@ main: search-engine: type: Alchemy\Phrasea\SearchEngine\Phrasea\PhraseaEngine options: [] + task-manager: + logger: + max-files: 10 + enabled: true + level: INFO binaries: ghostscript_binary: null php_binary: null diff --git a/lib/classes/module/console/schedulerStart.php b/lib/classes/module/console/schedulerStart.php index c0c90a0288..e030444cfa 100644 --- a/lib/classes/module/console/schedulerStart.php +++ b/lib/classes/module/console/schedulerStart.php @@ -41,9 +41,21 @@ class module_console_schedulerStart extends Command $streamHandler = new Handler\StreamHandler('php://stdout', $input->getOption('verbose') ? Logger::DEBUG : Logger::WARNING); $logger->pushHandler($streamHandler); - $logfile = __DIR__ . '/../../../../logs/scheduler.log'; - $rotateHandler = new Handler\RotatingFileHandler($logfile, 10, Logger::INFO); - $logger->pushHandler($rotateHandler); + $taskManagerConf = isset($this->container['phraseanet.configuration']['main']['task-manager']) ? $this->container['phraseanet.configuration']['main']['task-manager'] : array(); + $taskManagerConf = array_replace_recursive(array( + 'logger' => array( + 'enabled' => true, + 'level' => 'INFO', + 'max-files' => 10, + ) + ), $taskManagerConf); + + if ($taskManagerConf['logger']['enabled']) { + $level = defined('Monolog\\Logger::'.$taskManagerConf['logger']['level']) ? constant('Monolog\\Logger::'.$taskManagerConf['logger']['level']) : Logger::INFO; + $logfile = __DIR__ . '/../../../../logs/scheduler.log'; + $rotateHandler = new Handler\RotatingFileHandler($logfile, $taskManagerConf['logger']['max-files'], $level); + $logger->pushHandler($rotateHandler); + } try { $scheduler = new task_Scheduler($this->container, $logger); diff --git a/lib/classes/module/console/taskrun.php b/lib/classes/module/console/taskrun.php index a78ff818c0..3b30ad7f5c 100644 --- a/lib/classes/module/console/taskrun.php +++ b/lib/classes/module/console/taskrun.php @@ -96,8 +96,21 @@ class module_console_taskrun extends Command } } - $logfile = __DIR__ . '/../../../../logs/task_' . $task_id . '.log'; - $this->container['task-manager.logger']->pushHandler(new RotatingFileHandler($logfile, 10, Logger::INFO)); + $taskManagerConf = isset($this->container['phraseanet.configuration']['main']['task-manager']) ? $this->container['phraseanet.configuration']['main']['task-manager'] : array(); + $taskManagerConf = array_replace_recursive(array( + 'logger' => array( + 'enabled' => true, + 'level' => 'INFO', + 'max-files' => 10, + ) + ), $taskManagerConf); + + if ($taskManagerConf['logger']['enabled']) { + $level = defined('Monolog\\Logger::'.$taskManagerConf['logger']['level']) ? constant('Monolog\\Logger::'.$taskManagerConf['logger']['level']) : Logger::INFO; + $logfile = __DIR__ . '/../../../../logs/task_' . $task_id . '.log'; + $this->container['task-manager.logger']->pushHandler(new RotatingFileHandler($logfile, $taskManagerConf['logger']['max-files'], $level)); + } + $this->task = $task_manager->getTask($task_id, $this->container['task-manager.logger']); $lib2v = array( diff --git a/lib/classes/patch/383alpha5a.php b/lib/classes/patch/383alpha5a.php new file mode 100644 index 0000000000..623fa05266 --- /dev/null +++ b/lib/classes/patch/383alpha5a.php @@ -0,0 +1,63 @@ +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['main']['task-manager']['logger'] = array( + 'enabled' => true, + 'max-files' => 10, + 'level' => 'INFO', + ); + + $app['phraseanet.configuration']->setConfig($config); + + return true; + } +} diff --git a/lib/conf.d/configuration.yml b/lib/conf.d/configuration.yml index 8ebfa9f96a..174ae96d36 100644 --- a/lib/conf.d/configuration.yml +++ b/lib/conf.d/configuration.yml @@ -26,6 +26,11 @@ main: search-engine: type: Alchemy\Phrasea\SearchEngine\Phrasea\PhraseaEngine options: [] + task-manager: + logger: + max-files: 10 + enabled: true + level: INFO trusted-proxies: [] debugger: allowed-ips: [] From 7e7350a0a76653ce49ef4d9f2074f342a49cceb7 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Fri, 31 Jan 2014 15:06:10 +0100 Subject: [PATCH 2/6] Bump to version 3.8.3-alpha.5 --- lib/Alchemy/Phrasea/Core/Version.php | 2 +- lib/classes/patch/383alpha5a.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Alchemy/Phrasea/Core/Version.php b/lib/Alchemy/Phrasea/Core/Version.php index 6e23303357..ff45b79586 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.3-alpha.4'; + protected static $number = '3.8.3-alpha.5'; protected static $name = 'Diplodocus'; public static function getNumber() diff --git a/lib/classes/patch/383alpha5a.php b/lib/classes/patch/383alpha5a.php index 623fa05266..87896eb463 100644 --- a/lib/classes/patch/383alpha5a.php +++ b/lib/classes/patch/383alpha5a.php @@ -51,7 +51,7 @@ class patch_383alpha5a implements patchInterface $config = $app['phraseanet.configuration']->getConfig(); $config['main']['task-manager']['logger'] = array( - 'enabled' => true, + 'enabled' => true, 'max-files' => 10, 'level' => 'INFO', ); From dd8c4cb75f971f43dbec8a5b6efde21cca2f5045 Mon Sep 17 00:00:00 2001 From: Nicolas Le Goff Date: Fri, 31 Jan 2014 16:39:01 +0100 Subject: [PATCH 3/6] Fix #1660 video scale preview on ipad in lightbox --- templates/mobile/common/index.html.twig | 1 + templates/mobile/common/thumbnail.html.twig | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/templates/mobile/common/index.html.twig b/templates/mobile/common/index.html.twig index c62d468f09..01e1572735 100644 --- a/templates/mobile/common/index.html.twig +++ b/templates/mobile/common/index.html.twig @@ -4,6 +4,7 @@ + {{ app['phraseanet.registry'].get('GV_homeTitle') }} - {{ module_name }} diff --git a/templates/mobile/common/thumbnail.html.twig b/templates/mobile/common/thumbnail.html.twig index e3854a2772..fbcd30ac36 100644 --- a/templates/mobile/common/thumbnail.html.twig +++ b/templates/mobile/common/thumbnail.html.twig @@ -34,7 +34,7 @@ {% set random = thumbnail.get_random() %}
{% elseif record_type == 'FLEXPAPER' %} @@ -79,8 +79,8 @@ {% if record_type == 'VIDEO_MP4' or record_type == 'VIDEO_FLV' %} {% set random = thumbnail.get_random() %}
-
{% elseif record_type == 'FLEXPAPER' %} From b2af24954cab9c61f5acb0c60cb63077d5c379ef Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Mon, 3 Feb 2014 12:53:52 +0100 Subject: [PATCH 4/6] Fix #1662 : Abort plugin uninstall in case the plugin is not present --- lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php | 6 ++++++ .../Tests/Phrasea/Command/Plugin/RemovePluginTest.php | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php b/lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php index e6625ef56c..8636760218 100644 --- a/lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php +++ b/lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php @@ -30,6 +30,12 @@ class RemovePlugin extends AbstractPluginCommand { $name = $input->getArgument('name'); + if (!$this->container['plugins.manager']->hasPlugin($name)) { + $output->writeln(sprintf('There is no plugin named %s, aborting', $name)); + + return 0; + } + $output->write("Removing public assets..."); $this->container['plugins.assets-manager']->remove($name); $output->writeln(" OK"); diff --git a/tests/Alchemy/Tests/Phrasea/Command/Plugin/RemovePluginTest.php b/tests/Alchemy/Tests/Phrasea/Command/Plugin/RemovePluginTest.php index 29baa854b6..a31b0cee9e 100644 --- a/tests/Alchemy/Tests/Phrasea/Command/Plugin/RemovePluginTest.php +++ b/tests/Alchemy/Tests/Phrasea/Command/Plugin/RemovePluginTest.php @@ -21,6 +21,15 @@ class RemovePluginTest extends PluginCommandTestCase $command = new RemovePlugin(); $command->setContainer(self::$DI['cli']); + self::$DI['cli']['plugins.manager'] = $this->getMockBuilder('Alchemy\Phrasea\Plugin\PluginManager') + ->disableOriginalConstructor() + ->getMock(); + + self::$DI['cli']['plugins.manager']->expects($this->once()) + ->method('hasPlugin') + ->with('test-plugin') + ->will($this->returnValue(true)); + self::$DI['cli']['filesystem'] = $this->createFilesystemMock(); self::$DI['cli']['filesystem']->expects($this->at(0)) ->method('remove') From 0085b1530448e7faf114586d4db4f45e2a3e7230 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Mon, 3 Feb 2014 14:00:33 +0100 Subject: [PATCH 5/6] Fix #1663 : Remove plugin configuration on uninstall --- .../Phrasea/Command/Plugin/RemovePlugin.php | 10 ++- .../Command/Plugin/RemovePluginTest.php | 68 ++++++++++++++++++- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php b/lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php index e6625ef56c..b648e539f4 100644 --- a/lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php +++ b/lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php @@ -12,6 +12,7 @@ namespace Alchemy\Phrasea\Command\Plugin; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; @@ -23,7 +24,8 @@ class RemovePlugin extends AbstractPluginCommand $this ->setDescription('Removes a plugin given its name') - ->addArgument('name', InputArgument::REQUIRED, 'The name of the plugin'); + ->addArgument('name', InputArgument::REQUIRED, 'The name of the plugin') + ->addOption('keep-config', 'k', InputOption::VALUE_NONE, 'Use this flag to keep configuration'); } protected function doExecute(InputInterface $input, OutputInterface $output) @@ -42,6 +44,12 @@ class RemovePlugin extends AbstractPluginCommand $this->updateConfigFiles($input, $output); + if (!$input->getOption('keep-config')) { + $conf = $this->container['phraseanet.configuration']->getConfig(); + unset($conf['plugins'][$name]); + $this->container['phraseanet.configuration']->setConfig($conf); + } + return 0; } } diff --git a/tests/Alchemy/Tests/Phrasea/Command/Plugin/RemovePluginTest.php b/tests/Alchemy/Tests/Phrasea/Command/Plugin/RemovePluginTest.php index 29baa854b6..dee56a2971 100644 --- a/tests/Alchemy/Tests/Phrasea/Command/Plugin/RemovePluginTest.php +++ b/tests/Alchemy/Tests/Phrasea/Command/Plugin/RemovePluginTest.php @@ -12,9 +12,16 @@ class RemovePluginTest extends PluginCommandTestCase $input = $this->getMock('Symfony\Component\Console\Input\InputInterface'); $input->expects($this->once()) - ->method('getArgument') - ->with($this->equalTo('name')) - ->will($this->returnValue($name)); + ->method('getArgument') + ->with($this->equalTo('name')) + ->will($this->returnValue($name)); + $input->expects($this->any()) + ->method('getOption') + ->will($this->returnCallback(function ($option) { + if ($option === 'keep-config') { + return false; + } + })); $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); @@ -33,5 +40,60 @@ class RemovePluginTest extends PluginCommandTestCase $result = $command->execute($input, $output); $this->assertSame(0, $result); + + $conf = self::$DI['cli']['phraseanet.configuration']->getConfig(); + $this->assertArrayNotHasKey('test-plugin', $conf['plugins']); + } + + public function testExecuteWithoutRemoveConfig() + { + $name = 'test-plugin'; + + $input = $this->getMock('Symfony\Component\Console\Input\InputInterface'); + $input->expects($this->once()) + ->method('getArgument') + ->with($this->equalTo('name')) + ->will($this->returnValue($name)); + $input->expects($this->any()) + ->method('getOption') + ->will($this->returnCallback(function ($option) { + if ($option === 'keep-config') { + return true; + } + })); + + $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + + $command = new RemovePlugin(); + $command->setContainer(self::$DI['cli']); + + $data = $this->addPluginData(); + + self::$DI['cli']['filesystem'] = $this->createFilesystemMock(); + self::$DI['cli']['filesystem']->expects($this->at(0)) + ->method('remove') + ->with(self::$DI['cli']['root.path'].'/www/plugins/'.$name); + + self::$DI['cli']['filesystem']->expects($this->at(1)) + ->method('remove') + ->with(self::$DI['cli']['plugins.directory'].'/'.$name); + + $result = $command->execute($input, $output); + + $this->assertSame(0, $result); + + $conf = self::$DI['cli']['phraseanet.configuration']->getConfig(); + $this->assertSame($data, $conf['plugins']['test-plugin']); + } + + private function addPluginData() + { + $data = array('key' => 'value'); + + $conf = self::$DI['cli']['phraseanet.configuration']->getConfig(); + $conf['plugins']['test-plugin'] = $data; + self::$DI['cli']['phraseanet.configuration']->setConfig($conf); + + return $data; } } From a66f158dbb44d695e4994cdfbf569dc80fd8ab7c Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Mon, 3 Feb 2014 17:24:57 +0100 Subject: [PATCH 6/6] Fix #1661 : Use bin/setup for plugin manipulation to avoid plugin failures --- bin/setup | 6 ++++++ lib/Alchemy/Phrasea/CLI.php | 7 +++++++ .../Command/Plugin/AbstractPluginCommand.php | 13 +++++++++++++ lib/Alchemy/Phrasea/Command/Plugin/AddPlugin.php | 2 +- lib/Alchemy/Phrasea/Command/Plugin/ListPlugin.php | 2 +- lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php | 2 +- 6 files changed, 29 insertions(+), 3 deletions(-) diff --git a/bin/setup b/bin/setup index 8bf9f6f669..868681ea50 100755 --- a/bin/setup +++ b/bin/setup @@ -20,6 +20,9 @@ use Alchemy\Phrasea\Core\Version; use Alchemy\Phrasea\Command\UpgradeDBDatas; use Alchemy\Phrasea\Command\Setup\Install; use Alchemy\Phrasea\Command\Setup\PluginsReset; +use Alchemy\Phrasea\Command\Plugin\ListPlugin; +use Alchemy\Phrasea\Command\Plugin\AddPlugin; +use Alchemy\Phrasea\Command\Plugin\RemovePlugin; use Alchemy\Phrasea\CLI; use Alchemy\Phrasea\Command\Setup\CheckEnvironment; @@ -60,6 +63,9 @@ if ($app['phraseanet.configuration-tester']->isInstalled()) { $app->command(new UpgradeDBDatas('system:upgrade-datas')); } +$app->command(new AddPlugin()); +$app->command(new ListPlugin()); +$app->command(new RemovePlugin()); $app->command(new PluginsReset()); $app->command(new CheckEnvironment('check:system')); $app->command(new Install('system:install')); diff --git a/lib/Alchemy/Phrasea/CLI.php b/lib/Alchemy/Phrasea/CLI.php index 2a81f1356f..cf0fa99fd6 100644 --- a/lib/Alchemy/Phrasea/CLI.php +++ b/lib/Alchemy/Phrasea/CLI.php @@ -76,6 +76,13 @@ class CLI extends Application $app->run(); } + public function boot() + { + parent::boot(); + + $this['console']->setDispatcher($this['dispatcher']); + } + public function run(\Symfony\Component\HttpFoundation\Request $request = null) { if (null !== $request) { diff --git a/lib/Alchemy/Phrasea/Command/Plugin/AbstractPluginCommand.php b/lib/Alchemy/Phrasea/Command/Plugin/AbstractPluginCommand.php index 7f528991c9..5a259e9a92 100644 --- a/lib/Alchemy/Phrasea/Command/Plugin/AbstractPluginCommand.php +++ b/lib/Alchemy/Phrasea/Command/Plugin/AbstractPluginCommand.php @@ -30,6 +30,19 @@ abstract class AbstractPluginCommand extends Command return $manifests; } + protected function doExecute(InputInterface $input, OutputInterface $output) + { + if (basename($_SERVER['PHP_SELF']) === 'console') { + $output->writeln(""); + $output->writeln(sprintf(' /!\ Warning, this command is deprecated and will be removed as of Phraseanet 3.9, please use bin/setup %s instead /!\ ', $this->getName())); + $output->writeln(""); + } + + return $this->doExecutePluginAction($input, $output); + } + + abstract protected function doExecutePluginAction(InputInterface $input, OutputInterface $output); + protected function updateConfigFiles(InputInterface $input, OutputInterface $output) { $manifests = $this->validatePlugins($input, $output); diff --git a/lib/Alchemy/Phrasea/Command/Plugin/AddPlugin.php b/lib/Alchemy/Phrasea/Command/Plugin/AddPlugin.php index ebb9930e13..cd223e22b0 100644 --- a/lib/Alchemy/Phrasea/Command/Plugin/AddPlugin.php +++ b/lib/Alchemy/Phrasea/Command/Plugin/AddPlugin.php @@ -26,7 +26,7 @@ class AddPlugin extends AbstractPluginCommand ->addArgument('source', InputArgument::REQUIRED, 'The source is a folder'); } - protected function doExecute(InputInterface $input, OutputInterface $output) + protected function doExecutePluginAction(InputInterface $input, OutputInterface $output) { $source = $input->getArgument('source'); diff --git a/lib/Alchemy/Phrasea/Command/Plugin/ListPlugin.php b/lib/Alchemy/Phrasea/Command/Plugin/ListPlugin.php index db269b02ef..0b6eee9070 100644 --- a/lib/Alchemy/Phrasea/Command/Plugin/ListPlugin.php +++ b/lib/Alchemy/Phrasea/Command/Plugin/ListPlugin.php @@ -27,7 +27,7 @@ class ListPlugin extends AbstractPluginCommand ->addOption('json', 'j', InputOption::VALUE_NONE, 'Output result in JSON'); } - protected function doExecute(InputInterface $input, OutputInterface $output) + protected function doExecutePluginAction(InputInterface $input, OutputInterface $output) { $plugins = array_map(function (Plugin $plugin) use ($input) { if ($plugin->isErroneous()) { diff --git a/lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php b/lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php index e6625ef56c..109e205e4f 100644 --- a/lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php +++ b/lib/Alchemy/Phrasea/Command/Plugin/RemovePlugin.php @@ -26,7 +26,7 @@ class RemovePlugin extends AbstractPluginCommand ->addArgument('name', InputArgument::REQUIRED, 'The name of the plugin'); } - protected function doExecute(InputInterface $input, OutputInterface $output) + protected function doExecutePluginAction(InputInterface $input, OutputInterface $output) { $name = $input->getArgument('name');