Completed
Push — master ( ebda25...4c5acd )
by Jeroen De
01:42
created

ParamDefinitionFactory::newDefault()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.9666
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2
1
<?php
2
3
namespace ParamProcessor;
4
5
use Exception;
6
use OutOfBoundsException;
7
use ValueParsers\NullParser;
8
use ValueValidators\NullValidator;
9
10
/**
11
 * Factory for ParamDefinition implementing objects.
12
 *
13
 * @licence GNU GPL v2+
14
 * @author Jeroen De Dauw < [email protected] >
15
 */
16
class ParamDefinitionFactory {
17
18
	/**
19
	 * Maps parameter type to handling ParameterDefinition implementing class.
20
	 *
21
	 * @since 1.0
22
	 *
23
	 * @var array
24
	 */
25
	private $typeToClass = [];
26
27
	/**
28
	 * Maps parameter type to its associated components.
29
	 *
30
	 * @since 1.0
31
	 *
32
	 * @var array
33
	 */
34
	private $typeToComponent = [];
35
36
	/**
37
	 * @since 1.6
38
	 */
39 6
	public static function newDefault(): self {
40 6
		$instance = new self();
41
42 6
		foreach ( ParameterTypes::getCoreTypes() as $type => $data ) {
43 6
			$instance->registerType( $type, $data );
44
		}
45
46 6
		return $instance;
47
	}
48
49
	/**
50
	 * @deprecated since 1.0
51
	 */
52 64
	public static function singleton(): self {
53 64
		static $instance = false;
54
55 64
		if ( $instance === false ) {
56
			$instance = new self();
57
			$instance->registerGlobals();
0 ignored issues
show
Deprecated Code introduced by
The method ParamProcessor\ParamDefi...tory::registerGlobals() has been deprecated with message: since 1.6

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
58
		}
59
60 64
		return $instance;
61
	}
62
63
	/**
64
	 * Registers the parameter types specified in the global $wgParamDefinitions.
65
	 * @deprecated since 1.6
66
	 */
67
	public function registerGlobals() {
68
		if ( array_key_exists( 'wgParamDefinitions', $GLOBALS ) ) {
69
			foreach ( $GLOBALS['wgParamDefinitions'] as $type => $data ) {
70
				if ( is_string( $data ) ) {
71
					$data = [ 'definition' => $data ];
72
				}
73
74
				$this->registerType( $type, $data );
75
			}
76
		}
77
	}
78
79
	/**
80
	 * Registers a parameter type.
81
	 *
82
	 * The type is specified as a string identifier for the type, ie 'boolean',
83
	 * and an array containing further data. This data currently includes:
84
	 *
85
	 * - string-parser:       the parser to use to transform string values
86
	 *                        This class needs to implement ValueParser. Default: NullParser
87
	 * - typed-parser:        the parser to use to transform typed PHP values
88
	 *                        This class needs to implement ValueParser. Default: NullParser
89
	 * - validator:           the validation object to use
90
	 *                        This class needs to implement ValueValidator. Default: NullValidator
91
	 * - validation-callback  a callback to use for validation, called before the ValueValidator
92
	 *                        This callback needs to return a boolean indicating validity.
93
	 *
94
	 * @since 1.0
95
	 *
96
	 * @param string $type
97
	 * @param array $data
98
	 *
99
	 * @return boolean Indicates if the type was registered
100
	 */
101 6
	public function registerType( $type, array $data ) {
102 6
		if ( array_key_exists( $type, $this->typeToClass ) ) {
103
			return false;
104
		}
105
106 6
		$class = array_key_exists( 'definition', $data ) ? $data['definition'] : ParamDefinition::class;
107 6
		$this->typeToClass[$type] = $class;
108
109
		$defaults = [
110 6
			'string-parser' => NullParser::class,
111
			'typed-parser' => NullParser::class,
112
			'validator' => NullValidator::class,
113
			'validation-callback' => null,
114
		];
115
116 6
		$this->typeToComponent[$type] = [];
117
118 6
		foreach ( $defaults as $component => $default ) {
119 6
			$this->typeToComponent[$type][$component] = array_key_exists( $component, $data ) ? $data[$component] : $default;
120
		}
121
122 6
		return true;
123
	}
124
125
	/**
126
	 * Creates a new instance of a ParamDefinition based on the provided type.
127
	 *
128
	 * @since 1.0
129
	 *
130
	 * @param string $type
131
	 * @param string $name
132
	 * @param mixed $default
133
	 * @param string $message
134
	 * @param boolean $isList
135
	 *
136
	 * @return ParamDefinition
137
	 * @throws OutOfBoundsException
138
	 */
139 42
	public function newDefinition( string $type, string $name, $default, string $message, bool $isList = false ): ParamDefinition {
140 42
		if ( !array_key_exists( $type, $this->typeToClass ) ) {
141
			throw new OutOfBoundsException( 'Unknown parameter type "' . $type . '".' );
142
		}
143
144 42
		$class = $this->typeToClass[$type];
145
146
		/**
147
		 * @var ParamDefinition $definition
148
		 */
149 42
		$definition = new $class(
150 42
			$type,
151
			$name,
152
			$default,
153
			$message,
154
			$isList
155
		);
156
157 42
		$validator = $this->typeToComponent[$type]['validator'];
158
159 42
		if ( $validator !== NullValidator::class ) {
160 42
			$definition->setValueValidator( new $validator() );
161
		}
162
163 42
		$validationCallback = $this->typeToComponent[$type]['validation-callback'];
164
165 42
		if ( $validationCallback !== null ) {
166 39
			$definition->setValidationCallback( $validationCallback );
167
		}
168
169 42
		return $definition;
170
	}
171
172
	/**
173
	 * Returns the specified component for the provided parameter type.
174
	 * This method is likely to change in the future in a compat breaking way.
175
	 *
176
	 * @since 1.0
177
	 *
178
	 * @param string $paramType
179
	 * @param string $componentType
180
	 *
181
	 * @throws Exception
182
	 * @return mixed
183
	 */
184 64
	public function getComponentForType( $paramType, $componentType ) {
185 64
		if ( !array_key_exists( $paramType, $this->typeToComponent ) ) {
186
			throw new Exception( 'Unknown parameter type "' . $paramType . '".' );
187
		}
188
189 64
		if ( !array_key_exists( $componentType, $this->typeToComponent[$paramType] ) ) {
190
			throw new Exception( 'Unknown parameter component type "' . $paramType . '".' );
191
		}
192
193 64
		return $this->typeToComponent[$paramType][$componentType];
194
	}
195
196
	/**
197
	 * Construct a new ParamDefinition from an array.
198
	 *
199
	 * @since 1.0
200
	 *
201
	 * @param array $param
202
	 * @param bool $getMad DEPRECATED since 1.6
203
	 *
204
	 * @return ParamDefinition|false
205
	 * @throws Exception
206
	 */
207 41
	public function newDefinitionFromArray( array $param, $getMad = true ) {
208 41
		foreach ( [ 'name', 'message' ] as $requiredElement ) {
209 41
			if ( !array_key_exists( $requiredElement, $param ) ) {
210
				if ( $getMad ) {
211
					throw new Exception( 'Could not construct a ParamDefinition from an array without ' . $requiredElement . ' element' );
212
				}
213
214
				return false;
215
			}
216
		}
217
218 41
		$parameter = $this->newDefinition(
219 41
			array_key_exists( 'type', $param ) ? $param['type'] : 'string',
220 41
			$param['name'],
221 41
			array_key_exists( 'default', $param ) ? $param['default'] : null,
222 41
			$param['message'],
223 41
			array_key_exists( 'islist', $param ) ? $param['islist'] : false
224
		);
225
226 41
		$parameter->setArrayValues( $param );
227
228 41
		return $parameter;
229
	}
230
231
}
232