Completed
Pull Request — master (#130)
by None
07:05
created

MapsHooks::processLayersStoreCandidate()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 16
rs 9.4285
cc 3
eloc 6
nc 3
nop 2
1
<?php
2
3
/**
4
 * Static class for hooks handled by the Maps extension.
5
 *
6
 * @since 0.7
7
 *
8
 * @licence GNU GPL v2+
9
 * @author Jeroen De Dauw < [email protected] >
10
 * @author Daniel Werner
11
 */
12
final class MapsHooks {
13
	/**
14
	 * Helper flag indicating whether the page has been purged.
15
	 * @var bool
16
	 *
17
	 * TODO: Figure out a better way to do this, not requiring this flag and make sure it works with
18
	 *       later MW versions (purging mechanism got changed somewhat around 1.18).
19
	 */
20
	static $purgedBeforeStore = false;
21
22
	public static function onExtensionCallback() {
23
		global $egMapsNamespaceIndex, $egMapsStyleVersion, $wgStyleVersion;
24
25
		// Only initialize the extension when all dependencies are present.
26
		if ( !defined( 'Validator_VERSION' ) ) {
27
			throw new Exception( 'You need to have Validator installed in order to use Maps' );
28
		}
29
30
		if ( defined( 'Maps_VERSION' ) ) {
31
			// Do not initialize more than once.
32
			return 1;
33
		}
34
35
		define( 'Maps_VERSION' , '3.2 alpha' );
36
37
		$egMapsStyleVersion = $wgStyleVersion . '-' . Maps_VERSION;
38
39
		define( 'Maps_COORDS_FLOAT' , 'float' );
40
		define( 'Maps_COORDS_DMS' , 'dms' );
41
		define( 'Maps_COORDS_DM' , 'dm' );
42
		define( 'Maps_COORDS_DD' , 'dd' );
43
44
		require_once __DIR__ . '/Maps_Settings.php';
45
46
		define( 'Maps_NS_LAYER' , $egMapsNamespaceIndex + 0 );
47
		define( 'Maps_NS_LAYER_TALK' , $egMapsNamespaceIndex + 1 );
48
	}
49
50
	public static function onExtensionFunction() {
0 ignored issues
show
Coding Style introduced by
onExtensionFunction uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
51
		Hooks::run( 'MappingServiceLoad' );
52
		Hooks::run( 'MappingFeatureLoad' );
53
54
		if ( in_array( 'googlemaps3', $GLOBALS['egMapsAvailableServices'] ) ) {
55
			global $wgSpecialPages, $wgSpecialPageGroups;
56
57
			$wgSpecialPages['MapEditor'] = 'SpecialMapEditor';
58
			$wgSpecialPageGroups['MapEditor'] = 'maps';
59
		}
60
61
		return true;
62
	}
63
64
	public static function onParserFirstCallInit1( Parser &$parser ) {
65
		$instance = new MapsCoordinates();
66
		return $instance->init( $parser );
67
	}
68
69
	public static function onParserFirstCallInit2( Parser &$parser ) {
70
		$instance = new MapsDisplayMap();
71
		return $instance->init( $parser );
72
	}
73
74
	public static function onParserFirstCallInit3( Parser &$parser ) {
75
		$instance = new MapsDistance();
76
		return $instance->init( $parser );
77
	}
78
79
	public static function onParserFirstCallInit4( Parser &$parser ) {
80
		$instance = new MapsFinddestination();
81
		return $instance->init( $parser );
82
	}
83
84
	public static function onParserFirstCallInit5( Parser &$parser ) {
85
		$instance = new MapsGeocode();
86
		return $instance->init( $parser );
87
	}
88
89
	public static function onParserFirstCallInit6( Parser &$parser ) {
90
		$instance = new MapsGeodistance();
91
		return $instance->init( $parser );
92
	}
93
94
	public static function onParserFirstCallInit7( Parser &$parser ) {
95
		$instance = new MapsMapsDoc();
96
		return $instance->init( $parser );
97
	}
98
99
	public static function onParserFirstCallInit8( Parser &$parser ) {
100
		$instance = new MapsLayerDefinition();
101
		return $instance->init( $parser );
102
	}
103
104
	/**
105
	 * Initialization function for the Google Maps v3 service. 
106
	 * 
107
	 * @since 0.6.3
108
	 * @ingroup MapsGoogleMaps3
109
	 * 
110
	 * @return boolean true
111
	 */
112
	public static function efMapsInitGoogleMaps3() {
113
		global $wgAutoloadClasses;
114
115
		$wgAutoloadClasses['MapsGoogleMaps3'] = __DIR__ . '/includes/services/GoogleMaps3/Maps_GoogleMaps3.php';
116
117
		MapsMappingServices::registerService( 'googlemaps3', 'MapsGoogleMaps3' );
118
119
		// TODO: kill below code
120
		$googleMaps = MapsMappingServices::getServiceInstance( 'googlemaps3' );
121
		$googleMaps->addFeature( 'display_map', 'MapsDisplayMapRenderer' );
122
123
		return true;
124
	}
125
126
	public static function efMapsInitOpenLayers() {
127
		MapsMappingServices::registerService( 
128
			'openlayers',
129
			'MapsOpenLayers',
130
			array( 'display_map' => 'MapsDisplayMapRenderer' )
131
		);
132
		
133
		return true;
134
	}
135
136
	/**
137
	 * Initialization function for the Leaflet service.
138
	 *
139
	 * @ingroup Leaflet
140
	 *
141
	 * @return boolean true
142
	 */
143
	public static function efMapsInitLeaflet() {
144
		global $wgAutoloadClasses;
145
146
		$wgAutoloadClasses['MapsLeaflet'] = __DIR__ . '/Maps_Leaflet.php';
147
148
		MapsMappingServices::registerService( 'leaflet', 'MapsLeaflet' );
149
		$leafletMaps = MapsMappingServices::getServiceInstance( 'leaflet' );
150
		$leafletMaps->addFeature( 'display_map', 'MapsDisplayMapRenderer' );
151
152
		return true;
153
	}
154
155
	/**
156
	 * Adds a link to Admin Links page.
157
	 *
158
	 * @since 0.7
159
	 *
160
	 * @param ALTree $admin_links_tree
161
	 *
162
	 * @return boolean
163
	 */
164
	public static function addToAdminLinks( ALTree &$admin_links_tree ) {
165
		$displaying_data_section = $admin_links_tree->getSection( wfMessage( 'smw_adminlinks_displayingdata' )->text() );
166
167
		// Escape if SMW hasn't added links.
168
		if ( is_null( $displaying_data_section ) ) {
169
			return true;
170
		}
171
172
		$smw_docu_row = $displaying_data_section->getRow( 'smw' );
173
174
		$maps_docu_label = wfMessage( 'adminlinks_documentation', 'Maps' )->text();
175
		$smw_docu_row->addItem( AlItem::newFromExternalLink( 'https://semantic-mediawiki.org/wiki/Maps', $maps_docu_label ) );
176
177
		return true;
178
	}
179
180
	/**
181
	 * Intercept pages in the Layer namespace to handle them correctly.
182
	 *
183
	 * @param $title: Title
184
	 * @param $article: Article or null
185
	 *
186
	 * @return boolean
187
	 */
188
	public static function onArticleFromTitle( Title &$title, /* Article */ &$article ) {
189
		if ( $title->getNamespace() == Maps_NS_LAYER ) {
190
			$article = new MapsLayerPage( $title );
191
		}
192
193
		return true;
194
	}
195
196
	/**
197
	 * Adds global JavaScript variables.
198
	 *
199
	 * @since 1.0
200
         * @see http://www.mediawiki.org/wiki/Manual:Hooks/MakeGlobalVariablesScript
201
         * @param array &$vars Variables to be added into the output
202
         * @param OutputPage $outputPage OutputPage instance calling the hook
203
         * @return boolean true in all cases
204
	 */
205
	public static function onMakeGlobalVariablesScript( array &$vars, OutputPage $outputPage ) {
0 ignored issues
show
Unused Code introduced by
The parameter $outputPage is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
onMakeGlobalVariablesScript uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
206
		global $egMapsGlobalJSVars;
207
208
		$vars['egMapsDebugJS'] = $GLOBALS['egMapsDebugJS'];
209
                $vars[ 'egMapsAvailableServices' ] = $GLOBALS['egMapsAvailableServices'];
210
211
		$vars += $egMapsGlobalJSVars;
212
213
		return true;
214
	}
215
216
	/**
217
	 * @since 0.7
218
	 *
219
	 * @param array $list
220
	 *
221
	 * @return boolean
222
	 */
223
	public static function onCanonicalNamespaces( array &$list ) {
224
		$list[Maps_NS_LAYER] = 'Layer';
225
		$list[Maps_NS_LAYER_TALK] = 'Layer_talk';
226
		return true;
227
	}
228
229
	/**
230
	 * This will setup database tables for layer functionality.
231
	 *
232
	 * @since 3.0
233
	 *
234
	 * @param DatabaseUpdater $updater
235
	 *
236
	 * @return true 
237
	 */
238
	public static function onLoadExtensionSchemaUpdates( DatabaseUpdater $updater ) {
0 ignored issues
show
Coding Style introduced by
onLoadExtensionSchemaUpdates uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
239
		switch( $GLOBALS['wgDBtype'] ) {
240
			case 'mysql':
241
			case 'sqlite':
242
				$updater->addExtensionTable( 'maps_layers', __DIR__ . '/schema/MapsLayers.sql' );
243
				break;
244
			case 'postgres':
245
				$updater->addExtensionTable( 'maps_layers', __DIR__ . '/schema/MapsLayers-postgres.sql' );
246
				break;
247
		}
248
249
		return true;
250
	}
251
252
	/**
253
	 * Make sure layer data will be stored into database when purging the page
254
	 *
255
	 * @since 3.0
256
	 *
257
	 * @param $article WikiPage|Article (depending on MW version, WikiPage in 1.18+)
258
	 * @return type
259
	 */
260
	public static function onArticlePurge( &$article ) {
0 ignored issues
show
Unused Code introduced by
The parameter $article is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
261
		self::$purgedBeforeStore = true;
262
		return true;
263
	}
264
265
	/**
266
	 * At the end of article parsing, in case of layer page, save layers to database
267
	 *
268
	 * @since 3.0
269
	 *
270
	 * @param Parser &$parser
271
	 * @param string &$text
272
	 *
273
	 * @return true
274
	 */
275
	public static function onParserAfterTidy( Parser &$parser, &$text ) {
0 ignored issues
show
Unused Code introduced by
The parameter $text is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
276
277
		$title = $parser->getTitle();
278
279
		if( $title === null
280
			|| self::$purgedBeforeStore !== true
281
		) {
282
			// just preprocessing some stuff or no purge
283
			return true;
284
		}
285
286
		self::processLayersStoreCandidate( $parser->getOutput(), $title );
287
288
		// Set helper to false immediately so we won't run into job-processing weirdness:
289
		self::$purgedBeforeStore = false;
290
291
		return true;
292
	}
293
294
	/**
295
	 * After article was edited and parsed, in case of layer page, save layers to database
296
	 *
297
	 * @since 3.0
298
	 *
299
	 * @param LinksUpdate &$linksUpdate
300
	 *
301
	 * @return true
302
	 */
303
	public static function onLinksUpdateConstructed( LinksUpdate &$linksUpdate ) {
304
		$title = $linksUpdate->getTitle();
305
306
		self::processLayersStoreCandidate( $linksUpdate->mParserOutput, $title );
307
308
		return true;
309
	}
310
311
	/**
312
	 * Checks whether the parser output has some layer data which should be stored of the
313
	 * given title and performs the task.
314
	 *
315
	 * @since 3.0
316
	 *
317
	 * @param ParserOutput $parserOutput
318
	 * @param Title $title 
319
	 */
320
	protected static function processLayersStoreCandidate( ParserOutput $parserOutput, Title $title ) {
321
		
322
		// if site which is being parsed is in maps namespace:
323
		if( $title->getNamespace() === Maps_NS_LAYER ) {
324
325
			if( ! isset( $parserOutput->mExtMapsLayers ) ) {
326
				$parserOutput->mExtMapsLayers = new MapsLayerGroup();
327
			}
328
329
			// get MapsLayerGroup object with layers to be stored:
330
			$mapsForStore = $parserOutput->mExtMapsLayers;
331
332
			// store layers in database (also deletes previous definitions still in db):
333
			MapsLayers::storeLayers( $mapsForStore, $title );
334
		}
335
	}
336
337
	/**
338
	 * If a new parser process is getting started, clear collected layer data of the
339
	 * previous one.
340
	 *
341
	 * @since 3.0
342
	 *
343
	 * @param Parser $parser
344
	 *
345
	 * @return true
346
	 */
347
	public static function onParserClearState( Parser &$parser ) {
348
		$parser->getOutput()->mExtMapsLayers = null;
349
		return true;
350
	}
351
}
352
353