Completed
Pull Request — master (#877)
by wiese
64:32
created

ValidateConfigCommand::execute()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 14
nc 6
nop 2
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\Fundraising\Frontend\Cli\ConfigValidation;
6
7
use FileFetcher\SimpleFileFetcher;
8
use League\JsonGuard\Validator as JSONSchemaValidator;
9
use Symfony\Component\Console\Command\Command;
10
use Symfony\Component\Console\Input\InputArgument;
11
use Symfony\Component\Console\Input\InputDefinition;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Input\InputOption;
14
use Symfony\Component\Console\Output\ConsoleOutputInterface;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use WMDE\Fundraising\Frontend\Infrastructure\ConfigReader;
17
18
/**
19
 * @license GNU GPL v2+
20
 * @author Gabriel Birke < [email protected] >
21
 */
22
class ValidateConfigCommand extends Command {
23
24
	const NAME = 'validate-config';
25
	const DEFAULT_SCHEMA = __DIR__ . '/../../app/config/schema.json';
26
	const ERROR_RETURN_CODE = 1;
27
	const OK_RETURN_CODE = 0;
28
29
	protected function configure(): void {
30
		$this->setName( self::NAME )
31
			->setDescription( 'Validate configuration files' )
32
			->setHelp( 'This command merges the specified configuration files and validates them against a JSON schema' )
33
			->setDefinition(
34
				new InputDefinition( [
35
					new InputOption(
36
						'schema',
37
						's',
38
						InputOption::VALUE_REQUIRED,
39
						'JSON schema file',
40
						realpath( self::DEFAULT_SCHEMA )
41
					),
42
					new InputOption(
43
						'dump-config',
44
						'd',
45
						InputOption::VALUE_NONE,
46
						'Dump merged configuration'
47
					),
48
					new InputArgument( 'config_file', InputArgument::REQUIRED + InputArgument::IS_ARRAY ),
49
				] )
50
			);
51
	}
52
53
	protected function execute( InputInterface $input, OutputInterface $output ): int {
54
		$configObject = $this->loadConfigObjectFromFiles( $input->getArgument( 'config_file' ) );
55
56
		if ( $input->getOption( 'dump-config' ) ) {
57
			$output->writeln( json_encode( $configObject, JSON_PRETTY_PRINT ) );
58
		}
59
60
		$schema = ( new SchemaLoader( new SimpleFileFetcher() ) )->loadSchema( $input->getOption( 'schema' ) );
61
62
		$validator = new JSONSchemaValidator(
63
			$configObject,
64
			$schema
65
		);
66
67
		if ( $validator->passes() ) {
68
			return self::OK_RETURN_CODE;
69
		}
70
71
		$renderer = new ValidationErrorRenderer( $schema );
72
		foreach ( $validator->errors() as $error ) {
73
			$output->writeln( $renderer->render( $error ) );
74
		}
75
76
		return self::ERROR_RETURN_CODE;
77
	}
78
79
	/**
80
	 * @throws \RuntimeException
81
	 * @param array $configFiles
82
	 * @return \stdClass
83
	 */
84
	private function loadConfigObjectFromFiles( array $configFiles ): \stdClass {
85
		$configReader = new ConfigReader(
86
			new SimpleFileFetcher(),
87
			...$configFiles
88
		);
89
90
		return $configReader->getConfigObject();
91
	}
92
93
	private function writeError( OutputInterface $output, string $message ) {
94
		$errOutput = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output;
95
		$errOutput->writeln( $message );
96
	}
97
98
}