mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 18:03:17 +00:00
Merge branch '3.8'
Conflicts: bin/console composer.lock
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace KonsoleKommander;
|
namespace KonsoleKommander;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Command\Plugin\ListPlugin;
|
||||||
use Alchemy\Phrasea\Command\SearchEngine\IndexFull;
|
use Alchemy\Phrasea\Command\SearchEngine\IndexFull;
|
||||||
use Alchemy\Phrasea\Command\BuildMissingSubdefs;
|
use Alchemy\Phrasea\Command\BuildMissingSubdefs;
|
||||||
use Alchemy\Phrasea\Command\CreateCollection;
|
use Alchemy\Phrasea\Command\CreateCollection;
|
||||||
@@ -103,6 +104,7 @@ $cli->command(new RescanTechnicalDatas('records:rescan-technical-datas'));
|
|||||||
$cli->command(new BuildMissingSubdefs('records:build-missing-subdefs'));
|
$cli->command(new BuildMissingSubdefs('records:build-missing-subdefs'));
|
||||||
|
|
||||||
$cli->command(new AddPlugin());
|
$cli->command(new AddPlugin());
|
||||||
|
$cli->command(new ListPlugin());
|
||||||
$cli->command(new RemovePlugin());
|
$cli->command(new RemovePlugin());
|
||||||
$cli->command(new Configuration());
|
$cli->command(new Configuration());
|
||||||
$cli->command(new XSendFileConfigurationDumper());
|
$cli->command(new XSendFileConfigurationDumper());
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
"jms/serializer" : "~0.10",
|
"jms/serializer" : "~0.10",
|
||||||
"justinrainbow/json-schema" : "~1.3",
|
"justinrainbow/json-schema" : "~1.3",
|
||||||
"mediavorus/mediavorus" : "~0.4.0",
|
"mediavorus/mediavorus" : "~0.4.0",
|
||||||
"media-alchemyst/media-alchemyst" : "~0.4, >=0.4.3",
|
"media-alchemyst/media-alchemyst" : "~0.4, >=0.4.4",
|
||||||
"monolog/monolog" : "~1.3",
|
"monolog/monolog" : "~1.3",
|
||||||
"mrclay/minify" : "~2.1.6",
|
"mrclay/minify" : "~2.1.6",
|
||||||
"neutron/process-manager" : "~1.0",
|
"neutron/process-manager" : "~1.0",
|
||||||
|
829
composer.lock
generated
829
composer.lock
generated
File diff suppressed because it is too large
Load Diff
90
lib/Alchemy/Phrasea/Command/Plugin/ListPlugin.php
Normal file
90
lib/Alchemy/Phrasea/Command/Plugin/ListPlugin.php
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Phraseanet
|
||||||
|
*
|
||||||
|
* (c) 2005-2014 Alchemy
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Command\Plugin;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Plugin\Plugin;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
class ListPlugin extends AbstractPluginCommand
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct('plugins:list');
|
||||||
|
|
||||||
|
$this
|
||||||
|
->setDescription('Lists installed plugins')
|
||||||
|
->addOption('json', 'j', InputOption::VALUE_NONE, 'Output result in JSON');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$plugins = array_map(function (Plugin $plugin) use ($input) {
|
||||||
|
if ($plugin->isErroneous()) {
|
||||||
|
return $this->formatErroneousPlugin($input, $plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->formatPlugin($input, $plugin);
|
||||||
|
}, $this->container['plugins.manager']->listPlugins());
|
||||||
|
|
||||||
|
if ($input->getOption('json')) {
|
||||||
|
$output->writeln(json_encode(array('plugins' => array_values($plugins))));
|
||||||
|
} else {
|
||||||
|
$table = $this->getHelperSet()->get('table');
|
||||||
|
$table
|
||||||
|
->setHeaders(array('Name', 'Version', 'Description'))
|
||||||
|
->setRows($plugins)
|
||||||
|
;
|
||||||
|
|
||||||
|
$table->render($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function formatPlugin(InputInterface $input, Plugin $plugin)
|
||||||
|
{
|
||||||
|
if ($input->getOption('json')) {
|
||||||
|
return array(
|
||||||
|
'name' => $plugin->getName(),
|
||||||
|
'version' => $plugin->getManifest()->getVersion(),
|
||||||
|
'description' => $plugin->getManifest()->getDescription(),
|
||||||
|
'error' => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$plugin->getName(),
|
||||||
|
$plugin->getManifest()->getVersion(),
|
||||||
|
$plugin->getManifest()->getDescription(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function formatErroneousPlugin(InputInterface $input, Plugin $plugin)
|
||||||
|
{
|
||||||
|
if ($input->getOption('json')) {
|
||||||
|
return array(
|
||||||
|
'name' => $plugin->getName(),
|
||||||
|
'error' => true,
|
||||||
|
'description' => 'Error : '.$plugin->getError()->getMessage(),
|
||||||
|
'version' => null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'<error>' . $plugin->getName() . '</error>',
|
||||||
|
'<error>Error : ' . $plugin->getError()->getMessage() . '</error>',
|
||||||
|
'',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -47,11 +47,6 @@ class Step35 implements DatasUpgraderInterface
|
|||||||
|
|
||||||
$this->ensureMigrateColumn($databox);
|
$this->ensureMigrateColumn($databox);
|
||||||
|
|
||||||
$sql = 'TRUNCATE metadatas';
|
|
||||||
$stmt = $databox->get_connection()->prepare($sql);
|
|
||||||
$stmt->execute();
|
|
||||||
$stmt->closeCursor();
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
$rs = $this->getEmptyOriginalNameRecords($databox);
|
$rs = $this->getEmptyOriginalNameRecords($databox);
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Alchemy\Phrasea\Core\CLIProvider;
|
namespace Alchemy\Phrasea\Core\CLIProvider;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Plugin\PluginManager;
|
||||||
use Alchemy\Phrasea\Plugin\Schema\ManifestValidator;
|
use Alchemy\Phrasea\Plugin\Schema\ManifestValidator;
|
||||||
use Alchemy\Phrasea\Plugin\Management\PluginsExplorer;
|
use Alchemy\Phrasea\Plugin\Management\PluginsExplorer;
|
||||||
use Alchemy\Phrasea\Plugin\Management\ComposerInstaller;
|
use Alchemy\Phrasea\Plugin\Management\ComposerInstaller;
|
||||||
@@ -31,6 +32,10 @@ class PluginServiceProvider implements ServiceProviderInterface
|
|||||||
{
|
{
|
||||||
$app['plugins.schema'] = realpath(__DIR__ . '/../../../../conf.d/plugin-schema.json');
|
$app['plugins.schema'] = realpath(__DIR__ . '/../../../../conf.d/plugin-schema.json');
|
||||||
|
|
||||||
|
$app['plugins.manager'] = $app->share(function (Application $app) {
|
||||||
|
return new PluginManager($app['plugins.directory'], $app['plugins.plugins-validator']);
|
||||||
|
});
|
||||||
|
|
||||||
$app['plugins.json-validator'] = $app->share(function (Application $app) {
|
$app['plugins.json-validator'] = $app->share(function (Application $app) {
|
||||||
return new JsonValidator();
|
return new JsonValidator();
|
||||||
});
|
});
|
||||||
|
65
lib/Alchemy/Phrasea/Plugin/Plugin.php
Normal file
65
lib/Alchemy/Phrasea/Plugin/Plugin.php
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Phraseanet
|
||||||
|
*
|
||||||
|
* (c) 2005-2014 Alchemy
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Plugin;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Plugin\Exception\PluginValidationException;
|
||||||
|
use Alchemy\Phrasea\Plugin\Schema\Manifest;
|
||||||
|
|
||||||
|
class Plugin
|
||||||
|
{
|
||||||
|
private $error;
|
||||||
|
private $manifest;
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
public function __construct($name, Manifest $manifest = null, PluginValidationException $error = null)
|
||||||
|
{
|
||||||
|
if ($manifest === $error || (null !== $manifest && null !== $error)) {
|
||||||
|
throw new \LogicException('A plugin is either installed (with a stable manifest) or on error (given its error).');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->name = $name;
|
||||||
|
$this->manifest = $manifest;
|
||||||
|
$this->error = $error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
public function isErroneous()
|
||||||
|
{
|
||||||
|
return null !== $this->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Manifest
|
||||||
|
*/
|
||||||
|
public function getManifest()
|
||||||
|
{
|
||||||
|
return $this->manifest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return PluginValidationException
|
||||||
|
*/
|
||||||
|
public function getError()
|
||||||
|
{
|
||||||
|
return $this->error;
|
||||||
|
}
|
||||||
|
}
|
64
lib/Alchemy/Phrasea/Plugin/PluginManager.php
Normal file
64
lib/Alchemy/Phrasea/Plugin/PluginManager.php
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Phraseanet
|
||||||
|
*
|
||||||
|
* (c) 2005-2014 Alchemy
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Plugin;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Plugin\Schema\PluginValidator;
|
||||||
|
use Alchemy\Phrasea\Plugin\Exception\PluginValidationException;
|
||||||
|
use Symfony\Component\Finder\Finder;
|
||||||
|
|
||||||
|
class PluginManager
|
||||||
|
{
|
||||||
|
private $pluginDir;
|
||||||
|
private $validator;
|
||||||
|
|
||||||
|
public function __construct($pluginDir, PluginValidator $validator)
|
||||||
|
{
|
||||||
|
$this->pluginDir = $pluginDir;
|
||||||
|
$this->validator = $validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Plugin[] An array containing plugins
|
||||||
|
*/
|
||||||
|
public function listPlugins()
|
||||||
|
{
|
||||||
|
$finder = new Finder();
|
||||||
|
$finder
|
||||||
|
->depth(0)
|
||||||
|
->in($this->pluginDir)
|
||||||
|
->directories();
|
||||||
|
|
||||||
|
$plugins = array();
|
||||||
|
|
||||||
|
foreach ($finder as $pluginDir) {
|
||||||
|
$manifest = $error = null;
|
||||||
|
$name = $pluginDir->getBasename();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$manifest = $this->validator->validatePlugin((string) $pluginDir);
|
||||||
|
} catch (PluginValidationException $e) {
|
||||||
|
$error = $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plugins[$name] = new Plugin($name, $manifest, $error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasPlugin($name)
|
||||||
|
{
|
||||||
|
$plugins = $this->listPlugins();
|
||||||
|
|
||||||
|
return isset($plugins[$name]);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Tests\Phrasea\Command\Plugin;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Command\Plugin\ListPlugin;
|
||||||
|
|
||||||
|
class ListPluginTest extends PluginCommandTestCase
|
||||||
|
{
|
||||||
|
public function testExecute()
|
||||||
|
{
|
||||||
|
$input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
|
||||||
|
$output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
|
||||||
|
|
||||||
|
$table = $this->getMockBuilder('Symfony\Component\Console\Helper\TableHelper')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$table->expects($this->once())
|
||||||
|
->method('setHeaders')
|
||||||
|
->will($this->returnSelf());
|
||||||
|
|
||||||
|
$helperSet = $this->getMockBuilder('Symfony\Component\Console\Helper\HelperSet')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
$helperSet->expects($this->once())
|
||||||
|
->method('get')
|
||||||
|
->will($this->returnValue($table));
|
||||||
|
|
||||||
|
$command = new ListPlugin();
|
||||||
|
$command->setContainer(self::$DI['cli']);
|
||||||
|
$command->setHelperSet($helperSet);
|
||||||
|
|
||||||
|
$result = $command->execute($input, $output);
|
||||||
|
|
||||||
|
$this->assertSame(0, $result);
|
||||||
|
}
|
||||||
|
}
|
@@ -19,6 +19,11 @@ class PluginServiceProviderTest extends ServiceProviderTestCase
|
|||||||
'JsonSchema\Validator'
|
'JsonSchema\Validator'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
'Alchemy\Phrasea\Core\CLIProvider\PluginServiceProvider',
|
||||||
|
'plugins.manager',
|
||||||
|
'Alchemy\Phrasea\Plugin\PluginManager'
|
||||||
|
),
|
||||||
|
array(
|
||||||
'Alchemy\Phrasea\Core\CLIProvider\PluginServiceProvider',
|
'Alchemy\Phrasea\Core\CLIProvider\PluginServiceProvider',
|
||||||
'plugins.plugins-validator',
|
'plugins.plugins-validator',
|
||||||
'Alchemy\Phrasea\Plugin\Schema\PluginValidator'
|
'Alchemy\Phrasea\Plugin\Schema\PluginValidator'
|
||||||
|
43
tests/Alchemy/Tests/Phrasea/Plugin/PluginManagerTest.php
Normal file
43
tests/Alchemy/Tests/Phrasea/Plugin/PluginManagerTest.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Tests\Phrasea\Plugin;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Plugin\PluginManager;
|
||||||
|
use Alchemy\Phrasea\Plugin\Schema\PluginValidator;
|
||||||
|
|
||||||
|
class PluginManagerTest extends PluginTestCase
|
||||||
|
{
|
||||||
|
public function testListGoodPlugins()
|
||||||
|
{
|
||||||
|
$manager = new PluginManager(__DIR__ . '/Fixtures/PluginDirInstalled', self::$DI['cli']['plugins.plugins-validator']);
|
||||||
|
$plugins = $manager->listPlugins();
|
||||||
|
$this->assertCount(1, $plugins);
|
||||||
|
$plugin = array_pop($plugins);
|
||||||
|
|
||||||
|
$this->assertFalse($plugin->isErroneous());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testListWrongPlugins()
|
||||||
|
{
|
||||||
|
$manager = new PluginManager(__DIR__ . '/Fixtures/WrongPlugins', self::$DI['cli']['plugins.plugins-validator']);
|
||||||
|
$plugins = $manager->listPlugins();
|
||||||
|
$this->assertCount(8, $plugins);
|
||||||
|
$plugin = array_pop($plugins);
|
||||||
|
|
||||||
|
$this->assertTrue($plugin->isErroneous());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHasPlugin()
|
||||||
|
{
|
||||||
|
$manager = new PluginManager(__DIR__ . '/Fixtures/PluginDirInstalled', self::$DI['cli']['plugins.plugins-validator']);
|
||||||
|
$this->assertTrue($manager->hasPlugin('test-plugin'));
|
||||||
|
$this->assertFalse($manager->hasPlugin('test-plugin2'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createValidatorMock()
|
||||||
|
{
|
||||||
|
return $this->getMockBuilder('Alchemy\Phrasea\Plugin\Schema\PluginValidator')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
}
|
||||||
|
}
|
45
tests/Alchemy/Tests/Phrasea/Plugin/PluginTest.php
Normal file
45
tests/Alchemy/Tests/Phrasea/Plugin/PluginTest.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Tests\Phrasea\Plugin;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Plugin\Plugin;
|
||||||
|
|
||||||
|
class PluginTest extends PluginTestCase
|
||||||
|
{
|
||||||
|
public function testGetters()
|
||||||
|
{
|
||||||
|
$manifest = $this->createManifestMock();
|
||||||
|
$error = $this->getMock('Alchemy\Phrasea\Plugin\Exception\PluginValidationException');
|
||||||
|
|
||||||
|
$plugin = new Plugin('toto', $manifest, null);
|
||||||
|
$this->assertSame('toto', $plugin->getName());
|
||||||
|
$this->assertSame($manifest, $plugin->getManifest());
|
||||||
|
$this->assertNull($plugin->getError());
|
||||||
|
$this->assertFalse($plugin->isErroneous());
|
||||||
|
|
||||||
|
$plugin = new Plugin('toto', null, $error);
|
||||||
|
$this->assertSame('toto', $plugin->getName());
|
||||||
|
$this->assertNull($plugin->getManifest());
|
||||||
|
$this->assertSame($error, $plugin->getError());
|
||||||
|
$this->assertTrue($plugin->isErroneous());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \LogicException
|
||||||
|
*/
|
||||||
|
public function testBothNull()
|
||||||
|
{
|
||||||
|
new Plugin('toto', null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \LogicException
|
||||||
|
*/
|
||||||
|
public function testBothNotNull()
|
||||||
|
{
|
||||||
|
$manifest = $this->createManifestMock();
|
||||||
|
$error = $this->getMock('Alchemy\Phrasea\Plugin\Exception\PluginValidationException');
|
||||||
|
|
||||||
|
new Plugin('toto', $manifest, $error);
|
||||||
|
}
|
||||||
|
}
|
@@ -30,4 +30,11 @@ class PluginTestCase extends \PhraseanetTestCase
|
|||||||
{
|
{
|
||||||
return __DIR__ . '/../../../../../lib/conf.d/plugin-schema.json';
|
return __DIR__ . '/../../../../../lib/conf.d/plugin-schema.json';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function createManifestMock()
|
||||||
|
{
|
||||||
|
return $this->getMockBuilder('Alchemy\Phrasea\Plugin\Schema\Manifest')
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user