Completed
Push — master ( 7034c7...e9a56b )
by Jeroen De
03:10
created

DisplayMapRenderer::getLayerDependencies()   B

Complexity

Conditions 7
Paths 2

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 7.1429

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 12
cts 14
cp 0.8571
rs 8.6506
c 0
b 0
f 0
cc 7
nc 2
nop 2
crap 7.1429
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
		$dependencies = $this->service->getDependencyHtml( $params );
75
76
		// Only add a head item when there are dependencies.
77 20
		if ( $dependencies ) {
78 2
			$parser->getOutput()->addHeadItem( $dependencies );
79
		}
80
81 20
		$parser->getOutput()->addModules( $this->service->getResourceModules() );
82
83 20
		return $output;
84
	}
85
86
	/**
87
	 * Converts the data in the coordinates parameter to JSON-ready objects.
88
	 * These get stored in the locations parameter, and the coordinates on gets deleted.
89
	 */
90 20
	private function handleMarkerData( array &$params ) {
91 20
		$params['centre'] = $this->getCenter( $params['centre'] );
92
93 20
		if ( is_object( $params['wmsoverlay'] ) ) {
94
			$params['wmsoverlay'] = $params['wmsoverlay']->getJSONObject();
95
		}
96
97 20
		$params['locations'] = $this->getLocationJson( $params );
98
99 20
		unset( $params['coordinates'] );
100
101 20
		$this->handleShapeData( $params );
102 20
	}
103
104 20
	private function getCenter( $coordinatesOrAddress ) {
105 20
		if ( $coordinatesOrAddress === false ) {
106 20
			return false;
107
		}
108
109
		try {
110
			// FIXME: a Location makes no sense here, since the non-coordinate data is not used
111
			$location = $this->locationParser->parse( $coordinatesOrAddress );
112
		}
113
		catch ( \Exception $ex ) {
114
			// TODO: somehow report this to the user
115
			return false;
116
		}
117
118
		return $location->getJSONObject();
119
	}
120
121 20
	private function getLocationJson( array $params ) {
122 20
		$iconUrl = $this->fileUrlFinder->getUrlForFileName( $params['icon'] );
123 20
		$visitedIconUrl = $this->fileUrlFinder->getUrlForFileName( $params['visitedicon'] );
124
125 20
		$locationJsonObjects = [];
126
127 20
		foreach ( $params['coordinates'] as $coordinatesOrAddress ) {
128
			try {
129 15
				$location = $this->locationParser->parse( $coordinatesOrAddress );
130
			}
131 1
			catch ( \Exception $ex ) {
132
				// TODO: somehow report this to the user
133 1
				continue;
134
			}
135
136 14
			$locationJsonObjects[] = $this->getLocationJsonObject(
137 14
				$location,
138 14
				$params,
139 14
				$iconUrl,
140 14
				$visitedIconUrl
141
			);
142
		}
143
144 20
		return $locationJsonObjects;
145
	}
146
147 14
	private function getLocationJsonObject( Location $location, array $params, $iconUrl, $visitedIconUrl ) {
148 14
		$jsonObj = $location->getJSONObject( $params['title'], $params['label'], $iconUrl, '', '', $visitedIconUrl );
149
150 14
		$this->elementSerializer->titleAndText( $jsonObj );
151
152 14
		if ( isset( $jsonObj['inlineLabel'] ) ) {
153 1
			$jsonObj['inlineLabel'] = strip_tags(
154 1
				$this->wikitextParser->wikitextToHtml( $jsonObj['inlineLabel'] ),
155 1
				'<a><img>'
156
			);
157
		}
158
159 14
		return $jsonObj;
160
	}
161
162 20
	private function handleShapeData( array &$params ) {
163
		$textContainers = [
164 20
			&$params['lines'],
165 20
			&$params['polygons'],
166 20
			&$params['circles'],
167 20
			&$params['rectangles'],
168 20
			&$params['imageoverlays'], // FIXME: this is Google Maps specific!!
169
		];
170
171 20
		foreach ( $textContainers as &$textContainer ) {
172 20
			if ( is_array( $textContainer ) ) {
173 20
				foreach ( $textContainer as &$obj ) {
174 5
					$obj = $this->elementSerializer->elementToJson( $obj );
175
				}
176
			}
177
		}
178 20
	}
179
180
	/**
181
	 * Returns the HTML to display the map.
182
	 *
183
	 * @param array $params
184
	 * @param string $mapName
185
	 *
186
	 * @return string
187
	 */
188 20
	protected function getMapHTML( array $params, $mapName ) {
189 20
		return Html::rawElement(
190 20
			'div',
191
			[
192 20
				'id' => $mapName,
193 20
				'style' => "width: {$params['width']}; height: {$params['height']}; background-color: #cccccc; overflow: hidden;",
194 20
				'class' => 'maps-map maps-' . $this->service->getName()
195
			],
196 20
			wfMessage( 'maps-loading-map' )->inContentLanguage()->escaped() .
197 20
			Html::element(
198 20
				'div',
199 20
				[ 'style' => 'display:none', 'class' => 'mapdata' ],
200 20
				FormatJson::encode( $params )
201
			)
202
		);
203
	}
204
205
}
206