Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
ValidatorFactory
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
3 / 3
5
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 newValidator
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
3
 getSupportedKeys
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace MediaWiki\Extension\CommunityConfiguration\Validation;
4
5use InvalidArgumentException;
6use MediaWiki\Config\ServiceOptions;
7use Wikimedia\ObjectFactory\ObjectFactory;
8
9/**
10 * Create a configuration validation object
11 *
12 * Configuration returned by an IConfigurationStore needs to be validated. This factory is
13 * responsible for constructing an IValidator that can validate a given config file.
14 *
15 * Configuration of available validators is included in $wgCommunityConfigurationValidators,
16 * which can look like this (dict of ObjectFactory specs keyed by validator name):
17 *
18 * {
19 *     "noop": {
20 *         "class": "MediaWiki\\Extension\\CommunityConfiguration\\Validation\\NoopValidator",
21 *         "services": []
22 *     },
23 *     "jsonschema": {
24 *         "class": "MediaWiki\\Extension\\CommunityConfiguration\\Validation\\JsonSchemaValidator",
25 *         "services": []
26 *     }
27 * }
28 */
29class ValidatorFactory {
30
31    /**
32     * @var string[]
33     * @internal for use in ServiceWiring only
34     */
35    public const CONSTRUCTOR_OPTIONS = [
36        'CommunityConfigurationValidators',
37    ];
38
39    /** @var array ObjectFactory specs for validators, indexed by validator name */
40    private array $validatorSpecs;
41    /** @var IValidator[] validators indexed by name */
42    private array $validators = [];
43    private ObjectFactory $objectFactory;
44
45    /**
46     * @param ServiceOptions $options
47     * @param ObjectFactory $objectFactory
48     */
49    public function __construct(
50        ServiceOptions $options,
51        ObjectFactory $objectFactory
52    ) {
53        $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
54        $this->validatorSpecs = $options->get( 'CommunityConfigurationValidators' );
55
56        $this->objectFactory = $objectFactory;
57    }
58
59    /**
60     * Construct a new validator
61     *
62     * @param string $name Provider name (from CommunityConfigurationProviders attribute)
63     * @param string $type Validator key (from CommunityConfigurationValidators)
64     * @param array $validatorArgs
65     * @return IValidator
66     */
67    public function newValidator( string $name, string $type, array $validatorArgs ): IValidator {
68        if ( !array_key_exists( $type, $this->validatorSpecs ) ) {
69            throw new InvalidArgumentException( "Validator $type is not supported" );
70        }
71        $validatorKey = $name . '_' . $type;
72        if ( !array_key_exists( $validatorKey, $this->validators ) ) {
73            $this->validators[$validatorKey] = $this->objectFactory->createObject(
74                $this->validatorSpecs[$type],
75                [
76                    'assertClass' => IValidator::class,
77                    'extraArgs' => $validatorArgs,
78                ],
79            );
80        }
81
82        return $this->validators[$validatorKey];
83    }
84
85    /**
86     * Return a list of supported validators
87     *
88     * @return string[] List of validator names (supported by newValidator)
89     */
90    public function getSupportedKeys(): array {
91        return array_keys( $this->validatorSpecs );
92    }
93}