Add validators for package links and minimum-stability
parent
6206d0bc9c
commit
4b531771bd
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Package\Loader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*/
|
||||||
|
class InvalidPackageException extends \Exception
|
||||||
|
{
|
||||||
|
private $errors;
|
||||||
|
private $data;
|
||||||
|
|
||||||
|
public function __construct(array $errors, array $data)
|
||||||
|
{
|
||||||
|
$this->errors = $errors;
|
||||||
|
$this->data = $data;
|
||||||
|
parent::__construct("Invalid package information: \n".implode("\n", $errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getData()
|
||||||
|
{
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getErrors()
|
||||||
|
{
|
||||||
|
return $this->errors;
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
namespace Composer\Package\Loader;
|
namespace Composer\Package\Loader;
|
||||||
|
|
||||||
use Composer\Package;
|
use Composer\Package;
|
||||||
|
use Composer\Package\BasePackage;
|
||||||
use Composer\Package\Version\VersionParser;
|
use Composer\Package\Version\VersionParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,12 +43,12 @@ class ValidatingArrayLoader implements LoaderInterface
|
||||||
|
|
||||||
$this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
|
$this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
|
||||||
|
|
||||||
if (!empty($config['version'])) {
|
if (!empty($this->config['version'])) {
|
||||||
try {
|
try {
|
||||||
$this->versionParser->normalize($config['version']);
|
$this->versionParser->normalize($this->config['version']);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
unset($this->config['version']);
|
unset($this->config['version']);
|
||||||
$this->errors[] = 'version : invalid value ('.$config['version'].'): '.$e->getMessage();
|
$this->errors[] = 'version : invalid value ('.$this->config['version'].'): '.$e->getMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,8 +61,8 @@ class ValidatingArrayLoader implements LoaderInterface
|
||||||
$this->validateUrl('homepage');
|
$this->validateUrl('homepage');
|
||||||
$this->validateFlatArray('keywords', '[A-Za-z0-9 -]+');
|
$this->validateFlatArray('keywords', '[A-Za-z0-9 -]+');
|
||||||
|
|
||||||
if (isset($config['license'])) {
|
if (isset($this->config['license'])) {
|
||||||
if (is_string($config['license'])) {
|
if (is_string($this->config['license'])) {
|
||||||
$this->validateRegex('license', '[A-Za-z0-9+. ()-]+');
|
$this->validateRegex('license', '[A-Za-z0-9+. ()-]+');
|
||||||
} else {
|
} else {
|
||||||
$this->validateFlatArray('license', '[A-Za-z0-9+. ()-]+');
|
$this->validateFlatArray('license', '[A-Za-z0-9+. ()-]+');
|
||||||
|
@ -71,7 +72,7 @@ class ValidatingArrayLoader implements LoaderInterface
|
||||||
$this->validateString('time');
|
$this->validateString('time');
|
||||||
if (!empty($this->config['time'])) {
|
if (!empty($this->config['time'])) {
|
||||||
try {
|
try {
|
||||||
$date = new \DateTime($config['time']);
|
$date = new \DateTime($this->config['time']);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
|
$this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
|
||||||
unset($this->config['time']);
|
unset($this->config['time']);
|
||||||
|
@ -136,15 +137,49 @@ class ValidatingArrayLoader implements LoaderInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO validate require/require-dev/replace/provide
|
foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
|
||||||
// TODO validate suggest
|
if (isset($this->config[$linkType])) {
|
||||||
|
foreach ($this->config[$linkType] as $package => $constraint) {
|
||||||
|
if (!is_string($constraint)) {
|
||||||
|
$this->errors[] = $linkType.'.'.$package.' : invalid value, must be a string containing a version constraint';
|
||||||
|
unset($this->config[$linkType][$package]);
|
||||||
|
} elseif ('self.version' !== $constraint) {
|
||||||
|
try {
|
||||||
|
$this->versionParser->parseConstraints($constraint);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->errors[] = $linkType.'.'.$package.' : invalid version constraint ('.$e->getMessage().')';
|
||||||
|
unset($this->config[$linkType][$package]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->validateArray('suggest');
|
||||||
|
if (!empty($this->config['suggest'])) {
|
||||||
|
foreach ($this->config['suggest'] as $package => $description) {
|
||||||
|
if (!is_string($description)) {
|
||||||
|
$this->errors[] = 'suggest.'.$package.' : invalid value, must be a string describing why the package is suggested';
|
||||||
|
unset($this->config['suggest'][$package]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->validateString('minimum-stability');
|
||||||
|
if (!empty($this->config['minimum-stability'])) {
|
||||||
|
if (!isset(BasePackage::$stabilities[$this->config['minimum-stability']])) {
|
||||||
|
$this->errors[] = 'minimum-stability : invalid value, must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
|
||||||
|
unset($this->config['minimum-stability']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO validate autoload
|
// TODO validate autoload
|
||||||
// TODO validate minimum-stability
|
|
||||||
|
|
||||||
// TODO validate dist
|
// TODO validate dist
|
||||||
// TODO validate source
|
// TODO validate source
|
||||||
|
|
||||||
// TODO validate repositories
|
// TODO validate repositories
|
||||||
|
// TODO validate package repositories' packages using this recursively
|
||||||
|
|
||||||
$this->validateFlatArray('include-path');
|
$this->validateFlatArray('include-path');
|
||||||
|
|
||||||
|
@ -173,7 +208,7 @@ class ValidatingArrayLoader implements LoaderInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->errors && !$this->ignoreErrors) {
|
if ($this->errors && !$this->ignoreErrors) {
|
||||||
throw new \Exception(implode("\n", $this->errors));
|
throw new InvalidPackageException($this->errors, $config);
|
||||||
}
|
}
|
||||||
|
|
||||||
$package = $this->loader->load($this->config, $class);
|
$package = $this->loader->load($this->config, $class);
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace Composer\Util;
|
||||||
|
|
||||||
use Composer\Package\Loader\ArrayLoader;
|
use Composer\Package\Loader\ArrayLoader;
|
||||||
use Composer\Package\Loader\ValidatingArrayLoader;
|
use Composer\Package\Loader\ValidatingArrayLoader;
|
||||||
|
use Composer\Package\Loader\InvalidPackageException;
|
||||||
use Composer\Json\JsonValidationException;
|
use Composer\Json\JsonValidationException;
|
||||||
use Composer\IO\IOInterface;
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Json\JsonFile;
|
use Composer\Json\JsonFile;
|
||||||
|
@ -95,7 +96,6 @@ class ConfigValidator
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO validate package repositories' packages using the same technique as below
|
|
||||||
try {
|
try {
|
||||||
$loader = new ValidatingArrayLoader(new ArrayLoader(), false);
|
$loader = new ValidatingArrayLoader(new ArrayLoader(), false);
|
||||||
if (!isset($manifest['version'])) {
|
if (!isset($manifest['version'])) {
|
||||||
|
@ -105,8 +105,8 @@ class ConfigValidator
|
||||||
$manifest['name'] = 'dummy/dummy';
|
$manifest['name'] = 'dummy/dummy';
|
||||||
}
|
}
|
||||||
$loader->load($manifest);
|
$loader->load($manifest);
|
||||||
} catch (\Exception $e) {
|
} catch (InvalidPackageException $e) {
|
||||||
$errors = array_merge($errors, explode("\n", $e->getMessage()));
|
$errors = array_merge($errors, $e->getErrors());
|
||||||
}
|
}
|
||||||
|
|
||||||
return array($errors, $publishErrors, $warnings);
|
return array($errors, $publishErrors, $warnings);
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace Composer\Test\Package\Loader;
|
||||||
|
|
||||||
use Composer\Package;
|
use Composer\Package;
|
||||||
use Composer\Package\Loader\ValidatingArrayLoader;
|
use Composer\Package\Loader\ValidatingArrayLoader;
|
||||||
|
use Composer\Package\Loader\InvalidPackageException;
|
||||||
|
|
||||||
class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase
|
class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
@ -156,8 +157,8 @@ class ValidatingArrayLoaderTest extends \PHPUnit_Framework_TestCase
|
||||||
try {
|
try {
|
||||||
$loader->load($config);
|
$loader->load($config);
|
||||||
$this->fail('Expected exception to be thrown');
|
$this->fail('Expected exception to be thrown');
|
||||||
} catch (\Exception $e) {
|
} catch (InvalidPackageException $e) {
|
||||||
$errors = explode("\n", $e->getMessage());
|
$errors = $e->getErrors();
|
||||||
sort($expectedErrors);
|
sort($expectedErrors);
|
||||||
sort($errors);
|
sort($errors);
|
||||||
$this->assertEquals($expectedErrors, $errors);
|
$this->assertEquals($expectedErrors, $errors);
|
||||||
|
|
Loading…
Reference in New Issue