Completed
Push — cs ( 148090 )
by Jeroen De
03:24
created

MapsMappingServices::getServiceInstance()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 0
cts 11
cp 0
rs 8.7972
c 0
b 0
f 0
cc 4
eloc 13
nc 4
nop 1
crap 20
1
<?php
2
3
/**
4
 * Class for interaction with MappingService objects.
5
 *
6
 * @since 0.6.6
7
 *
8
 * @licence GNU GPL v2+
9
 * @author Jeroen De Dauw < [email protected] >
10
 */
11
final class MapsMappingServices {
12
13
	/**
14
	 * Associative array containing service identifiers as keys and the names
15
	 * of service classes as values.
16
	 *
17
	 * @since 0.6.6
18
	 *
19
	 * @var string[]
20
	 */
21
	protected static $registeredServices = [];
22
23
	/**
24
	 * Associative with service identifiers as keys containing instances of
25
	 * the mapping service classes.
26
	 *
27
	 * Note: This list only contains the instances, so is not to be used for
28
	 * looping over all available services, as not all of them are guaranteed
29
	 * to have an instance already, use $registeredServices for this purpose.
30
	 *
31
	 * @since 0.6.6
32
	 *
33
	 * @var MapsMappingService[]
34
	 */
35
	protected static $services = [];
36
37
	/**
38
	 * Registers a service class linked to an identifier.
39
	 * Also allows automatic registration of a list of features for this service.
40
	 *
41
	 * @since 0.6.6
42
	 *
43
	 * @param string $serviceIdentifier
44
	 * @param string $serviceClassName
45
	 * @param string[] $features
46
	 */
47
	public static function registerService( $serviceIdentifier, $serviceClassName, array $features = [] ) {
48
		self::$registeredServices[$serviceIdentifier] = $serviceClassName;
49
50
		foreach ( $features as $featureName => $featureClassName ) {
51
			self::registerServiceFeature( $serviceIdentifier, $featureName, $featureClassName );
52
		}
53
	}
54
55
	/**
56
	 * Registeres a feature for a service object.
57
	 * Registers a warning when the service is not registered, but does not give an error.
58
	 *
59
	 * @since 0.6.6
60
	 *
61
	 * @param $serviceIdentifier String: internal service identifier
62
	 * @param $featureName String
63
	 * @param $featureClassName String
64
	 */
65
	public static function registerServiceFeature( $serviceIdentifier, $featureName, $featureClassName ) {
66
		if ( array_key_exists( $serviceIdentifier, self::$registeredServices ) ) {
67
			$service = self::getServiceInstance( $serviceIdentifier );
68
			$service->addFeature( $featureName, $featureClassName );
69
		}
70
		else {
71
			// If the feature is not registered, register a warning. This is not an error though!
72
			wfWarn(
73
				"Tried to register feature '$featureName' with class '$featureClassName' to non-registered service '$serviceIdentifier'."
74
			);
75
		}
76
	}
77
78
	/**
79
	 * Returns the instance of a service class. This method takes
80
	 * care of creating the instance if this is not done yet.
81
	 *
82
	 * @since 0.6.6
83
	 *
84
	 * @param string $serviceIdentifier
85
	 *
86
	 * @return MapsMappingService
87
	 * @throws MWException
88
	 */
89
	public static function getServiceInstance( $serviceIdentifier ) {
90
		if ( !array_key_exists( $serviceIdentifier, self::$services ) ) {
91
			if ( array_key_exists( $serviceIdentifier, self::$registeredServices ) ) {
92
				$service = new self::$registeredServices[$serviceIdentifier]( $serviceIdentifier );
93
94
				if ( $service instanceof MapsMappingService ) {
95
					self::$services[$serviceIdentifier] = $service;
96
				}
97
				else {
98
					throw new MWException(
99
						'The service object linked to service identifier ' . $serviceIdentifier . ' does not implement iMappingService.'
100
					);
101
				}
102
			}
103
			else {
104
				throw new MWException(
105
					'There is no service object linked to service identifier ' . $serviceIdentifier . '.'
106
				);
107
			}
108
		}
109
110
		return self::$services[$serviceIdentifier];
111
	}
112
113
	/**
114
	 * Retuns an instance of a MapsMappingService. The service name is validated
115
	 * and aliases are resolved and a check is made if the feature is supported.
116
	 * If the feature is not supported, or the service does not exist, defaulting
117
	 * will be used.
118
	 *
119
	 * @since 0.6.6
120
	 *
121
	 * @param $service String: service name or alias, does not need to be secure
122
	 * @param $feature String
123
	 *
124
	 * @return MapsMappingService
125
	 */
126
	public static function getValidServiceInstance( $service, $feature ) {
127
		return self::getServiceInstance( self::getValidServiceName( $service, $feature ) );
128
	}
129
130
	/**
131
	 * Returns a valid service. When an invalid service is provided, the default one will be returned.
132
	 * Aliases are also changed into the main service names @see MapsMappingServices::getMainServiceName.
133
	 *
134
	 * @since 0.6.6
135
	 *
136
	 * @param $service String: service name or alias, does not need to be secure
137
	 * @param $feature String
138
	 *
139
	 * @return string
140
	 */
141
	public static function getValidServiceName( $service, $feature ) {
142
		global $egMapsDefaultService, $egMapsDefaultServices;
143
144
		// Get rid of any aliases.
145
		// Also rely on this to instantiate all registered services.
146
		$service = self::getMainServiceName( $service );
147
148
		// Check if there is a mathing instance.
149
		$shouldChange = !array_key_exists( $service, self::$services );
150
151
		// If it should not be changed, ensure the service supports this feature.
152
		if ( !$shouldChange ) {
153
			$shouldChange = self::getServiceInstance( $service )->getFeature( $feature ) === false;
154
		}
155
156
		// Change the service to the most specific default value available.
157
		// Note: the default services should support their corresponding features.
158
		// If they don't, a fatal error will occur later on.
159
		if ( $shouldChange ) {
160
			if ( array_key_exists( $feature, $egMapsDefaultServices ) ) {
161
				$service = $egMapsDefaultServices[$feature];
162
			}
163
			else {
164
				$service = $egMapsDefaultService;
165
			}
166
		}
167
168
		return $service;
169
	}
170
171
	/**
172
	 * Checks if the service name is an alias for an actual service,
173
	 * and changes it into the main service name if this is the case.
174
	 *
175
	 * @since 0.6.6
176
	 *
177
	 * @param $serviceName String: service name or alias, does not need to be secure
178
	 *
179
	 * @return string
180
	 */
181
	protected static function getMainServiceName( $serviceName ) {
182
		if ( !array_key_exists( $serviceName, self::$services ) ) {
183
			foreach ( self::getServiceIdentifiers() as $serviceIdentifier ) {
184
				$service = self::getServiceInstance( $serviceIdentifier );
185
186
				if ( $service->hasAlias( $serviceName ) ) {
187
					$serviceName = $service->getName();
188
					break;
189
				}
190
			}
191
		}
192
193
		return $serviceName;
194
	}
195
196
	/**
197
	 * Returns an array with the identifiers for all registered services.
198
	 *
199
	 * @since 0.6.6
200
	 *
201
	 * @return array
202
	 */
203
	public static function getServiceIdentifiers() {
204
		return array_keys( self::$registeredServices );
205
	}
206
207
	/**
208
	 * Returns an array containing all the possible values for the service parameter, including aliases.
209
	 *
210
	 * @since 0.6.6
211
	 *
212
	 * @return array of string
213
	 */
214
	public static function getAllServiceValues() {
215
		global $egMapsAvailableServices;
216
217
		$allServiceValues = [];
218
219
		foreach ( $egMapsAvailableServices as $availableService ) {
220
			$allServiceValues[] = $availableService;
221
			$allServiceValues = array_merge(
222
				$allServiceValues,
223
				self::getServiceInstance( $availableService )->getAliases()
224
			);
225
		}
226
227
		return $allServiceValues;
228
	}
229
230
	/**
231
	 * Returns an array with an instance of a MappingService object for every available mapping service.
232
	 *
233
	 * @since 0.7.3
234
	 *
235
	 * @return array of MappingService
236
	 */
237
	public static function getAllObjects() {
238
		$objects = [];
239
240
		foreach ( self::$registeredServices as $service => $class ) {
241
			$objects[] = self::getServiceInstance( $service );
242
		}
243
244
		return $objects;
245
	}
246
247
}
248