Add relaxed schema for application packages that do not need to be distributed
parent
bd54e43d37
commit
82dd1c1f7f
|
@ -0,0 +1,190 @@
|
|||
{
|
||||
"name": "Package",
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Package name, including 'vendor-name/' prefix."
|
||||
},
|
||||
"type": {
|
||||
"description": "Package type, either 'library' for common packages, 'composer-installer' for custom installers, or a custom type defined by whatever project this package applies to.",
|
||||
"type": "string"
|
||||
},
|
||||
"target-dir": {
|
||||
"description": "Forces the package to be installed into the given subdirectory path. This is used for autoloading PSR-0 packages that do not contain their full path. Use forward slashes for cross-platform compatibility.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Short package description."
|
||||
},
|
||||
"keywords": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"description": "A tag/keyword that this package relates to."
|
||||
}
|
||||
},
|
||||
"homepage": {
|
||||
"type": "string",
|
||||
"description": "Homepage URL for the project.",
|
||||
"format": "uri"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Package version, see http://packagist.org/about for more info on valid schemes."
|
||||
},
|
||||
"time": {
|
||||
"type": "string",
|
||||
"description": "Package release date, in 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' format."
|
||||
},
|
||||
"license": {
|
||||
"type": ["string", "array"],
|
||||
"description": "License name. Or an array of license names."
|
||||
},
|
||||
"authors": {
|
||||
"type": "array",
|
||||
"description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Full name of the author.",
|
||||
"required": true
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "Email address of the author.",
|
||||
"format": "email"
|
||||
},
|
||||
"homepage": {
|
||||
"type": "string",
|
||||
"description": "Homepage URL for the author.",
|
||||
"format": "uri"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"type": "object",
|
||||
"description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"replace": {
|
||||
"type": "object",
|
||||
"description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"conflict": {
|
||||
"type": "object",
|
||||
"description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"provide": {
|
||||
"type": "object",
|
||||
"description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"recommend": {
|
||||
"type": "object",
|
||||
"description": "This is a hash of package name (keys) and version constraints (values) that this package recommends to be installed (typically this will be installed as well).",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"suggest": {
|
||||
"type": "object",
|
||||
"description": "This is a hash of package name (keys) and version constraints (values) that this package suggests work well with it (typically this will only be suggested to the user).",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"config": {
|
||||
"type": ["object"],
|
||||
"description": "Composer options.",
|
||||
"properties": {
|
||||
"vendor-dir": {
|
||||
"type": "string",
|
||||
"description": "The location where all packages are installed, defaults to \"vendor\"."
|
||||
},
|
||||
"bin-dir": {
|
||||
"type": "string",
|
||||
"description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
|
||||
}
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"type": ["object", "array"],
|
||||
"description": "Arbitrary extra data that can be used by custom installers, for example, package of type composer-installer must have a 'class' key defining the installer class name.",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"autoload": {
|
||||
"type": "object",
|
||||
"description": "Description of how the package can be autoloaded.",
|
||||
"properties": {
|
||||
"psr-0": {
|
||||
"type": "object",
|
||||
"description": "This is a hash of namespaces (keys) and the directories they can be found into (values) by the autoloader.",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"repositories": {
|
||||
"type": ["object", "array"],
|
||||
"description": "A set of additional repositories where packages can be found.",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"bin": {
|
||||
"type": ["array"],
|
||||
"description": "A set of files that should be treated as binaries and symlinked into bin-dir (from config).",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"type": ["object"],
|
||||
"description": "Scripts listeners that will be executed before/after some events.",
|
||||
"properties": {
|
||||
"pre-install-cmd": {
|
||||
"type": ["array", "string"],
|
||||
"description": "Occurs before the install command is executed, contains one or more Class::method callables."
|
||||
},
|
||||
"post-install-cmd": {
|
||||
"type": ["array", "string"],
|
||||
"description": "Occurs after the install command is executed, contains one or more Class::method callables."
|
||||
},
|
||||
"pre-update-cmd": {
|
||||
"type": ["array", "string"],
|
||||
"description": "Occurs before the update command is executed, contains one or more Class::method callables."
|
||||
},
|
||||
"post-update-cmd": {
|
||||
"type": ["array", "string"],
|
||||
"description": "Occurs after the update command is executed, contains one or more Class::method callables."
|
||||
},
|
||||
"pre-package-install": {
|
||||
"type": ["array", "string"],
|
||||
"description": "Occurs before a package is installed, contains one or more Class::method callables."
|
||||
},
|
||||
"post-package-install": {
|
||||
"type": ["array", "string"],
|
||||
"description": "Occurs after a package is installed, contains one or more Class::method callables."
|
||||
},
|
||||
"pre-package-update": {
|
||||
"type": ["array", "string"],
|
||||
"description": "Occurs before a package is updated, contains one or more Class::method callables."
|
||||
},
|
||||
"post-package-update": {
|
||||
"type": ["array", "string"],
|
||||
"description": "Occurs after a package is updated, contains one or more Class::method callables."
|
||||
},
|
||||
"pre-package-uninstall": {
|
||||
"type": ["array", "string"],
|
||||
"description": "Occurs before a package has been uninstalled, contains one or more Class::method callables."
|
||||
},
|
||||
"post-package-uninstall": {
|
||||
"type": ["array", "string"],
|
||||
"description": "Occurs after a package has been uninstalled, contains one or more Class::method callables."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ use Symfony\Component\Console\Input\InputInterface;
|
|||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Composer\Json\JsonFile;
|
||||
use Composer\Json\JsonValidationException;
|
||||
|
||||
/**
|
||||
* @author Robert Schönthal <seroscho@googlemail.com>
|
||||
|
@ -52,11 +53,27 @@ EOT
|
|||
return 1;
|
||||
}
|
||||
|
||||
$laxValid = false;
|
||||
try {
|
||||
$json = new JsonFile($file);
|
||||
$json->read();
|
||||
|
||||
$json->validateSchema(JsonFile::LAX_SCHEMA);
|
||||
$laxValid = true;
|
||||
$json->validateSchema();
|
||||
} catch (JsonValidationException $e) {
|
||||
if ($laxValid) {
|
||||
$output->writeln('<info>'.$file.' is valid for simple usage with composer but has</info>');
|
||||
$output->writeln('<info>strict errors that make it unable to be published as a package:</info>');
|
||||
} else {
|
||||
$output->writeln('<error>'.$file.' is invalid, the following errors were found:</error>');
|
||||
}
|
||||
foreach ($e->getErrors() as $message) {
|
||||
$output->writeln('<error>'.$message.'</error>');
|
||||
}
|
||||
return 1;
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln('<error>'.$file.' contains a JSON Syntax Error:</error>');
|
||||
$output->writeln('<error>'.$e->getMessage().'</error>');
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ class Factory
|
|||
);
|
||||
|
||||
$packageConfig = $file->read();
|
||||
$file->validateSchema();
|
||||
$file->validateSchema(JsonFile::LAX_SCHEMA);
|
||||
|
||||
if (isset($packageConfig['config']) && is_array($packageConfig['config'])) {
|
||||
$packageConfig['config'] = array_merge($composerConfig, $packageConfig['config']);
|
||||
|
|
|
@ -36,6 +36,9 @@ if (!defined('JSON_UNESCAPED_UNICODE')) {
|
|||
*/
|
||||
class JsonFile
|
||||
{
|
||||
const LAX_SCHEMA = 1;
|
||||
const STRICT_SCHEMA = 2;
|
||||
|
||||
private $path;
|
||||
|
||||
/**
|
||||
|
@ -111,11 +114,11 @@ class JsonFile
|
|||
/**
|
||||
* Validates the schema of the current json file according to composer-schema.json rules
|
||||
*
|
||||
* @param string $json
|
||||
* @param int $schema a JsonFile::*_SCHEMA constant
|
||||
* @return Boolean true on success
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public function validateSchema()
|
||||
public function validateSchema($schema = self::STRICT_SCHEMA)
|
||||
{
|
||||
$content = file_get_contents($this->path);
|
||||
$data = json_decode($content);
|
||||
|
@ -124,17 +127,20 @@ class JsonFile
|
|||
self::validateSyntax($content);
|
||||
}
|
||||
|
||||
$schema = json_decode(file_get_contents(__DIR__ . '/../../../res/composer-schema.json'));
|
||||
$schemaFile = __DIR__ . '/../../../res/composer-schema'.($schema === self::LAX_SCHEMA ? '-lax' : '').'.json';
|
||||
$schema = json_decode(file_get_contents($schemaFile));
|
||||
|
||||
$validator = new Validator();
|
||||
$validator->check($data, $schema);
|
||||
|
||||
// TODO add more specific checks for common errors if needed
|
||||
|
||||
if (!$validator->isValid()) {
|
||||
$msg = "\n";
|
||||
$errors = array();
|
||||
foreach ((array) $validator->getErrors() as $error) {
|
||||
$msg .= ($error['property'] ? $error['property'].' : ' : '').$error['message']."\n";
|
||||
$errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
|
||||
}
|
||||
throw new \UnexpectedValueException('Your composer.json is invalid. The following errors were found:' . $msg);
|
||||
throw new JsonValidationException($errors);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?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\Json;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class JsonValidationException extends Exception
|
||||
{
|
||||
protected $errors;
|
||||
|
||||
public function __construct(array $errors)
|
||||
{
|
||||
parent::__construct(implode("\n", $errors));
|
||||
$this->errors = $errors;
|
||||
}
|
||||
|
||||
public function getErrors()
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue