summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/DisplayMapFunction.php
blob: bad0d842f16811f82205a71fb56f5da180e86929 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php

namespace Maps\MediaWiki\ParserHooks;

use Maps;
use Maps\MapsFunctions;
use Maps\MappingServices;
use Maps\Presentation\ParameterExtractor;
use MWException;
use ParamProcessor;
use ParamProcessor\ProcessedParam;
use Parser;

/**
 * Class for the 'display_map' parser hooks.
 *
 * @licence GNU GPL v2+
 * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 */
class DisplayMapFunction {

	private $services;

	private $renderer;

	public function __construct( MappingServices $services ) {
		$this->services = $services;

		$this->renderer = new DisplayMapRenderer();
	}

	/**
	 * @param Parser $parser
	 * @param string[] $parameters Values of the array can be named parameters ("key=value") or unnamed.
	 * They are not normalized, so can be "key =  value "
	 *
	 * @return string
	 * @throws MWException
	 */
	public function getMapHtmlForKeyValueStrings( Parser $parser, array $parameters ): string {
		$processor = new \ParamProcessor\Processor( new \ParamProcessor\Options() );

		$service = $this->services->getServiceOrDefault(
			$this->extractServiceName(
				Maps\Presentation\ParameterExtractor::extractFromKeyValueStrings( $parameters )
			)
		);

		$this->renderer->service = $service;

		$processor->setFunctionParams(
			$parameters,
			array_merge(
				self::getHookDefinition( ';' )->getParameters(),
				$service->getParameterInfo()
			),
			self::getHookDefinition( ';' )->getDefaultParameters()
		);

		return $this->getMapHtmlFromProcessor( $parser, $processor );
	}

	/**
	 * @param Parser $parser
	 * @param string[] $parameters Key value list of parameters. Unnamed parameters have numeric keys.
	 * Both keys and values have not been normalized.
	 *
	 * @return string
	 * @throws MWException
	 */
	public function getMapHtmlForParameterList( Parser $parser, array $parameters ) {
		$processor = new \ParamProcessor\Processor( new \ParamProcessor\Options() );

		$service = $this->services->getServiceOrDefault( $this->extractServiceName( $parameters ) );

		$this->renderer->service = $service;

		$processor->setParameters(
			$parameters,
			array_merge(
				self::getHookDefinition( "\n" )->getParameters(),
				$service->getParameterInfo()
			)
		);

		return $this->getMapHtmlFromProcessor( $parser, $processor );
	}

	private function getMapHtmlFromProcessor( Parser $parser, ParamProcessor\Processor $processor ) {
		$params = $processor->processParameters()->getParameters();

		$this->defaultMapZoom( $params );

		$this->trackMap( $parser );

		return $this->renderer->renderMap(
			$this->processedParametersToKeyValueArray( $params ),
			$parser
		);
	}

	private function extractServiceName( array $parameters ): string {
		$service = ( new ParameterExtractor() )->extract(
			[ 'mappingservice', 'service' ],
			$parameters
		);

		return $service ?? '';
	}

	private function processedParametersToKeyValueArray( array $params ): array {
		$parameters = [];

		foreach ( $params as $parameter ) {
			$parameters[$parameter->getName()] = $parameter->getValue();
		}

		return $parameters;
	}

	public static function getHookDefinition( string $locationDelimiter ): \ParserHooks\HookDefinition {
		return new \ParserHooks\HookDefinition(
			[ 'display_map', 'display_point', 'display_points', 'display_line' ],
			self::getParameterDefinitions( $locationDelimiter ),
			[ 'coordinates' ]
		);
	}

	private static function getParameterDefinitions( $locationDelimiter ): array {
		$params = MapsFunctions::getCommonParameters();

		$params['coordinates'] = [
			'type' => 'string',
			'aliases' => [ 'coords', 'location', 'address', 'addresses', 'locations', 'points' ],
			'default' => [],
			'islist' => true,
			'delimiter' => $locationDelimiter,
			'message' => 'maps-displaymap-par-coordinates',
		];

		return $params;
	}

	/**
	 * @param ProcessedParam[] $parameters
	 */
	private function defaultMapZoom( array &$parameters ) {
		if ( array_key_exists( 'zoom', $parameters ) && $parameters['zoom']->wasSetToDefault() && count(
				$parameters['coordinates']->getValue()
			) > 1 ) {
			$parameters['zoom'] = $this->getParameterWithValue( $parameters['zoom'], false );
		}
	}

	private function getParameterWithValue( ProcessedParam $param, $value ) {
		return new ProcessedParam(
			$param->getName(),
			$value,
			$param->wasSetToDefault(),
			$param->getOriginalName(),
			$param->getOriginalValue()
		);
	}

	private function trackMap( Parser $parser ) {
		if ( $GLOBALS['egMapsEnableCategory'] ) {
			$parser->addTrackingCategory( 'maps-tracking-category' );
		}
	}

}