Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ConfigValidatorFactory
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 5
182
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 titleEquals
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getSupportedConfigPages
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 constructValidator
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
42
 newConfigValidator
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace GrowthExperiments\Config\Validation;
4
5use GrowthExperiments\NewcomerTasks\TaskType\TaskTypeHandlerRegistry;
6use InvalidArgumentException;
7use MediaWiki\Config\Config;
8use MediaWiki\Linker\LinkTarget;
9use MediaWiki\Title\Title;
10use MediaWiki\Title\TitleFactory;
11
12class ConfigValidatorFactory {
13    private Config $config;
14    private TitleFactory $titleFactory;
15    private TaskTypeHandlerRegistry $taskTypeHandlerRegistry;
16
17    /**
18     * @var string[]
19     *
20     * Maps variable to validator class.
21     *
22     * @note When adding a mapping, add an entry to ConfigValidatorFactory::constructValidator
23     * as well.
24     */
25    private const CONFIG_VALIDATOR_MAP = [
26        'GEWikiConfigPageTitle' => GrowthConfigValidation::class,
27        'GENewcomerTasksConfigTitle' => NewcomerTasksValidator::class,
28        'GENewcomerTasksOresTopicConfigTitle' => NoValidationValidator::class,
29        'GENewcomerTasksTopicConfigTitle' => NoValidationValidator::class,
30        'GEStructuredMentorList' => StructuredMentorListValidator::class,
31    ];
32
33    /**
34     * @param Config $config
35     * @param TitleFactory $titleFactory
36     * @param TaskTypeHandlerRegistry $taskTypeHandlerRegistry
37     */
38    public function __construct(
39        Config $config,
40        TitleFactory $titleFactory,
41
42        // Dependencies for validators
43        TaskTypeHandlerRegistry $taskTypeHandlerRegistry
44    ) {
45        $this->config = $config;
46        $this->titleFactory = $titleFactory;
47
48        // Dependencies for validators
49        $this->taskTypeHandlerRegistry = $taskTypeHandlerRegistry;
50    }
51
52    /**
53     * Code helper for comparing titles
54     *
55     * @param Title $configTitle
56     * @param string $otherConfigPage
57     * @return bool
58     */
59    private function titleEquals( Title $configTitle, string $otherConfigPage ): bool {
60        $varTitle = $this->titleFactory
61            ->newFromText( $otherConfigPage );
62        return $varTitle !== null && $configTitle->equals( $varTitle );
63    }
64
65    /**
66     * Return list of supported config pages
67     *
68     * @return Title[]
69     */
70    public function getSupportedConfigPages(): array {
71        return array_filter(
72            array_map(
73                function ( string $var ) {
74                    return $this->titleFactory->newFromText(
75                        $this->config->get( $var )
76                    );
77                },
78                array_keys( self::CONFIG_VALIDATOR_MAP )
79            )
80        );
81    }
82
83    /**
84     * Construct given validator
85     *
86     * @param string $class A ::class constant from one of the validators
87     * @return IConfigValidator
88     * @throws InvalidArgumentException when passed class is not supported; this should never
89     * happen in practice.
90     */
91    private function constructValidator( string $class ): IConfigValidator {
92        switch ( $class ) {
93            case GrowthConfigValidation::class:
94                return new GrowthConfigValidation();
95            case NewcomerTasksValidator::class:
96                return new NewcomerTasksValidator(
97                    $this->taskTypeHandlerRegistry
98                );
99            case StructuredMentorListValidator::class:
100                return new StructuredMentorListValidator();
101            case NoValidationValidator::class:
102                return new NoValidationValidator();
103            default:
104                throw new InvalidArgumentException( 'Unsupported config class' );
105        }
106    }
107
108    /**
109     * Generate a validator for a config page
110     *
111     * @param LinkTarget $configPage
112     * @return IConfigValidator
113     * @throws InvalidArgumentException when passed config page is not recognized; this should
114     * never happen in practice.
115     */
116    public function newConfigValidator( LinkTarget $configPage ): IConfigValidator {
117        $title = $this->titleFactory->newFromLinkTarget( $configPage );
118
119        foreach ( self::CONFIG_VALIDATOR_MAP as $var => $validatorClass ) {
120            if ( $this->titleEquals( $title, $this->config->get( $var ) ) ) {
121                return $this->constructValidator( $validatorClass );
122            }
123        }
124
125        throw new InvalidArgumentException( 'Unsupported config page' );
126    }
127}