Completed
Push — master ( a742ac...72f78c )
by Jeroen De
14s queued 10s
created

DisplayMapRenderer::getLayerDependencies()   B

Complexity

Conditions 7
Paths 2

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 7.0178

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 13
cts 14
cp 0.9286
rs 8.6506
c 0
b 0
f 0
cc 7
nc 2
nop 2
crap 7.0178
1
<?php
2
3
namespace Maps\MediaWiki\ParserHooks;
4
5
use FormatJson;
6
use Html;
7
use Maps\DataAccess\MediaWikiFileUrlFinder;
8
use Maps\Elements\Location;
9
use Maps\MappingService;
10
use Maps\Presentation\ElementJsonSerializer;
11
use Maps\Presentation\WikitextParser;
12
use Maps\Presentation\WikitextParsers\LocationParser;
13
use Parser;
14
15
/**
16
 * Class handling the #display_map rendering.
17
 *
18
 * @licence GNU GPL v2+
19
 * @author Jeroen De Dauw < [email protected] >
20
 * @author Kim Eik
21
 */
22
class DisplayMapRenderer {
23
24
	public $service;
25
26
	/**
27
	 * @var LocationParser
28
	 */
29
	private $locationParser;
30
31
	/**
32
	 * @var MediaWikiFileUrlFinder
33
	 */
34
	private $fileUrlFinder;
35
36
	/**
37
	 * @var WikitextParser
38
	 */
39
	private $wikitextParser;
40
	/**
41
	 * @var ElementJsonSerializer
42
	 */
43
	private $elementSerializer;
44
45 20
	public function __construct( MappingService $service = null ) {
46 20
		$this->service = $service;
47 20
	}
48
49
	/**
50
	 * Handles the request from the parser hook by doing the work that's common for all
51
	 * mapping services, calling the specific methods and finally returning the resulting output.
52
	 *
53
	 * @param array $params
54
	 * @param Parser $parser
55
	 *
56
	 * @return string
57
	 */
58 20
	public final function renderMap( array $params, Parser $parser ) {
59 20
		$factory = \Maps\MapsFactory::newDefault();
60
61 20
		$this->locationParser = $factory->newLocationParser();
62 20
		$this->fileUrlFinder = $factory->getFileUrlFinder();
63
64 20
		$this->wikitextParser = new WikitextParser( clone $parser );
65 20
		$this->elementSerializer = new ElementJsonSerializer( $this->wikitextParser );
66
67 20
		$this->handleMarkerData( $params );
68
69 20
		$output = $this->getMapHTML(
70 20
			$params,
71 20
			$this->service->getMapId()
72
		);
73
74 20
		$this->service->addHtmlDependencies(
75 20
			self::getLayerDependencies( $params['mappingservice'], $params )
76
		);
77
78 20
		$this->service->addDependencies( $parser->getOutput() );
79
80 20
		return $output;
81
	}
82
83
	/**
84
	 * Converts the data in the coordinates parameter to JSON-ready objects.
85
	 * These get stored in the locations parameter, and the coordinates on gets deleted.
86
	 */
87 20
	private function handleMarkerData( array &$params ) {
88 20
		$params['centre'] = $this->getCenter( $params['centre'] );
89
90 20
		if ( is_object( $params['wmsoverlay'] ) ) {
91
			$params['wmsoverlay'] = $params['wmsoverlay']->getJSONObject();
92
		}
93
94 20
		$params['locations'] = $this->getLocationJson( $params );
95
96 20
		unset( $params['coordinates'] );
97
98 20
		$this->handleShapeData( $params );
99 20
	}
100
101 20
	private function getCenter( $coordinatesOrAddress ) {
102 20
		if ( $coordinatesOrAddress === false ) {
103 20
			return false;
104
		}
105
106
		try {
107
			// FIXME: a Location makes no sense here, since the non-coordinate data is not used
108
			$location = $this->locationParser->parse( $coordinatesOrAddress );
109
		}
110
		catch ( \Exception $ex ) {
111
			// TODO: somehow report this to the user
112
			return false;
113
		}
114
115
		return $location->getJSONObject();
116
	}
117
118 20
	private function getLocationJson( array $params ) {
119 20
		$iconUrl = $this->fileUrlFinder->getUrlForFileName( $params['icon'] );
120 20
		$visitedIconUrl = $this->fileUrlFinder->getUrlForFileName( $params['visitedicon'] );
121
122 20
		$locationJsonObjects = [];
123
124 20
		foreach ( $params['coordinates'] as $coordinatesOrAddress ) {
125
			try {
126 15
				$location = $this->locationParser->parse( $coordinatesOrAddress );
127
			}
128 1
			catch ( \Exception $ex ) {
129
				// TODO: somehow report this to the user
130 1
				continue;
131
			}
132
133 14
			$locationJsonObjects[] = $this->getLocationJsonObject(
134 14
				$location,
135 14
				$params,
136 14
				$iconUrl,
137 14
				$visitedIconUrl
138
			);
139
		}
140
141 20
		return $locationJsonObjects;
142
	}
143
144 14
	private function getLocationJsonObject( Location $location, array $params, $iconUrl, $visitedIconUrl ) {
145 14
		$jsonObj = $location->getJSONObject( $params['title'], $params['label'], $iconUrl, '', '', $visitedIconUrl );
146
147 14
		$this->elementSerializer->titleAndText( $jsonObj );
148
149 14
		if ( isset( $jsonObj['inlineLabel'] ) ) {
150 1
			$jsonObj['inlineLabel'] = strip_tags(
151 1
				$this->wikitextParser->wikitextToHtml( $jsonObj['inlineLabel'] ),
152 1
				'<a><img>'
153
			);
154
		}
155
156 14
		return $jsonObj;
157
	}
158
159 20
	private function handleShapeData( array &$params ) {
160
		$textContainers = [
161 20
			&$params['lines'],
162 20
			&$params['polygons'],
163 20
			&$params['circles'],
164 20
			&$params['rectangles'],
165 20
			&$params['imageoverlays'], // FIXME: this is Google Maps specific!!
166
		];
167
168 20
		foreach ( $textContainers as &$textContainer ) {
169 20
			if ( is_array( $textContainer ) ) {
170 20
				foreach ( $textContainer as &$obj ) {
171 20
					$obj = $this->elementSerializer->elementToJson( $obj );
172
				}
173
			}
174
		}
175 20
	}
176
177
	/**
178
	 * Returns the HTML to display the map.
179
	 *
180
	 * @param array $params
181
	 * @param string $mapName
182
	 *
183
	 * @return string
184
	 */
185 20
	protected function getMapHTML( array $params, $mapName ) {
186 20
		return Html::rawElement(
187 20
			'div',
188
			[
189 20
				'id' => $mapName,
190 20
				'style' => "width: {$params['width']}; height: {$params['height']}; background-color: #cccccc; overflow: hidden;",
191 20
				'class' => 'maps-map maps-' . $this->service->getName()
192
			],
193 20
			wfMessage( 'maps-loading-map' )->inContentLanguage()->escaped() .
194 20
			Html::element(
195 20
				'div',
196 20
				[ 'style' => 'display:none', 'class' => 'mapdata' ],
197 20
				FormatJson::encode( $params )
198
			)
199
		);
200
	}
201
202 20
	public static function getLayerDependencies( $service, $params ) {
203 20
		global $egMapsLeafletLayerDependencies, $egMapsLeafletAvailableLayers,
204 20
			   $egMapsLeafletLayersApiKeys;
205
206 20
		$layerDependencies = [];
207
208 20
		if ( $service === 'leaflet' ) {
209 13
			$layerNames = $params['layers'];
210 13
			foreach ( $layerNames as $layerName ) {
211 13
				if ( array_key_exists( $layerName, $egMapsLeafletAvailableLayers )
212 13
					&& $egMapsLeafletAvailableLayers[$layerName]
213 13
					&& array_key_exists( $layerName, $egMapsLeafletLayersApiKeys )
214 13
					&& array_key_exists( $layerName, $egMapsLeafletLayerDependencies ) ) {
215
					$layerDependencies[] = '<script src="' . $egMapsLeafletLayerDependencies[$layerName] .
216 13
						$egMapsLeafletLayersApiKeys[$layerName] . '"></script>';
217
				}
218
			}
219
		}
220
221 20
		return array_unique( $layerDependencies );
222
	}
223
224
}
225