Completed
Push — rmol ( fe50d5 )
by Jeroen De
03:31
created

MapsSetup   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 425
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 22.1%

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 11
dl 0
loc 425
ccs 40
cts 181
cp 0.221
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A setup() 0 8 3
A registerAllTheThings() 0 11 1
A defaultSettings() 0 17 5
A registerWebResources() 0 6 1
B registerParserHooks() 0 71 4
A registerMappingServices() 0 23 1
B registerGoogleMapsModules() 0 85 1
B registerLeafletModules() 0 125 1
A registerPermissions() 0 10 3
A registerParameterTypes() 0 41 1
A registerHooks() 0 4 1
A registerApiModules() 0 3 1
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace Maps;
6
7
use DataValues\Geo\Parsers\LatLongParser;
8
use Maps\DataAccess\JsonFileParser;
9
use Maps\MediaWiki\Api\Geocode;
10
use Maps\MediaWiki\Content\GeoJsonContent;
11
use Maps\MediaWiki\Content\GeoJsonContentHandler;
12
use Maps\MediaWiki\ParserHooks\CoordinatesFunction;
13
use Maps\MediaWiki\ParserHooks\DisplayMapFunction;
14
use Maps\MediaWiki\ParserHooks\DisplayMapRenderer;
15
use Maps\MediaWiki\ParserHooks\DistanceFunction;
16
use Maps\MediaWiki\ParserHooks\FindDestinationFunction;
17
use Maps\MediaWiki\ParserHooks\GeocodeFunction;
18
use Maps\MediaWiki\ParserHooks\GeoDistanceFunction;
19
use Maps\MediaWiki\ParserHooks\MapsDocFunction;
20
use Maps\Presentation\WikitextParsers\CircleParser;
21
use Maps\Presentation\WikitextParsers\DistanceParser;
22
use Maps\Presentation\WikitextParsers\ImageOverlayParser;
23
use Maps\Presentation\WikitextParsers\LineParser;
24
use Maps\Presentation\WikitextParsers\LocationParser;
25
use Maps\Presentation\WikitextParsers\PolygonParser;
26
use Maps\Presentation\WikitextParsers\RectangleParser;
27
use Maps\Presentation\WikitextParsers\WmsOverlayParser;
28
use Parser;
29
use PPFrame;
30
31
/**
32
 * @licence GNU GPL v2+
33
 * @author Jeroen De Dauw < [email protected] >
34
 */
35
class MapsSetup {
36
37
	private $mwGlobals;
38
39
	public function __construct( array &$mwGlobals ) {
40
		$this->mwGlobals = $mwGlobals;
41
	}
42
43
	public function setup() {
44
		$this->defaultSettings();
45
		$this->registerAllTheThings();
46
47
		if ( !$this->mwGlobals['egMapsDisableSmwIntegration'] && defined( 'SMW_VERSION' ) ) {
48
			SemanticMaps::newFromMediaWikiGlobals( $this->mwGlobals )->initExtension();
49
		}
50
	}
51
52
	private function registerAllTheThings() {
53
		$this->registerWebResources();
54
		$this->registerApiModules();
55
		$this->registerParserHooks();
56
		$this->registerMappingServices();
57
		$this->registerPermissions();
58
		$this->registerParameterTypes();
59
		$this->registerHooks();
60
61
		$this->mwGlobals['wgContentHandlers'][GeoJsonContent::CONTENT_MODEL_ID] = GeoJsonContentHandler::class;
62
	}
63
64
	private function defaultSettings() {
65
		if ( $this->mwGlobals['egMapsGMaps3Language'] === '' ) {
66
			$this->mwGlobals['egMapsGMaps3Language'] = $this->mwGlobals['wgLang'];
67
		}
68
69
		if ( in_array( 'googlemaps3', $this->mwGlobals['egMapsAvailableServices'] ) ) {
70
			$this->mwGlobals['wgSpecialPages']['MapEditor'] = 'Maps\MediaWiki\Specials\SpecialMapEditor';
71
			$this->mwGlobals['wgSpecialPageGroups']['MapEditor'] = 'Maps';
72
		}
73
74
		if ( $this->mwGlobals['egMapsGMaps3ApiKey'] === '' && array_key_exists(
75
				'egGoogleJsApiKey',
76
				$this->mwGlobals
77
			) ) {
78
			$this->mwGlobals['egMapsGMaps3ApiKey'] = $this->mwGlobals['egGoogleJsApiKey'];
79
		}
80
	}
81
82
	private function registerWebResources() {
83
		$this->mwGlobals['wgResourceModules'] = array_merge(
84
			$this->mwGlobals['wgResourceModules'],
85
			include __DIR__ . '/../Maps.resources.php'
86
		);
87
	}
88
89
	private function registerParserHooks() {
90 49
		$this->mwGlobals['wgHooks']['ParserFirstCallInit'][] = function ( Parser &$parser ) {
91 49
			$instance = new CoordinatesFunction();
92 49
			return $instance->init( $parser );
93
		};
94
95 49
		$this->mwGlobals['wgHooks']['ParserFirstCallInit'][] = function ( Parser &$parser ) {
96 49
			foreach ( [ 'display_map', 'display_point', 'display_points', 'display_line' ] as $hookName ) {
97 49
				$parser->setFunctionHook(
98 49
					$hookName,
99 49
					function ( Parser $parser, PPFrame $frame, array $arguments ) {
100 18
						$hook = new DisplayMapFunction();
101
102 18
						$mapHtml = $hook->getMapHtmlForKeyValueStrings(
103 18
							$parser,
104 18
							array_map(
105 18
								function ( $argument ) use ( $frame ) {
106 18
									return $frame->expand( $argument );
107 18
								},
108 18
								$arguments
109
							)
110
						);
111
112
						return [
113 18
							$mapHtml,
114
							'noparse' => true,
115
							'isHTML' => true,
116
						];
117 49
					},
118 49
					Parser::SFH_OBJECT_ARGS
119
				);
120
121 49
				$parser->setHook(
122 49
					$hookName,
123 49
					function ( $text, array $arguments, Parser $parser ) {
124 2
						if ( $text !== null ) {
125 2
							$defaultParameters = DisplayMapFunction::getHookDefinition( "\n" )->getDefaultParameters();
126 2
							$defaultParam = array_shift( $defaultParameters );
127
128
							// If there is a first default parameter, set the tag contents as its value.
129 2
							if ( $defaultParam !== null ) {
130 2
								$arguments[$defaultParam] = $text;
131
							}
132
						}
133
134 2
						return ( new DisplayMapFunction() )->getMapHtmlForParameterList( $parser, $arguments );
135 49
					}
136
				);
137
			}
138 49
		};
139
140 49
		$this->mwGlobals['wgHooks']['ParserFirstCallInit'][] = function ( Parser &$parser ) {
141 49
			return ( new DistanceFunction() )->init( $parser );
142
		};
143
144 49
		$this->mwGlobals['wgHooks']['ParserFirstCallInit'][] = function ( Parser &$parser ) {
145 49
			return ( new FindDestinationFunction() )->init( $parser );
146
		};
147
148 49
		$this->mwGlobals['wgHooks']['ParserFirstCallInit'][] = function ( Parser &$parser ) {
149 49
			return ( new GeocodeFunction() )->init( $parser );
150
		};
151
152 49
		$this->mwGlobals['wgHooks']['ParserFirstCallInit'][] = function ( Parser &$parser ) {
153 49
			return ( new GeoDistanceFunction() )->init( $parser );
154
		};
155
156 49
		$this->mwGlobals['wgHooks']['ParserFirstCallInit'][] = function ( Parser &$parser ) {
157 49
			return ( new MapsDocFunction() )->init( $parser );
158
		};
159
	}
160
161
	private function registerMappingServices() {
162
		$localBasePath = __DIR__ . '/../resources';
163
		$remoteExtPath = array_slice(
164
				explode( '/', str_replace( DIRECTORY_SEPARATOR, '/', __DIR__ ) ),
165
				-2,
166
				1
167
			)[0] . '/../resources';
168
169
		$this->registerGoogleMapsModules( $localBasePath, $remoteExtPath );
170
171
		MappingServices::registerService( 'googlemaps3', GoogleMapsService::class );
172
173
		$googleMaps = MappingServices::getServiceInstance( 'googlemaps3' );
174
		$googleMaps->addFeature( 'display_map', DisplayMapRenderer::class );
175
176
177
		// Leaflet API
178
		$this->registerLeafletModules( $localBasePath, $remoteExtPath );
179
180
		MappingServices::registerService( 'leaflet', LeafletService::class );
181
		$leafletMaps = MappingServices::getServiceInstance( 'leaflet' );
182
		$leafletMaps->addFeature( 'display_map', DisplayMapRenderer::class );
183
	}
184
185
	private function registerGoogleMapsModules( string $localBasePath, string $remoteExtPath ) {
186
		global $wgResourceModules;
187
188
		$localBasePath = $localBasePath . '/GoogleMaps';
189
		$remoteExtPath = $remoteExtPath . '/GoogleMaps';
190
191
		$wgResourceModules['ext.maps.googlemaps3'] = [
192
			'dependencies' => [ 'ext.maps.common' ],
193
			'localBasePath' => $localBasePath,
194
			'remoteExtPath' => $remoteExtPath,
195
			'group' => 'ext.maps',
196
			'targets' => [
197
				'mobile',
198
				'desktop'
199
			],
200
			'scripts' => [
201
				'jquery.googlemap.js',
202
				'ext.maps.googlemaps3.js'
203
			],
204
			'messages' => [
205
				'maps-googlemaps3-incompatbrowser',
206
				'maps-copycoords-prompt',
207
				'maps-searchmarkers-text',
208
				'maps-fullscreen-button',
209
				'maps-fullscreen-button-tooltip',
210
			]
211
		];
212
213
		$wgResourceModules['ext.maps.gm3.markercluster'] = [
214
			'localBasePath' => $localBasePath . '/gm3-util-library',
215
			'remoteExtPath' => $remoteExtPath . '/gm3-util-library',
216
			'group' => 'ext.maps',
217
			'targets' => [
218
				'mobile',
219
				'desktop'
220
			],
221
			'scripts' => [
222
				'markerclusterer.js',
223
			],
224
		];
225
226
		$wgResourceModules['ext.maps.gm3.markerwithlabel'] = [
227
			'localBasePath' => $localBasePath . '/gm3-util-library',
228
			'remoteExtPath' => $remoteExtPath  . '/gm3-util-library',
229
			'group' => 'ext.maps',
230
			'targets' => [
231
				'mobile',
232
				'desktop'
233
			],
234
			'scripts' => [
235
				'markerwithlabel.js',
236
			],
237
			'styles' => [
238
				'markerwithlabel.css',
239
			],
240
		];
241
242
		$wgResourceModules['ext.maps.gm3.geoxml'] = [
243
			'localBasePath' => $localBasePath . '/geoxml3',
244
			'remoteExtPath' => $remoteExtPath,
245
			'group' => 'ext.maps' . '/geoxml3',
246
			'targets' => [
247
				'mobile',
248
				'desktop'
249
			],
250
			'scripts' => [
251
				'geoxml3.js',
252
				'ZipFile.complete.js', //kmz handling
253
				'ProjectedOverlay.js', //Overlay handling
254
			],
255
		];
256
257
		$wgResourceModules['ext.maps.gm3.earth'] = [
258
			'localBasePath' => $localBasePath . '/gm3-util-library',
259
			'remoteExtPath' => $remoteExtPath  . '/gm3-util-library',
260
			'group' => 'ext.maps',
261
			'targets' => [
262
				'mobile',
263
				'desktop'
264
			],
265
			'scripts' => [
266
				'googleearth-compiled.js',
267
			],
268
		];
269
	}
270
271
	private function registerLeafletModules( string $localBasePath, string $remoteExtPath ) {
272
		global $wgResourceModules;
273
274
		$localBasePath = $localBasePath . '/leaflet';
275
		$remoteExtPath = $remoteExtPath . '/leaflet';
276
277
		$wgResourceModules['ext.maps.leaflet.base'] = [
278
			'localBasePath' => $localBasePath . '/leaflet',
279
			'remoteExtPath' => $remoteExtPath . '/leaflet',
280
			'group' => 'ext.maps',
281
			'targets' => [
282
				'mobile',
283
				'desktop'
284
			],
285
			'scripts' => [
286
				'leaflet.js',
287
			],
288
			'styles' => [
289
				'leaflet.css',
290
			],
291
		];
292
293
		$wgResourceModules['ext.maps.leaflet'] = [
294
			'dependencies' => [
295
				'ext.maps.common',
296
				'ext.maps.services',
297
				'ext.maps.leaflet.base'
298
			],
299
			'localBasePath' => $localBasePath,
300
			'remoteExtPath' => $remoteExtPath,
301
			'group' => 'ext.maps',
302
			'targets' => [
303
				'mobile',
304
				'desktop'
305
			],
306
			'scripts' => [
307
				'jquery.leaflet.js',
308
				'ext.maps.leaflet.js',
309
			],
310
			'messages' => [
311
				'maps-markers',
312
				'maps-copycoords-prompt',
313
				'maps-searchmarkers-text',
314
			],
315
		];
316
317
		$wgResourceModules['ext.maps.leaflet.fullscreen'] = [
318
			'dependencies' => [ 'ext.maps.leaflet' ],
319
			'localBasePath' => $localBasePath . '/leaflet.fullscreen',
320
			'remoteExtPath' => $remoteExtPath . '/leaflet.fullscreen',
321
			'group' => 'ext.maps',
322
			'targets' => [
323
				'mobile',
324
				'desktop'
325
			],
326
			'scripts' => [
327
				'Control.FullScreen.js',
328
			],
329
			'styles' => [
330
				'Control.FullScreen.css',
331
			],
332
		];
333
334
		$wgResourceModules['ext.maps.leaflet.markercluster'] = [
335
			'dependencies' => [ 'ext.maps.leaflet' ],
336
			'localBasePath' => $localBasePath . '/leaflet.markercluster',
337
			'remoteExtPath' => $remoteExtPath . '/leaflet.markercluster',
338
			'group' => 'ext.maps',
339
			'targets' => [
340
				'mobile',
341
				'desktop'
342
			],
343
			'scripts' => [
344
				'leaflet.markercluster.js',
345
			],
346
			'styles' => [
347
				'MarkerCluster.css',
348
			],
349
		];
350
351
		$wgResourceModules['ext.maps.leaflet.providers'] = [
352
			'dependencies' => [ 'ext.maps.leaflet' ],
353
			'localBasePath' => $localBasePath . '/leaflet-providers',
354
			'remoteExtPath' => $remoteExtPath . '/leaflet-providers',
355
			'group' => 'ext.maps',
356
			'targets' => [
357
				'mobile',
358
				'desktop'
359
			],
360
			'scripts' => [
361
				'leaflet-providers.js',
362
			],
363
		];
364
365
		$wgResourceModules['ext.maps.leaflet.editable'] = [
366
			'dependencies' => [ 'ext.maps.leaflet.base' ],
367
			'localBasePath' => $localBasePath . '/leaflet.editable',
368
			'remoteExtPath' => $remoteExtPath . '/leaflet.editable',
369
			'group' => 'ext.maps',
370
			'targets' => [
371
				'mobile',
372
				'desktop'
373
			],
374
			'scripts' => [
375
				'Leaflet.Editable.js',
376
			],
377
		];
378
379
		$wgResourceModules['ext.maps.leaflet.editor'] = [
380
			'dependencies' => [
381
				'ext.maps.leaflet.base',
382
				//'ext.maps.leaflet.editable'
383
			],
384
			'localBasePath' => $localBasePath,
385
			'remoteExtPath' => $remoteExtPath,
386
			'group' => 'ext.maps',
387
			'targets' => [
388
				'mobile',
389
				'desktop'
390
			],
391
			'scripts' => [
392
				'leaflet.editor.js',
393
			],
394
		];
395
	}
396
397
	private function registerPermissions() {
398
		$this->mwGlobals['wgAvailableRights'][] = 'geocode';
399
400
		// Users that can geocode. By default the same as those that can edit.
401
		foreach ( $this->mwGlobals['wgGroupPermissions'] as $group => $rights ) {
402
			if ( array_key_exists( 'edit', $rights ) ) {
403
				$this->mwGlobals['wgGroupPermissions'][$group]['geocode'] = $this->mwGlobals['wgGroupPermissions'][$group]['edit'];
404
			}
405
		}
406
	}
407
408
	private function registerParameterTypes() {
409
		$this->mwGlobals['wgParamDefinitions']['coordinate'] = [
410
			'string-parser' => LatLongParser::class,
411
		];
412
413
		$this->mwGlobals['wgParamDefinitions']['mapslocation'] = [
414
			'string-parser' => LocationParser::class,
415
		];
416
417
		$this->mwGlobals['wgParamDefinitions']['mapsline'] = [
418
			'string-parser' => LineParser::class,
419
		];
420
421
		$this->mwGlobals['wgParamDefinitions']['mapscircle'] = [
422
			'string-parser' => CircleParser::class,
423
		];
424
425
		$this->mwGlobals['wgParamDefinitions']['mapsrectangle'] = [
426
			'string-parser' => RectangleParser::class,
427
		];
428
429
		$this->mwGlobals['wgParamDefinitions']['mapspolygon'] = [
430
			'string-parser' => PolygonParser::class,
431
		];
432
433
		$this->mwGlobals['wgParamDefinitions']['distance'] = [
434
			'string-parser' => DistanceParser::class,
435
		];
436
437
		$this->mwGlobals['wgParamDefinitions']['wmsoverlay'] = [
438
			'string-parser' => WmsOverlayParser::class,
439
		];
440
441
		$this->mwGlobals['wgParamDefinitions']['mapsimageoverlay'] = [
442
			'string-parser' => ImageOverlayParser::class,
443
		];
444
445
		$this->mwGlobals['wgParamDefinitions']['jsonfile'] = [
446
			'string-parser' => JsonFileParser::class,
447
		];
448
	}
449
450
	private function registerHooks() {
451
		$this->mwGlobals['wgHooks']['AdminLinks'][] = 'Maps\MediaWiki\MapsHooks::addToAdminLinks';
452
		$this->mwGlobals['wgHooks']['MakeGlobalVariablesScript'][] = 'Maps\MediaWiki\MapsHooks::onMakeGlobalVariablesScript';
453
	}
454
455
	private function registerApiModules() {
456
		$this->mwGlobals['wgAPIModules']['geocode'] = Geocode::class;
457
	}
458
459
}
460