Address github comments

This commit is contained in:
Romain Neutron
2013-05-31 10:16:27 +02:00
parent bdcb98a3d5
commit dddf316f29
12 changed files with 131 additions and 46 deletions

View File

@@ -32,12 +32,12 @@ class PluginServiceProvider implements ServiceProviderInterface
$app['plugins.directory'] = realpath(__DIR__ . '/../../../../../plugins');
$app['plugins.schema'] = realpath(__DIR__ . '/../../../../conf.d/plugin-schema.json');
$app['json-validator'] = $app->share(function (Application $app) {
$app['plugins.json-validator'] = $app->share(function (Application $app) {
return new JsonValidator();
});
$app['plugins.manifest-validator'] = $app->share(function (Application $app) {
return ManifestValidator::create($app['json-validator'], $app['plugins.schema']);
return ManifestValidator::create($app);
});
$app['plugins.plugins-validator'] = $app->share(function (Application $app) {

View File

@@ -1,5 +1,14 @@
<?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\Core\Provider;
use Neutron\TemporaryFilesystem\TemporaryFilesystem;

View File

@@ -42,39 +42,66 @@ class AutoloaderGenerator
private function createLoader($manifests)
{
$buffer = "<?php\n"
."\n// This file is automatically generated, please do not edit it.\n"
."// To update configuration, use bin/console plugins:* commands.\n"
."\nreturn call_user_func(function () {\n";
$buffer = <<<EOF
<?php
// This file is automatically generated, please do not edit it.
// To update configuration, use bin/console plugins:* commands.
return call_user_func(function () {
EOF;
foreach ($manifests as $manifest) {
$buffer .= " require __DIR__ . '/" . $manifest->getName() . DIRECTORY_SEPARATOR . "vendor" . DIRECTORY_SEPARATOR . "autoload.php';\n";
$autoloader = '/' . $manifest->getName() . DIRECTORY_SEPARATOR . "vendor" . DIRECTORY_SEPARATOR . "autoload.php";
$buffer .= <<<EOF
require __DIR__ . '$autoloader';
EOF;
}
// composer loader are preprent
$buffer .= " \$loader = require __DIR__ . '/../vendor/autoload.php';\n";
$autoloader = '/../vendor/autoload.php';
$buffer .= <<<EOF
$buffer .= "\n return \$loader;\n});\n";
\$loader = require __DIR__ . '$autoloader';
return \$loader;\n});
EOF;
return $buffer;
}
private function createServices($manifests)
{
$buffer = "<?php\n"
."\n// This file is automatically generated, please do not edit it.\n"
."// To update configuration, use bin/console plugins:* commands.\n"
."\nuse Alchemy\Phrasea\Application;\n"
."\nreturn call_user_func(function (Application \$app) {"
."\n";
$buffer = <<<EOF
<?php
// This file is automatically generated, please do not edit it.
// To update configuration, use bin/console plugins:* commands.
use Alchemy\Phrasea\Application;
return call_user_func(function (Application \$app) {
EOF;
foreach ($manifests as $manifest) {
foreach ($manifest->getServices() as $service) {
$buffer .= " \$app->register(\\".$service['class']."::create(\$app));\n";
$class = $service['class'];
$buffer .= <<<EOF
\$app->register($class::create(\$app));
EOF;
}
}
$buffer .= "\n return \$app;\n}, \$app);\n";
$buffer .= <<<EOF
return \$app;
}, \$app);
EOF;
return $buffer;
}

View File

@@ -11,22 +11,26 @@
namespace Alchemy\Phrasea\Plugin\Schema;
use Alchemy\Phrasea\Application;
use JsonSchema\Validator as JsonValidator;
use Alchemy\Phrasea\Exception\InvalidArgumentException;
use Alchemy\Phrasea\Plugin\Exception\JsonValidationException;
use Alchemy\Phrasea\Core\Version;
class ManifestValidator
{
private $validator;
private $version;
private $schemaData;
public function __construct(JsonValidator $validator, $schemaData)
public function __construct(JsonValidator $validator, $schemaData, Version $version)
{
if (!is_object($schemaData)) {
throw new InvalidArgumentException('Json Schema must be an object');
}
$this->validator = $validator;
$this->version = $version;
$this->schemaData = $schemaData;
}
@@ -36,12 +40,12 @@ class ManifestValidator
throw new InvalidArgumentException('Json Schema must be an object');
}
$validator = clone $this->validator;
$validator->check($data, $this->schemaData);
$this->validator->reset();
$this->validator->check($data, $this->schemaData);
if (!$validator->isValid()) {
if (!$this->validator->isValid()) {
$errors = array();
foreach ((array) $validator->getErrors() as $error) {
foreach ((array) $this->validator->getErrors() as $error) {
$errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
}
throw new JsonValidationException('Manifest file does not match the expected JSON schema', $errors);
@@ -51,17 +55,35 @@ class ManifestValidator
throw new JsonValidationException('Does not match the expected JSON schema', array('"name" must not contains only alphanumeric caracters'));
}
// validate gainst versions
if (isset($data->{'minimum-phraseanet-version'})) {
if (true !== version_compare($this->version->getNumber(), $data->{'minimum-phraseanet-version'}, '>=')) {
throw new JsonValidationException(sprintf(
'Version incomptibility : Minimum Phraseanet version required is %s, current version is %s',
$data->{'minimum-phraseanet-version'},
$this->version->getNumber()
));
}
}
public static function create(JsonValidator $jsonValidator, $path)
if (isset($data->{'maximum-phraseanet-version'})) {
if (true !== version_compare($this->version->getNumber(), $data->{'maximum-phraseanet-version'}, '<')) {
throw new JsonValidationException(sprintf(
'Version incomptibility : Maximum Phraseanet version required is %s, current version is %s',
$data->{'maximum-phraseanet-version'},
$this->version->getNumber()
));
}
}
}
public static function create(Application $app)
{
$data = @json_decode(@file_get_contents($path));
$data = @json_decode(@file_get_contents($app['plugins.schema']));
if (JSON_ERROR_NONE !== json_last_error()) {
throw new InvalidArgumentException(sprintf('Unable to read %s', $path));
throw new InvalidArgumentException(sprintf('Unable to read %s', $app['plugins.schema']));
}
return new static($jsonValidator, $data);
return new static($app['plugins.json-validator'], $data, $app['phraseanet.version']);
}
}

View File

@@ -43,8 +43,7 @@ class PluginValidator
throw new PluginValidationException('Manifest file is invalid', $e->getCode(), $e);
}
// a ameliorer
return new Manifest(@json_decode(@file_get_contents($manifest), true));
return new Manifest($this->objectToArray($data));
}
private function ensureManifest($directory)
@@ -65,4 +64,17 @@ class PluginValidator
throw new PluginValidationException(sprintf('Required file %s is not present.', $file));
}
}
private function objectToArray($data)
{
if (is_object($data)) {
$data = get_object_vars($data);
}
if (is_array($data)) {
return array_map(array($this, 'objectToArray'), $data);
}
return $data;
}
}

