These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | use Maps\Element; |
||
3 | use Maps\Elements\Line; |
||
4 | use Maps\Elements\Location; |
||
5 | |||
6 | /** |
||
7 | * Class handling the #display_map rendering. |
||
8 | * |
||
9 | * @licence GNU GPL v2+ |
||
10 | * @author Jeroen De Dauw < [email protected] > |
||
11 | * @author Kim Eik |
||
12 | */ |
||
13 | class MapsDisplayMapRenderer { |
||
14 | |||
15 | /** |
||
16 | * @since 2.0 |
||
17 | * |
||
18 | * @var iMappingService |
||
19 | */ |
||
20 | protected $service; |
||
21 | |||
22 | /** |
||
23 | * Constructor. |
||
24 | * |
||
25 | * @param iMappingService $service |
||
26 | */ |
||
27 | public function __construct( iMappingService $service ) { |
||
28 | $this->service = $service; |
||
29 | } |
||
30 | |||
31 | /** |
||
32 | * Returns the HTML to display the map. |
||
33 | * |
||
34 | * @since 2.0 |
||
35 | * |
||
36 | * @param array $params |
||
37 | * @param Parser $parser |
||
38 | * @param string $mapName |
||
39 | * |
||
40 | * @return string |
||
41 | */ |
||
42 | protected function getMapHTML( array $params, Parser $parser, $mapName ) { |
||
43 | return Html::rawElement( |
||
44 | 'div', |
||
45 | [ |
||
46 | 'id' => $mapName, |
||
47 | 'style' => "width: {$params['width']}; height: {$params['height']}; background-color: #cccccc; overflow: hidden;", |
||
48 | 'class' => 'maps-map maps-' . $this->service->getName() |
||
49 | ], |
||
50 | wfMessage( 'maps-loading-map' )->inContentLanguage()->escaped() . |
||
51 | Html::element( |
||
52 | 'div', |
||
53 | [ 'style' => 'display:none', 'class' => 'mapdata' ], |
||
54 | FormatJson::encode( $this->getJSONObject( $params, $parser ) ) |
||
55 | ) |
||
56 | ); |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * Returns a PHP object to encode to JSON with the map data. |
||
61 | * |
||
62 | * @since 2.0 |
||
63 | * |
||
64 | * @param array $params |
||
65 | * @param Parser $parser |
||
66 | * |
||
67 | * @return mixed |
||
68 | */ |
||
69 | protected function getJSONObject( array $params, Parser $parser ) { |
||
70 | return $params; |
||
71 | } |
||
72 | |||
73 | /** |
||
74 | * Handles the request from the parser hook by doing the work that's common for all |
||
75 | * mapping services, calling the specific methods and finally returning the resulting output. |
||
76 | * |
||
77 | * @param array $params |
||
78 | * @param Parser $parser |
||
79 | * |
||
80 | * @return string |
||
81 | */ |
||
82 | public final function renderMap( array $params, Parser $parser ) { |
||
83 | $this->handleMarkerData( $params, $parser ); |
||
84 | |||
85 | $mapName = $this->service->getMapId(); |
||
86 | |||
87 | $output = $this->getMapHTML( $params, $parser, $mapName ); |
||
88 | |||
89 | $configVars = Skin::makeVariablesScript( $this->service->getConfigVariables() ); |
||
90 | |||
91 | $this->service->addDependencies( $parser ); |
||
92 | $parser->getOutput()->addHeadItem( $configVars ); |
||
93 | |||
94 | return $output; |
||
95 | } |
||
96 | |||
97 | /** |
||
98 | * Converts the data in the coordinates parameter to JSON-ready objects. |
||
99 | * These get stored in the locations parameter, and the coordinates on gets deleted. |
||
100 | * |
||
101 | * FIXME: complexity |
||
102 | * |
||
103 | * @since 1.0 |
||
104 | * |
||
105 | * @param array &$params |
||
106 | * @param Parser $parser |
||
107 | */ |
||
108 | protected function handleMarkerData( array &$params, Parser $parser ) { |
||
109 | if ( is_object( $params['centre'] ) ) { |
||
110 | $params['centre'] = $params['centre']->getJSONObject(); |
||
111 | } |
||
112 | |||
113 | $parserClone = clone $parser; |
||
114 | |||
115 | if ( is_object( $params['wmsoverlay'] ) ) { |
||
116 | $params['wmsoverlay'] = $params['wmsoverlay']->getJSONObject(); |
||
117 | } |
||
118 | |||
119 | $iconUrl = MapsMapper::getFileUrl( $params['icon'] ); |
||
120 | $visitedIconUrl = MapsMapper::getFileUrl( $params['visitedicon'] ); |
||
121 | $params['locations'] = []; |
||
122 | |||
123 | /** |
||
124 | * @var Location $location |
||
125 | */ |
||
126 | foreach ( $params['coordinates'] as $location ) { |
||
127 | $jsonObj = $location->getJSONObject( $params['title'], $params['label'], $iconUrl, '', '',$visitedIconUrl); |
||
128 | |||
129 | $jsonObj['title'] = $parserClone->parse( $jsonObj['title'], $parserClone->getTitle(), new ParserOptions() )->getText(); |
||
130 | $jsonObj['text'] = $parserClone->parse( $jsonObj['text'], $parserClone->getTitle(), new ParserOptions() )->getText(); |
||
131 | if ( isset( $jsonObj['inlineLabel'] ) ) { |
||
132 | $jsonObj['inlineLabel'] = strip_tags($parserClone->parse( $jsonObj['inlineLabel'], $parserClone->getTitle(), new ParserOptions() )->getText(),'<a><img>'); |
||
133 | } |
||
134 | |||
135 | $hasTitleAndtext = $jsonObj['title'] !== '' && $jsonObj['text'] !== ''; |
||
136 | $jsonObj['text'] = ( $hasTitleAndtext ? '<b>' . $jsonObj['title'] . '</b><hr />' : $jsonObj['title'] ) . $jsonObj['text']; |
||
137 | $jsonObj['title'] = strip_tags( $jsonObj['title'] ); |
||
138 | |||
139 | $params['locations'][] = $jsonObj; |
||
140 | } |
||
141 | |||
142 | unset( $params['coordinates'] ); |
||
143 | |||
144 | $this->handleShapeData( $params, $parserClone ); |
||
145 | |||
146 | if ( $params['mappingservice'] === 'openlayers' ) { |
||
147 | $params['layers'] = self::evilOpenLayersHack( $params['layers'] ); |
||
148 | } |
||
149 | } |
||
150 | |||
151 | protected function handleShapeData( array &$params, Parser $parserClone ) { |
||
152 | $textContainers = [ |
||
153 | &$params['lines'] , |
||
154 | &$params['polygons'] , |
||
155 | &$params['circles'] , |
||
156 | &$params['rectangles'], |
||
157 | &$params['imageoverlays'], // FIXME: this is Google Maps specific!! |
||
158 | ]; |
||
159 | |||
160 | foreach ( $textContainers as &$textContainer ) { |
||
161 | if ( is_array( $textContainer ) ) { |
||
162 | foreach ( $textContainer as &$obj ) { |
||
163 | if ( $obj instanceof Element ) { |
||
164 | $obj = $obj->getArrayValue(); |
||
165 | } |
||
166 | |||
167 | $obj['title'] = $parserClone->parse( $obj['title'] , $parserClone->getTitle() , new ParserOptions() )->getText(); |
||
168 | $obj['text'] = $parserClone->parse( $obj['text'] , $parserClone->getTitle() , new ParserOptions() )->getText(); |
||
169 | |||
170 | $hasTitleAndtext = $obj['title'] !== '' && $obj['text'] !== ''; |
||
171 | $obj['text'] = ( $hasTitleAndtext ? '<b>' . $obj['title'] . '</b><hr />' : $obj['title'] ) . $obj['text']; |
||
172 | $obj['title'] = strip_tags( $obj['title'] ); |
||
173 | } |
||
174 | } |
||
175 | } |
||
176 | } |
||
177 | |||
178 | /** |
||
179 | * FIXME |
||
180 | * |
||
181 | * Temporary hack until the mapping service handling gets a proper refactor |
||
182 | * This kind of JS construction is also rather evil and should not be done at this point |
||
183 | * |
||
184 | * @since 3.0 |
||
185 | * @deprecated |
||
186 | * |
||
187 | * @param string[] $layers |
||
188 | * |
||
189 | * @return string[] |
||
190 | */ |
||
191 | public static function evilOpenLayersHack( $layers ) { |
||
192 | global $egMapsOLLayerGroups, $egMapsOLAvailableLayers; |
||
193 | |||
194 | $layerDefs = []; |
||
195 | $layerNames = []; |
||
196 | |||
197 | foreach ( $layers as $layerOrGroup ) { |
||
198 | $lcLayerOrGroup = strtolower( $layerOrGroup ); |
||
199 | |||
200 | // Layer groups. Loop over all items and add them if not present yet: |
||
201 | if ( array_key_exists( $lcLayerOrGroup, $egMapsOLLayerGroups ) ) { |
||
202 | foreach ( $egMapsOLLayerGroups[$lcLayerOrGroup] as $layerName ) { |
||
203 | if ( !in_array( $layerName, $layerNames ) ) { |
||
204 | if ( is_array( $egMapsOLAvailableLayers[$layerName] ) ) { |
||
205 | $layerDefs[] = 'new ' . $egMapsOLAvailableLayers[$layerName][0]; |
||
206 | } |
||
207 | else { |
||
208 | $layerDefs[] = 'new ' . $egMapsOLAvailableLayers[$layerName]; |
||
209 | } |
||
210 | $layerNames[] = $layerName; |
||
211 | } |
||
212 | } |
||
213 | } |
||
214 | // Single layers. Add them if not present yet: |
||
215 | elseif ( array_key_exists( $lcLayerOrGroup, $egMapsOLAvailableLayers ) ) { |
||
216 | if ( !in_array( $lcLayerOrGroup, $layerNames ) ) { |
||
217 | if ( is_array( $egMapsOLAvailableLayers[$lcLayerOrGroup] ) ) { |
||
218 | $layerDefs[] = 'new ' . $egMapsOLAvailableLayers[$lcLayerOrGroup][0]; |
||
219 | } |
||
220 | else { |
||
221 | $layerDefs[] = 'new ' . $egMapsOLAvailableLayers[$lcLayerOrGroup]; |
||
222 | } |
||
223 | |||
224 | $layerNames[] = $lcLayerOrGroup; |
||
225 | } |
||
226 | } |
||
227 | } |
||
228 | |||
229 | MapsMappingServices::getServiceInstance( 'openlayers' )->addLayerDependencies( self::getLayerDependencies( $layerNames ) ); |
||
0 ignored issues
–
show
|
|||
230 | |||
231 | return $layerDefs; |
||
232 | } |
||
233 | |||
234 | /** |
||
235 | * FIXME |
||
236 | * @see evilOpenLayersHack |
||
237 | */ |
||
238 | private static function getLayerDependencies( array $layerNames ) { |
||
239 | global $egMapsOLLayerDependencies, $egMapsOLAvailableLayers; |
||
240 | |||
241 | $layerDependencies = []; |
||
242 | |||
243 | foreach ( $layerNames as $layerName ) { |
||
244 | if ( array_key_exists( $layerName, $egMapsOLAvailableLayers ) // The layer must be defined in php |
||
245 | && is_array( $egMapsOLAvailableLayers[$layerName] ) // The layer must be an array... |
||
246 | && count( $egMapsOLAvailableLayers[$layerName] ) > 1 // ...with a second element... |
||
247 | && array_key_exists( $egMapsOLAvailableLayers[$layerName][1], $egMapsOLLayerDependencies ) ) { //...that is a dependency. |
||
248 | $layerDependencies[] = $egMapsOLLayerDependencies[$egMapsOLAvailableLayers[$layerName][1]]; |
||
249 | } |
||
250 | } |
||
251 | |||
252 | return array_unique( $layerDependencies ); |
||
253 | } |
||
254 | |||
255 | } |
||
256 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the interface: