Completed
Branch AUTOMATED_TESTING (fff10f)
by Gordon
11:14
created

MapAPI::setKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
/*
4
*
5
* This script is distributed in the hope that it will be useful,
6
* but WITHOUT ANY WARRANTY; without even the implied warranty of
7
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8
* GNU General public License for more details.
9
*
10
* This copyright notice MUST APPEAR in all copies of the script!
11
*
12
*  @author            CERDAN Yohann <[email protected]>
13
*  @copyright      (c) 2009  CERDAN Yohann, All rights reserved
14
*  @ version         18:13 26/05/2009
15
*/
16
17
class MapAPI extends ViewableData
18
{
19
20
	 /** GoogleMap key **/
21
	protected $googleMapKey = '';
22
23
	/** GoogleMap ID for the HTML DIV  **/
24
	protected $googleMapId = 'googlemapapi';
25
26
	/* Additional CSS classes to use when rendering the map */
27
	protected $set_additional_css_classes = '';
28
29
	/** Width of the gmap **/
30
	protected $width = 800;
31
32
	/** Height of the gmap **/
33
	protected $height = 600;
34
35
	/* array of lines to be drawn on the map */
36
	protected $lines = array();
37
38
	/* kml file to be rendered */
39
	protected $kmlFiles = array();
40
41
	/** Default zoom of the gmap **/
42
	protected $zoom = 9;
43
44
	/** Enable the zoom of the Infowindow **/
45
	protected $enableWindowZoom = false;
46
47
	/** Default zoom of the Infowindow **/
48
	protected $infoWindowZoom = 13;
49
50
	/** Lang of the gmap **/
51
	protected $lang = 'en';
52
53
	/**Center of the gmap **/
54
	protected $center = 'Paris, France';
55
56
	/*
57
	 Additional CSS classes to render as a class attribute for the div of the
58
	 map.  Use this if you want more  fine grained control over your map using
59
	 CSS.  If blank it will be ignored
60
	 */
61
	protected $additional_css_classes = '';
62
63
64
	/* Decided whether or not to show the inline map css style on div creation */
65
	protected $show_inline_map_div_style = true;
66
67
	protected $latLongCenter = null;
68
69
	protected $jsonMapStyles = '[]';
70
71
	/**
72
	 * Type of the gmap, can be:
73
	 *  'road' (roadmap),
74
	 *  'satellite' (sattelite/aerial photographs)
75
	 *  'hybrid' (hybrid of road and satellite)
76
	 *  'terrain' (terrain)
77
	 *  The JavaScript for the mapping service will convert this into a suitable mapping type
78
	 */
79
80
	protected $mapType = 'road';
81
82
83
	/** Content of the HTML generated **/
84
	protected $content = '';
85
86
	protected $mapService = 'google';
87
88
	/** Hide the marker by default **/
89
	protected $defaultHideMarker = false;
90
91
	/** Extra content (marker, etc...) **/
92
	protected $contentMarker = '';
93
94
	// a list of markers, markers being associative arrays
95
	protected $markers = array();
96
97
	/** Use clusterer to display a lot of markers on the gmap **/
98
	protected $useClusterer = false;
99
	protected $gridSize = 50;
100
	protected $maxZoom = 17;
101
	protected $clustererLibraryPath = "/mappable/javascript/google/markerclusterer.js";
102
103
	/** Enable automatic center/zoom **/
104
	protected $enableAutomaticCenterZoom = false;
105
106
	/** maximum longitude of all markers **/
107
	protected $maxLng = -1000000;
108
109
	/** minimum longitude of all markers **/
110
	protected $minLng = 1000000;
111
112
	/** max latitude of all markers **/
113
	protected $maxLat = -1000000;
114
115
	/** min latitude of all markers **/
116
	protected $minLat = 1000000;
117
118
	/** map center latitude (horizontal), calculated automatically as markers
119
	are added to the map **/
120
	protected $centerLat = null;
121
122
	/** map center longitude (vertical),  calculated automatically as markers
123
	are added to the map **/
124
	protected $centerLng = null;
125
126
	/** factor by which to fudge the boundaries so that when we zoom encompass,
127
	the markers aren't too close to the edge **/
128
	protected $coordCoef = 0.01;
129
130
	/* set this to true to render button to maximize / minimize a map */
131
	protected $allowFullScreen = null;
132
133
	/**
134
	 * Class constructor
135
	 *
136
	 * @param string  $googleMapKey the googleMapKey
137
	 */
138
139
	public function __construct($googleMapKey = '') {
140
		$this->googleMapKey = $googleMapKey;
141
	}
142
143
	public function setShowInlineMapDivStyle($new_show_inline_map_div_style) {
144
		$this->show_inline_map_div_style = $new_show_inline_map_div_style;
145
		return $this;
146
	}
147
148
	public function setAdditionalCSSClasses($new_additional_css_classes) {
149
		$this->additional_css_classes = $new_additional_css_classes;
150
		return $this;
151
	}
152
153
154
	public function setMapStyle($newStyles) {
155
		$this->jsonMapStyles = $newStyles;
156
		return $this;
157
	}
158
159
	/**
160
	 * Set the useClusterer parameter (optimization to display a lot of marker)
161
	 *
162
	 * @param boolean $useClusterer     use cluster or not
163
	 * @param int     $gridSize         grid size
164
	 * @param int     $maxZoom 			max zoom to cluster at
165
	 *
166
	 * * @return MapAPI This same object, in order to enable chaining of methods
167
	 */
168
169
	public function setClusterer($useClusterer, $gridSize = 50, $maxZoom = 17,
170
		$clustererLibraryPath = '/mappable/javascript/google/markerclusterer.js') {
171
		$this->useClusterer = $useClusterer;
172
		$this->gridSize = $gridSize;
173
		$this->maxZoom = $maxZoom;
174
		$this->clustererLibraryPath = $clustererLibraryPath;
175
		return $this;
176
	}
177
178
	/**
179
	 * Set the ID of the default gmap DIV
180
	 *
181
	 * @param string  $googleMapId the google div ID
182
	 *
183
	 * @return MapAPI This same object, in order to enable chaining of methods
184
	 */
185
186
	public function setDivId($googleMapId) {
187
		$this->googleMapId = $googleMapId;
188
		return $this;
189
	}
190
191
	/**
192
	 * Set the size of the gmap.  If these values are not provided
193
	 * then CSS is used instead
194
	 *
195
	 * @param int     $width  GoogleMap  width
196
	 * @param int     $height GoogleMap  height
197
	 *
198
	 * @return MapAPI This same object, in order to enable chaining of methods
199
	 */
200
201
	public function setSize($width, $height) {
202
		$this->width = $width;
203
		$this->height = $height;
204
		return $this;
205
	}
206
207
	/**
208
	 * Set the lang of the gmap
209
	 *
210
	 * @param string  $lang GoogleMap  lang : fr,en,..
211
	 *
212
	 * @return MapAPI This same object, in order to enable chaining of methods
213
	 */
214
215
	public function setLang($lang) {
216
		$this->lang = $lang;
217
		return $this;
218
	}
219
220
	/**
221
	 * Set the zoom of the gmap
222
	 *
223
	 * @param int $zoom GoogleMap zoom.
224
	 *
225
	 * @return MapAPI This same object, in order to enable chaining of methods
226
	 */
227
228
	public function setZoom($zoom) {
229
		$this->zoom = $zoom;
230
		return $this;
231
	}
232
233
	/**
234
	 * Set the zoom of the infowindow
235
	 *
236
	 * @param int 	$infoWindowZoom GoogleMap information window zoom.
237
	 *
238
	 * @return MapAPI This same object, in order to enable chaining of methods
239
	 */
240
241
	public function setInfoWindowZoom($infoWindowZoom) {
242
		$this->infoWindowZoom = $infoWindowZoom;
243
		return $this;
244
	}
245
246
	/**
247
	 * Enable the zoom on the marker when you click on it
248
	 *
249
	 * @param int $enableWindowZoom info window enabled zoom.
250
	 *
251
	 * @return MapAPI This same object, in order to enable chaining of methods
252
	 */
253
254
	public function setEnableWindowZoom($enableWindowZoom) {
255
		$this->enableWindowZoom = $enableWindowZoom;
0 ignored issues
show
Documentation Bug introduced by
The property $enableWindowZoom was declared of type boolean, but $enableWindowZoom is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
256
		return $this;
257
	}
258
259
	/**
260
	 * Enable theautomatic center/zoom at the gmap load
261
	 *
262
	 * @param int $enableAutomaticCenterZoom enable automatic centre zoom
263
	 *
264
	 * @return MapAPI This same object, in order to enable chaining of methods
265
	 */
266
267
	public function setEnableAutomaticCenterZoom($enableAutomaticCenterZoom) {
268
		$this->enableAutomaticCenterZoom = $enableAutomaticCenterZoom;
0 ignored issues
show
Documentation Bug introduced by
The property $enableAutomaticCenterZoom was declared of type boolean, but $enableAutomaticCenterZoom is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
269
		return $this;
270
	}
271
272
	/**
273
	 * Set the center of the gmap (an address)
274
	 *
275
	 * @param string  $center GoogleMap  center (an address)
276
	 *
277
	 * @return MapAPI This same object, in order to enable chaining of methods
278
	 */
279
280
	public function setCenter($center) {
281
		$this->center = $center;
282
		return $this;
283
	}
284
285
	/**
286
	 * Set the type of the gmap.  Also takes into account legacy settings
287
	 *
288
	 * FIXME - allow other valid settings in config for map type
289
	 *
290
	 * @param string  $mapType  Can be one of road,satellite,hybrid or terrain. Defaults to road
291
	 *
292
	 * @return MapAPI This same object, in order to enable chaining of methods
293
	 */
294
295
	public function setMapType($mapType) {
296
		$this->mapType = $mapType;
297
298
		// deal with legacy values for backwards compatbility
299
		switch ($mapType) {
300
			case 'google.maps.MapTypeId.SATELLITE':
301
				$this->mapType = "satellite";
302
				break;
303
			case 'google.maps.MapTypeId.G_HYBRID_MAP':
304
				$this->mapType = "hybrid";
305
				break;
306
			case 'google.maps.MapTypeId.G_PHYSICAL_MAP':
307
				$this->mapType = "terrain";
308
				break;
309
			case 'google.maps.MapTypeId.ROADMAP':
310
				$this->mapType = "road";
311
				break;
312
		}
313
		return $this;
314
	}
315
316
	/*
317
	Set whether or not to allow the full screen tools
318
	@return MapAPI This same object, in order to enable chaining of methods
319
	*/
320
	public function setAllowFullScreen($allowed) {
321
		$this->allowFullScreen = $allowed;
322
		return $this;
323
	}
324
325
	/**
326
	* Set the center of the gmap
327
	*
328
	* @return MapAPI This same object, in order to enable chaining of methods
329
	**/
330
	public function setLatLongCenter($center) {
331
		// error check, we want an associative array with lat,lng keys numeric
332
333
		if (!is_array($center)) {
334
			throw new InvalidArgumentException('Center must be an associative array containing lat,lng');
335
		}
336
337
		$keys = array_keys($center);
338
		sort($keys);
339
		if (implode(',', $keys) != 'lat,lng') {
340
			throw new InvalidArgumentException('Keys provided must be lat, lng');
341
		}
342
343
		$this->latLongCenter = $center;
344
		return $this;
345
	}
346
347
	/**
348
	 * Set the defaultHideMarker
349
	 *
350
	 * @param boolean $defaultHideMarker hide all the markers on the map by default
351
	 *
352
	 * @return MapAPI
353
	 */
354
355
	public function setDefaultHideMarker($defaultHideMarker) {
356
		$this->defaultHideMarker = $defaultHideMarker;
357
		return $this;
358
	}
359
360
	/**
361
	 * Get the google map content
362
	 *
363
	 * @return string the google map html code
364
	 */
365
366
	public function getGoogleMap() {
367
		return $this->content;
368
	}
369
370
371
	/**
372
	 * Get URL content using cURL.
373
	 *
374
	 * @param string  $url the url
375
	 *
376
	 * @return string the html code
377
	 *
378
	 * @todo add proxy settings
379
	 */
380
381
	public function getContent($url) {
382
		$curl = curl_init();
383
		curl_setopt($curl, CURLOPT_TIMEOUT, 10);
384
		curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
385
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
386
		curl_setopt($curl, CURLOPT_URL, $url);
387
		$data = curl_exec($curl);
388
		curl_close($curl);
389
		return $data;
390
	}
391
392
	/**
393
	 * Geocoding an address (address -> lat,lng)
394
	 *
395
	 * @param string  $address an address
396
	 *
397
	 * @return string array with precision, lat & lng
398
	 */
399
400
	public function geocoding($address) {
401
		$geocoder = new MappableGoogleGeocoder();
402
		$locations = $geocoder->getLocations($address);
403
		$result = null;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
404
		if (!empty($locations)) {
405
			$place = $locations[0];
406
			$location = $place['geometry']['location'];
407
			$result = array(
408
				'lat' => $location['lat'],
409
				'lon' => $location['lng'],
410
				'geocoded' => true
411
			);
412
413
		} else {
414
			$result = array(); // no results
415
		}
416
		return $result;
417
	}
418
419
	/**
420
	 * Add marker by his coord
421
	 *
422
	 * @param string  $lat      lat
423
	 * @param string  $lng      lngs
424
	 * @param string  $html     html code display in the info window
425
	 * @param string  $category marker category
426
	 * @param string  $icon     an icon url
427
	 *
428
	 * @return MapAPI
429
	 */
430
431
	public function addMarkerByCoords($lat, $lng, $html = '', $category = '', $icon = '') {
432
		$m = array(
433
			'latitude' => $lat,
434
			'longitude' => $lng,
435
			'html' => $html,
436
			'category' => $category,
437
			'icon' => $icon
438
		);
439
		array_push($this->markers, $m);
440
		return $this;
441
	}
442
443
444
	/**
445
	 * Add marker by his address
446
	 *
447
	 * @param string  $address  an ddress
448
	 * @param string  $content  html code display in the info window
449
	 * @param string  $category marker category
450
	 * @param string  $icon     an icon url
451
	 *
452
	 * @return MapAPI
453
	 */
454
455
	public function addMarkerByAddress($address, $content = '', $category = '', $icon = '') {
456
		$point = $this->geocoding($address);
457
		if ($point !== null) {
458
			$this->addMarkerByCoords($point['lat'], $point['lon'], $content, $category, $icon);
459
		}
460
		return $this;
461
	}
462
463
	/**
464
	 * Add marker by an array of coord
465
	 *
466
	 * @param array  $coordtab an array of lat,lng,content
467
	 * @param string  $category marker category
468
	 * @param string  $icon     an icon url
469
	 *
470
	 * @return MapAPI
471
	 */
472
473
	public function addArrayMarkerByCoords($coordtab, $category = '', $icon = '') {
474
		foreach ($coordtab as $coord) {
475
			$this->addMarkerByCoords($coord[0], $coord[1], $coord[2], $category, $icon);
476
		}
477
		return $this;
478
	}
479
480
481
	/**
482
	 * Adds a {@link ViewableData} object that implements {@link Mappable}
483
	 * to the map.
484
	 * @param   $infowindowtemplateparams Optional array of extra parameters to pass to the map info window
485
	 *
486
	 * @param ViewableData $obj
487
	 */
488
	public function addMarkerAsObject(ViewableData $obj, $infowindowtemplateparams = null) {
489
		$extensionsImplementMappable = false;
490
		$extensions = Object::get_extensions(get_class($obj));
491
		if (is_array($extensions)) {
492
493
			foreach ($extensions as $extension) {
494
				$class = new ReflectionClass($extension);
495
				if ($class->implementsInterface('Mappable')) {
496
					$extensionsImplementMappable = true;
497
				}
498
499
			}
500
		}
501
502
		if ($extensionsImplementMappable ||
503
			($obj instanceof Mappable) ||
504
			(Object::has_extension($obj->ClassName, 'MapExtension'))
505
		) {
506
			$cat = $obj->hasMethod('getMappableMapCategory') ? $obj->getMappableMapCategory() : "default";
507
			if ($infowindowtemplateparams !== null) {
508
				foreach ($infowindowtemplateparams as $key => $value) {
509
					$obj->{$key} = $value;
510
				}
511
			}
512
			$this->addMarkerByCoords(
513
				$obj->getMappableLatitude(),
514
				$obj->getMappableLongitude(),
515
				$obj->getMappableMapContent(),
516
				$cat,
517
				$obj->getMappableMapPin()
518
			);
519
		}
520
521
		return $this;
522
	}
523
524
525
	/**
526
	 * Draws a line between two {@link ViewableData} objects
527
	 *
528
	 * @param ViewableData $one   The first point
529
	 * @param ViewableData $two   The second point
530
	 * @param string  $color The hexidecimal color of the line
531
	 */
532
	public function connectPoints(ViewableData $one, ViewableData $two, $color = "#FF3300") {
533
		$this->addLine(
534
			array($one->getMappableLatitude(), $one->getMappableLongitude()),
535
			array($two->getMappableLatitude(), $two->getMappableLongitude()),
536
			$color
537
		);
538
	}
539
540
	public function forTemplate() {
541
		$this->generate();
542
		MapUtil::set_map_already_rendered(true);
543
		return $this->getGoogleMap();
544
	}
545
546
	/**
547
	 * Add a KML file which will be rendered on this map.  Normally used for likes
548
	 * of GPS traces from activities
549
	 *
550
	 * @param string  $url      url of the kml file compatible with gmap and gearth
551
	 *
552
	 * @return MapAPI
553
	 */
554
555
	public function addKML($url) {
556
		array_push($this->kmlFiles, $url);
557
		return $this;
558
	}
559
560
561
	/*
562
	Add a line to the map
563
564
	*/
565
	public function addLine($from = array(), $to = array(), $color = "#FF3300") {
566
		$line = array(
567
			'lat1' => $from[0],
568
			'lon1' => $from[1],
569
			'lat2' => $to[0],
570
			'lon2' => $to[1],
571
			'color' => $color
572
		);
573
574
		array_push($this->lines, $line);
575
		return $this;
576
	}
577
578
579
	/*
580
	For php 5.3
581
	*/
582
	public static function jsonRemoveUnicodeSequences($struct) {
583
		 return preg_replace("/\\\\u([a-f0-9]{4})/e",
584
		 					"iconv('UCS-4LE','UTF-8',pack('V', hexdec('U$1')))",
585
		 					json_encode($struct));
586
	}
587
588
589
	/**
590
	 * Generate the gmap
591
	 *
592
	 * @return void
593
	 */
594
595
	public function generate() {
596
		// from http://stackoverflow.com/questions/3586401/cant-decode-json-string-in-php
597
		$jsonMarkers = null;
0 ignored issues
show
Unused Code introduced by
$jsonMarkers is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
598
		$linesJson = null;
0 ignored issues
show
Unused Code introduced by
$linesJson is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
599
		$kmlJson = null;
0 ignored issues
show
Unused Code introduced by
$kmlJson is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
600
601
		// prior to PHP version 5.4, one needs to use regex
602
		if (PHP_VERSION_ID < 50400) {
603
			$jsonMarkers = stripslashes(MapAPI::jsonRemoveUnicodeSequences($this->markers));
604
			$linesJson = stripslashes(MapAPI::jsonRemoveUnicodeSequences($this->lines));
605
			$kmlJson = stripslashes(MapAPI::jsonRemoveUnicodeSequences($this->kmlFiles));
606
		} else {
607
			$jsonMarkers = stripslashes(json_encode($this->markers, JSON_UNESCAPED_UNICODE));
608
			$linesJson = stripslashes(json_encode($this->lines, JSON_UNESCAPED_UNICODE));
609
			$kmlJson = stripslashes(json_encode($this->kmlFiles, JSON_UNESCAPED_UNICODE));
610
		}
611
612
		 // Center of the GMap - text centre takes precedence
613
		$geocodeCentre = ($this->latLongCenter) ?
614
							$this->latLongCenter : $this->geocoding($this->center);
615
616
		// coordinates for centre depending on which method used
617
		if (isset($geocodeCentre['geocoded'])) {
618
			$latlngCentre = array(
619
				'lat' => $geocodeCentre['lat'],
620
				'lng' => $geocodeCentre['lon']
621
			);
622
		} else if (is_array($this->latLongCenter)) {
623
			$latlngCentre = $this->latLongCenter;
624
		}
625
626
		$this->LatLngCentreJSON = stripslashes(json_encode($latlngCentre));
0 ignored issues
show
Documentation introduced by
The property LatLngCentreJSON does not exist on object<MapAPI>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Bug introduced by
The variable $latlngCentre does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
627
628
		$lenLng = $this->maxLng - $this->minLng;
629
		$lenLat = $this->maxLat - $this->minLat;
630
		$this->minLng -= $lenLng * $this->coordCoef;
631
		$this->maxLng += $lenLng * $this->coordCoef;
632
		$this->minLat -= $lenLat * $this->coordCoef;
633
		$this->maxLat += $lenLat * $this->coordCoef;
634
635
		// add the css class mappable as a handle onto the map styling
636
		$this->additional_css_classes .= ' mappable';
637
638
		if (!$this->enableAutomaticCenterZoom) {
639
			$this->enableAutomaticCenterZoom = 'false';
0 ignored issues
show
Documentation Bug introduced by
The property $enableAutomaticCenterZoom was declared of type boolean, but 'false' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
640
		}
641
642
		if (!$this->useClusterer) {
643
			$this->useClusterer = 'false';
0 ignored issues
show
Documentation Bug introduced by
The property $useClusterer was declared of type boolean, but 'false' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
644
		}
645
646
		if (!$this->defaultHideMarker) {
647
			$this->defaultHideMarker = 'false';
0 ignored issues
show
Documentation Bug introduced by
The property $defaultHideMarker was declared of type boolean, but 'false' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
648
		}
649
650
		if (!$this->MapTypeId) {
0 ignored issues
show
Bug introduced by
The property MapTypeId does not seem to exist. Did you mean mapType?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
651
			$this->MapTypeId = 'false';
0 ignored issues
show
Bug introduced by
The property MapTypeId does not seem to exist. Did you mean mapType?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
652
		}
653
654
		// initialise full screen as the config value if not already set
655
		if ($this->allowFullScreen === null) {
656
			$this->allowFullScreen = Config::inst()->get('Mappable', 'allow_full_screen');
657
		}
658
659
		if (!$this->allowFullScreen) {
660
			$this->allowFullScreen = 'false';
661
		}
662
663
		if (!$this->enableWindowZoom) {
664
			$this->enableWindowZoom = 'false';
0 ignored issues
show
Documentation Bug introduced by
The property $enableWindowZoom was declared of type boolean, but 'false' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
665
		}
666
667
		$vars = new ArrayData(array(
668
669
				'JsonMapStyles' => $this->jsonMapStyles,
670
				'AdditionalCssClasses' => $this->additional_css_classes,
671
				'Width' => $this->width,
672
				'Height' => $this->height,
673
				'ShowInlineMapDivStyle' => $this->show_inline_map_div_style,
674
				'InfoWindowZoom' => $this->infoWindowZoom,
675
				'EnableWindowZoom' => $this->enableWindowZoom,
676
				'MapMarkers' => $jsonMarkers,
677
				'DefaultHideMarker' => $this->defaultHideMarker,
678
				'LatLngCentre' => $this->LatLngCentreJSON,
0 ignored issues
show
Documentation introduced by
The property LatLngCentreJSON does not exist on object<MapAPI>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
679
				'EnableAutomaticCenterZoom' => $this->enableAutomaticCenterZoom,
680
				'Zoom' => $this->zoom,
681
				'MaxZoom' => $this->maxZoom,
682
				'GridSize' => $this->gridSize,
683
				'MapType' => $this->mapType,
684
				'GoogleMapID' => $this->googleMapId,
685
				'Lang'=>$this->lang,
686
				'UseClusterer'=>$this->useClusterer,
687
				'ClustererLibraryPath' => $this->clustererLibraryPath,
688
				'ClustererMaxZoom' => $this->maxZoom,
689
				'ClustererGridSize' => $this->gridSize,
690
				'Lines' => $linesJson,
691
				'KmlFiles' => $kmlJson,
692
				'AllowFullScreen' => $this->allowFullScreen,
693
				'UseCompressedAssets' => Config::inst()->get('Mappable', 'use_compressed_assets')
694
			)
695
		);
696
697
		if (!MapUtil::get_map_already_rendered()) {
698
			$vars->setField('GoogleMapKey', $this->googleMapKey);
699
			$vars->setField('GoogleMapLang', $this->lang);
700
		}
701
702
		// HTML component of the map
703
		$this->content = $this->processTemplateHTML('Map', $vars);
704
	}
705
706
	/**
707
	 * @param string $templateName
708
	 * @param ArrayData $templateVariables
709
	 */
710
	public function processTemplateHTML($templateName, $templateVariables = null) {
711
		if (!$templateVariables) {
712
			$templateVariables = new ArrayList();
713
		}
714
		$mappingService = Config::inst()->get('Mappable', 'mapping_service');
715
		$result = $templateVariables->renderWith($templateName.$mappingService.'HTML');
716
		return $result;
717
	}
718
}
719