View File

@@ -16,7 +16,7 @@ class PluginServiceProvidertest extends ServiceProviderTestCase
return array(
array(
'Alchemy\Phrasea\Core\Provider\PluginServiceProvider',
'json-validator',
'plugins.json-validator',
'JsonSchema\Validator'
),
array(

View File

@@ -0,0 +1,5 @@
{
"name": "TestPlugin",
"description" : "A custom class connector",
"minimum-phraseanet-version": "14"
}

View File

@@ -0,0 +1,5 @@
{
"name": "TestPlugin",
"description" : "A custom class connector",
"maximum-phraseanet-version": "3.8"
}

View File

@@ -33,7 +33,7 @@ class AutoloaderGeneratorTest extends \PHPUnit_Framework_TestCase
$this->assertFileExists($file);
$process = ProcessBuilder::create(array($php, '-l', $file))->getProcess();
$process->run();
$this->assertTrue($process->isSuccessful());
$this->assertTrue($process->isSuccessful(), basename($file) . ' is valid');
}
// test autoload

View File

@@ -2,8 +2,15 @@
namespace Alchemy\Tests\Phrasea\Plugin;
class PluginTestCase extends \PHPUnit_Framework_TestCase
use Alchemy\Phrasea\Plugin\Schema\ManifestValidator;
class PluginTestCase extends \PhraseanetPHPUnitAbstract
{
protected function createManifestValidator()
{
return ManifestValidator::create(self::$DI['app']);
}
protected function getPluginDirectory()
{
return __DIR__ . DIRECTORY_SEPARATOR . 'PluginFolder';

View File

@@ -42,6 +42,8 @@ class ManifestValidatorTest extends PluginTestCase
array(__DIR__ . '/../Fixtures/manifest-wrong2.json'),
array(__DIR__ . '/../Fixtures/manifest-wrong3.json'),
array(__DIR__ . '/../Fixtures/manifest-wrong4.json'),
array(__DIR__ . '/../Fixtures/manifest-wrong5-min-version.json'),
array(__DIR__ . '/../Fixtures/manifest-wrong6-max-version.json'),
);
}
@@ -59,12 +61,12 @@ class ManifestValidatorTest extends PluginTestCase
*/
public function testConstructWithInvalidSchema()
{
$validator = new ManifestValidator(new JsonSchemaValidator(), array());
new ManifestValidator(new JsonSchemaValidator(), array(), self::$DI['app']['phraseanet.version']);
}
public function testCreate()
{
$validator = ManifestValidator::create(new JsonSchemaValidator(), $this->getSchemaPath());
$validator = ManifestValidator::create(self::$DI['app']);
$this->assertInstanceOf('Alchemy\Phrasea\Plugin\Schema\ManifestValidator', $validator);
}
@@ -73,6 +75,6 @@ class ManifestValidatorTest extends PluginTestCase
{
$schema = json_decode($this->getSchema());
return new ManifestValidator(new JsonSchemaValidator(), $schema);
return new ManifestValidator(new JsonSchemaValidator(), $schema, self::$DI['app']['phraseanet.version']);
}
}

View File

@@ -15,9 +15,7 @@ class PluginValidatorTest extends PluginTestCase
*/
public function testValidateInvalidPlugin($directory)
{
$schema = json_decode($this->getSchema());
$validator = new PluginValidator(new ManifestValidator(new JsonValidator(), $schema));
$validator = new PluginValidator($this->createManifestValidator());
$validator->validatePlugin($directory);
}
@@ -26,9 +24,7 @@ class PluginValidatorTest extends PluginTestCase
*/
public function testValidatePlugin($directory)
{
$schema = json_decode($this->getSchema());
$validator = new PluginValidator(new ManifestValidator(new JsonValidator(), $schema));
$validator = new PluginValidator($this->createManifestValidator());
$validator->validatePlugin($directory);
}