* Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; 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; use Composer\Util\RemoteFilesystem; use Composer\Util\SpdxLicenseIdentifier; /** * ValidateCommand * * @author Robert Schönthal * @author Jordi Boggiano */ class ValidateCommand extends Command { /** * configure */ protected function configure() { $this ->setName('validate') ->setDescription('Validates a composer.json') ->setDefinition(array( new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json') )) ->setHelp(<<getArgument('file'); if (!file_exists($file)) { $output->writeln('' . $file . ' not found.'); return 1; } if (!is_readable($file)) { $output->writeln('' . $file . ' is not readable.'); return 1; } $errors = array(); $publishErrors = array(); $warnings = array(); // validate json schema $laxValid = false; $valid = false; try { $json = new JsonFile($file, new RemoteFilesystem($this->getIO())); $manifest = $json->read(); $json->validateSchema(JsonFile::LAX_SCHEMA); $laxValid = true; $json->validateSchema(); $valid = true; } catch (JsonValidationException $e) { foreach ($e->getErrors() as $message) { if ($laxValid) { $publishErrors[] = 'Publish Error: ' . $message . ''; } else { $errors[] = '' . $message . ''; } } } catch (\Exception $e) { $output->writeln('' . $e->getMessage() . ''); return 1; } // validate actual data if (!empty($manifest['license'])) { $licenseValidator = new SpdxLicenseIdentifier(); if (!$licenseValidator->validate($manifest['license'])) { $warnings[] = sprintf( 'License %s is not a valid SPDX license identifier, see http://www.spdx.org/licenses/ if you use an open license', json_encode($manifest['license']) ); } } else { $warnings[] = 'No license specified, it is recommended to do so'; } if (preg_match('{[A-Z]}', $manifest['name'])) { $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']); $suggestName = strtolower($suggestName); $warnings[] = sprintf( 'Name "%s" does not match the best practice (e.g. lower-cased/with-dashes). We suggest using "%s" instead. As such you will not be able to submit it to Packagist.', $manifest['name'], $suggestName ); } // output errors/warnings if (!$errors && !$publishErrors && !$warnings) { $output->writeln('' . $file . ' is valid'); } elseif (!$errors && !$publishErrors) { $output->writeln('' . $file . ' is valid, but with a few warnings'); $output->writeln('See http://getcomposer.org/doc/04-schema.md for details on the schema'); } elseif (!$errors) { $output->writeln('' . $file . ' is valid for simple usage with composer but has'); $output->writeln('strict errors that make it unable to be published as a package:'); $output->writeln('See http://getcomposer.org/doc/04-schema.md for details on the schema'); } else { $output->writeln('' . $file . ' is invalid, the following errors/warnings were found:'); } $messages = array( 'error' => array_merge($errors, $publishErrors), 'warning' => $warnings, ); foreach ($messages as $style => $msgs) { foreach ($msgs as $msg) { $output->writeln('<' . $style . '>' . $msg . ''); } } return $errors || $publishErrors ? 1 : 0; } }