Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.67% covered (success)
96.67%
29 / 30
85.71% covered (warning)
85.71%
6 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
JsonSchemaValidator
96.67% covered (success)
96.67%
29 / 30
85.71% covered (warning)
85.71%
6 / 7
14
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
4
 areSchemasSupported
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSchemaBuilder
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 validateStrictly
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 validatePermissively
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 validate
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
5
 getSchemaVersion
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 JsonSchema\Validator;
7use MediaWiki\Extension\CommunityConfiguration\Schema\JsonSchema;
8use MediaWiki\Extension\CommunityConfiguration\Schema\JsonSchemaBuilder;
9use MediaWiki\Extension\CommunityConfiguration\Schema\JsonSchemaReader;
10use MediaWiki\Extension\CommunityConfiguration\Schema\SchemaBuilder;
11use Status;
12use StatusValue;
13
14/**
15 * JSON Schema validator.
16 */
17class JsonSchemaValidator implements IValidator {
18
19    private JsonSchemaReader $jsonSchema;
20    private JsonSchemaBuilder $jsonSchemaBuilder;
21
22    /**
23     * @param JsonSchema|string $classNameOrClassInstance JsonSchema derived class name (instance only allowed in tests)
24     */
25    public function __construct( $classNameOrClassInstance ) {
26        // @codeCoverageIgnoreStart
27        if ( is_object( $classNameOrClassInstance ) ) {
28            if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
29                throw new InvalidArgumentException(
30                    'JsonSchema should never be instantiated in production code'
31                );
32            }
33            if ( !( $classNameOrClassInstance instanceof JsonSchema ) ) {
34                throw new InvalidArgumentException(
35                    get_class( $classNameOrClassInstance ) . ' must be instance of ' . JsonSchema::class
36                );
37            }
38        }
39        // @codeCoverageIgnoreEnd
40
41        $this->jsonSchema = new JsonSchemaReader( $classNameOrClassInstance );
42        $this->jsonSchemaBuilder = new JsonSchemaBuilder( $this->jsonSchema );
43    }
44
45    /**
46     * @inheritDoc
47     */
48    public function areSchemasSupported(): bool {
49        return true;
50    }
51
52    /**
53     * @inheritDoc
54     */
55    public function getSchemaBuilder(): SchemaBuilder {
56        return $this->jsonSchemaBuilder;
57    }
58
59    /**
60     * @inheritDoc
61     */
62    public function validateStrictly( $config ): StatusValue {
63        return $this->validate( $config, false );
64    }
65
66    /**
67     * @inheritDoc
68     */
69    public function validatePermissively( $config ): StatusValue {
70        return $this->validate( $config, true );
71    }
72
73    /**
74     * @param mixed $config
75     * @param bool $modeForReading
76     * @return StatusValue
77     */
78    private function validate( $config, bool $modeForReading ): StatusValue {
79        $validator = new Validator();
80
81        $validator->validate(
82            $config,
83            $this->jsonSchemaBuilder->getRootSchema()
84        );
85        if ( $validator->isValid() ) {
86            return Status::newGood();
87        }
88        $status = new Status();
89        foreach ( $validator->getErrors() as $error ) {
90            if ( $modeForReading && in_array( $error['constraint'], [ 'required', 'additionalProp', 'enum' ] ) ) {
91                $status->warning(
92                    'communityconfiguration-schema-validation-error',
93                    $error['property'],
94                    $error['message'],
95                    $error
96                );
97            } else {
98                $status->fatal(
99                    'communityconfiguration-schema-validation-error',
100                    $error['property'],
101                    $error['message'],
102                    $error
103                );
104            }
105        }
106
107        return $status;
108    }
109
110    /**
111     * @inheritDoc
112     */
113    public function getSchemaVersion(): ?string {
114        return $this->jsonSchema->getVersion();
115    }
116}