Joomla Platform  13.1
Documentation des API du framework Joomla Platform
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
maps.php
Aller à la documentation de ce fichier.
1 <?php
2 /**
3  * @package Joomla.Platform
4  * @subpackage Google
5  *
6  * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved
7  * @license GNU General Public License version 2 or later; see LICENSE
8  */
9 
10 defined('JPATH_PLATFORM') or die;
11 
12 /**
13  * Google Maps embed class for the Joomla Platform.
14  *
15  * @package Joomla.Platform
16  * @subpackage Google
17  * @since 12.3
18  */
20 {
21 
22  /**
23  * @var JHttp The HTTP client object to use in sending HTTP requests.
24  * @since 12.3
25  */
26  protected $http;
27 
28  /**
29  * Constructor.
30  *
31  * @param JRegistry $options Google options object
32  * @param JUri $uri URL of the page being rendered
33  * @param JHttp $http Http client for geocoding requests
34  *
35  * @since 12.3
36  */
37  public function __construct(JRegistry $options = null, JUri $uri = null, JHttp $http = null)
38  {
39  parent::__construct($options = null, $uri = null);
40  $this->http = $http ? $http : new JHttp($this->options);
41  }
42 
43  /**
44  * Method to get the API key
45  *
46  * @return string The Google Maps API key
47  *
48  * @since 12.3
49  */
50  public function getKey()
51  {
52  return $this->getOption('key');
53  }
54 
55  /**
56  * Method to set the API key
57  *
58  * @param string $key The Google Maps API key
59  *
60  * @return JGoogleEmbedMaps The object for method chaining
61  *
62  * @since 12.3
63  */
64  public function setKey($key)
65  {
66  $this->setOption('key', $key);
67 
68  return $this;
69  }
70 
71  /**
72  * Method to get the id of the map div
73  *
74  * @return string The ID
75  *
76  * @since 12.3
77  */
78  public function getMapID()
79  {
80  return $this->getOption('mapid') ? $this->getOption('mapid') : 'map_canvas';
81  }
82 
83  /**
84  * Method to set the map div id
85  *
86  * @param string $id The ID
87  *
88  * @return JGoogleEmbedMaps The object for method chaining
89  *
90  * @since 12.3
91  */
92  public function setMapID($id)
93  {
94  $this->setOption('mapid', $id);
95 
96  return $this;
97  }
98 
99  /**
100  * Method to get the class of the map div
101  *
102  * @return string The class
103  *
104  * @since 12.3
105  */
106  public function getMapClass()
107  {
108  return $this->getOption('mapclass') ? $this->getOption('mapclass') : '';
109  }
110 
111  /**
112  * Method to set the map div class
113  *
114  * @param string $class The class
115  *
116  * @return JGoogleEmbedMaps The object for method chaining
117  *
118  * @since 12.3
119  */
120  public function setMapClass($class)
121  {
122  $this->setOption('mapclass', $class);
123 
124  return $this;
125  }
126 
127  /**
128  * Method to get the style of the map div
129  *
130  * @return string The style
131  *
132  * @since 12.3
133  */
134  public function getMapStyle()
135  {
136  return $this->getOption('mapstyle') ? $this->getOption('mapstyle') : '';
137  }
138 
139  /**
140  * Method to set the map div style
141  *
142  * @param string $style The style
143  *
144  * @return JGoogleEmbedMaps The object for method chaining
145  *
146  * @since 12.3
147  */
148  public function setMapStyle($style)
149  {
150  $this->setOption('mapstyle', $style);
151 
152  return $this;
153  }
154 
155  /**
156  * Method to get the map type setting
157  *
158  * @return string The class
159  *
160  * @since 12.3
161  */
162  public function getMapType()
163  {
164  return $this->getOption('maptype') ? $this->getOption('maptype') : 'ROADMAP';
165  }
166 
167  /**
168  * Method to set the map type ()
169  *
170  * @param string $type Valid types are ROADMAP, SATELLITE, HYBRID, and TERRAIN
171  *
172  * @return JGoogleEmbedMaps The object for method chaining
173  *
174  * @since 12.3
175  */
176  public function setMapType($type)
177  {
178  $this->setOption('maptype', strtoupper($type));
179 
180  return $this;
181  }
182 
183  /**
184  * Method to get additional map options
185  *
186  * @return string The options
187  *
188  * @since 12.3
189  */
190  public function getAdditionalMapOptions()
191  {
192  return $this->getOption('mapoptions') ? $this->getOption('mapoptions') : array();
193  }
194 
195  /**
196  * Method to add additional map options
197  *
198  * @param array $options Additional map options
199  *
200  * @return JGoogleEmbedMaps The object for method chaining
201  *
202  * @since 12.3
203  */
204  public function setAdditionalMapOptions($options)
205  {
206  $this->setOption('mapoptions', $options);
207 
208  return $this;
209  }
210 
211  /**
212  * Method to get additional map options
213  *
214  * @return string The options
215  *
216  * @since 12.3
217  */
218  public function getAdditionalJavascript()
219  {
220  return $this->getOption('extrascript') ? $this->getOption('extrascript') : '';
221  }
222 
223  /**
224  * Method to add additional javascript
225  *
226  * @param array $script Additional javascript
227  *
228  * @return JGoogleEmbedMaps The object for method chaining
229  *
230  * @since 12.3
231  */
232  public function setAdditionalJavascript($script)
233  {
234  $this->setOption('extrascript', $script);
235 
236  return $this;
237  }
238 
239  /**
240  * Method to get the zoom
241  *
242  * @return int The zoom level
243  *
244  * @since 12.3
245  */
246  public function getZoom()
247  {
248  return $this->getOption('zoom') ? $this->getOption('zoom') : 0;
249  }
250 
251  /**
252  * Method to set the map zoom
253  *
254  * @param int $zoom Zoom level (0 is whole world)
255  *
256  * @return JGoogleEmbedMaps The object for method chaining
257  *
258  * @since 12.3
259  */
260  public function setZoom($zoom)
261  {
262  $this->setOption('zoom', $zoom);
263 
264  return $this;
265  }
266 
267  /**
268  * Method to set the center of the map
269  *
270  * @return mixed A latitude longitude array or an address string
271  *
272  * @since 12.3
273  */
274  public function getCenter()
275  {
276  return $this->getOption('mapcenter') ? $this->getOption('mapcenter') : array(0, 0);
277  }
278 
279  /**
280  * Method to set the center of the map
281  *
282  * @param mixed $location A latitude/longitude array or an address string
283  * @param mixed $title Title of marker or false for no marker
284  * @param array $markeroptions Options for marker
285  *
286  * @return JGoogleEmbedMaps The latitude/longitude of the center or false on failure
287  *
288  * @since 12.3
289  */
290  public function setCenter($location, $title = true, $markeroptions = array())
291  {
292  if ($title)
293  {
294  $title = is_string($title) ? $title : null;
295 
296  if (!$marker = $this->addMarker($location, $title, $markeroptions))
297  {
298  return false;
299  }
300  $location = $marker['loc'];
301  }
302  elseif (is_string($location))
303  {
304  $geocode = $this->geocodeAddress($location);
305 
306  if (!$geocode)
307  {
308  return false;
309  }
310 
311  $location = $geocode['geometry']['location'];
312  $location = array_values($location);
313  }
314 
315  $this->setOption('mapcenter', $location);
316 
317  return $this;
318  }
319 
320  /**
321  * Add a marker to the map
322  *
323  * @param mixed $location A latitude longitude array or an address string
324  * @param mixed $title The hover-text for the marker
325  * @param array $options Options for marker
326  *
327  * @return mixed The marker or false on failure
328  *
329  * @since 12.3
330  */
331  public function addMarker($location, $title = null, $options = array())
332  {
333  if (is_string($location))
334  {
335  if (!$title)
336  {
337  $title = $location;
338  }
339 
340  $geocode = $this->geocodeAddress($location);
341 
342  if (!$geocode)
343  {
344  return false;
345  }
346 
347  $location = $geocode['geometry']['location'];
348  }
349  elseif (!$title)
350  {
351  $title = implode(', ', $location);
352  }
353 
354  $location = array_values($location);
355  $marker = array('loc' => $location, 'title' => $title, 'options' => $options);
356 
357  $markers = $this->listMarkers();
358  $markers[] = $marker;
359  $this->setOption('markers', $markers);
360 
361  return $marker;
362  }
363 
364  /**
365  * List the markers added to the map
366  *
367  * @return array A list of markers
368  *
369  * @since 12.3
370  */
371  public function listMarkers()
372  {
373  return $this->getOption('markers') ? $this->getOption('markers') : array();
374  }
375 
376  /**
377  * Delete a marker from the map
378  *
379  * @param int $index Index of marker to delete (defaults to last added marker)
380  *
381  * @return array The latitude/longitude of the deleted marker
382  *
383  * @since 12.3
384  */
385  public function deleteMarker($index = null)
386  {
387  $markers = $this->listMarkers();
388 
389  if ($index === null)
390  {
391  $index = count($markers) - 1;
392  }
393 
394  if ($index >= count($markers) || $index < 0)
395  {
396  throw new OutOfBoundsException('Marker index out of bounds.');
397  }
398 
399  $marker = $markers[$index];
400  unset($markers[$index]);
401  $markers = array_values($markers);
402  $this->setOption('markers', $markers);
403 
404  return $marker;
405  }
406 
407  /**
408  * Checks if the javascript is set to be asynchronous
409  *
410  * @return boolean True if asynchronous
411  *
412  * @since 12.3
413  */
414  public function isAsync()
415  {
416  return $this->getOption('async') === null ? true : $this->getOption('async');
417  }
418 
419  /**
420  * Load javascript asynchronously
421  *
422  * @return JGoogleEmbedMaps The object for method chaining
423  *
424  * @since 12.3
425  */
426  public function useAsync()
427  {
428  $this->setOption('async', true);
429 
430  return $this;
431  }
432 
433  /**
434  * Load javascript synchronously
435  *
436  * @return JGoogleEmbedAMaps The object for method chaining
437  *
438  * @since 12.3
439  */
440  public function useSync()
441  {
442  $this->setOption('async', false);
443 
444  return $this;
445  }
446 
447  /**
448  * Method to get callback function for async javascript loading
449  *
450  * @return string The ID
451  *
452  * @since 12.3
453  */
454  public function getAsyncCallback()
455  {
456  return $this->getOption('callback') ? $this->getOption('callback') : 'initialize';
457  }
458 
459  /**
460  * Method to set the callback function for async javascript loading
461  *
462  * @param string $callback The callback function name
463  *
464  * @return JGoogleEmbedMaps The object for method chaining
465  *
466  * @since 12.3
467  */
468  public function setAsyncCallback($callback)
469  {
470  $this->setOption('callback', $callback);
471 
472  return $this;
473  }
474 
475  /**
476  * Checks if a sensor is set to be required
477  *
478  * @return boolean True if asynchronous
479  *
480  * @since 12.3
481  */
482  public function hasSensor()
483  {
484  return $this->getOption('sensor') === null ? false : $this->getOption('sensor');
485  }
486 
487  /**
488  * Require access to sensor data
489  *
490  * @return JGoogleEmbedMaps The object for method chaining
491  *
492  * @since 12.3
493  */
494  public function useSensor()
495  {
496  $this->setOption('sensor', true);
497 
498  return $this;
499  }
500 
501  /**
502  * Don't require access to sensor data
503  *
504  * @return JGoogleEmbedAMaps The object for method chaining
505  *
506  * @since 12.3
507  */
508  public function noSensor()
509  {
510  $this->setOption('sensor', false);
511 
512  return $this;
513  }
514 
515  /**
516  * Checks how the script should be loaded
517  *
518  * @return string Autoload type (onload, jquery, mootools, or false)
519  *
520  * @since 12.3
521  */
522  public function getAutoload()
523  {
524  return $this->getOption('autoload') ? $this->getOption('autoload') : 'false';
525  }
526 
527  /**
528  * Automatically add the callback to the window
529  *
530  * @param string $type The method to add the callback (options are onload, jquery, mootools, and false)
531  *
532  * @return JGoogleEmbedAMaps The object for method chaining
533  *
534  * @since 12.3
535  */
536  public function setAutoload($type = 'onload')
537  {
538  $this->setOption('autoload', $type);
539 
540  return $this;
541  }
542 
543  /**
544  * Get code to load Google Maps javascript
545  *
546  * @return string Javascript code
547  *
548  * @since 12.3
549  */
550  public function getHeader()
551  {
552  if (!$this->getOption('key'))
553  {
554  throw new UnexpectedValueException('A Google Maps API key is required.');
555  }
556 
557  $zoom = $this->getZoom();
558  $center = $this->getCenter();
559  $maptype = $this->getMapType();
560  $id = $this->getMapID();
561  $scheme = $this->isSecure() ? 'https' : 'http';
562  $key = $this->getKey();
563  $sensor = $this->hasSensor() ? 'true' : 'false';
564 
565  $setup = 'var mapOptions = {';
566  $setup .= "zoom: {$zoom},";
567  $setup .= "center: new google.maps.LatLng({$center[0]},{$center[1]}),";
568  $setup .= "mapTypeId: google.maps.MapTypeId.{$maptype},";
569  $setup .= substr(json_encode($this->getAdditionalMapOptions()), 1, -1);
570  $setup .= '};';
571  $setup .= "var map = new google.maps.Map(document.getElementById('{$id}'), mapOptions);";
572 
573  foreach ($this->listMarkers() as $marker)
574  {
575  $loc = $marker['loc'];
576  $title = $marker['title'];
577  $options = $marker['options'];
578 
579  $setup .= 'new google.maps.Marker({';
580  $setup .= "position: new google.maps.LatLng({$loc[0]},{$loc[1]}),";
581  $setup .= 'map: map,';
582  $setup .= "title:'{$title}',";
583  $setup .= substr(json_encode($options), 1, -1);
584  $setup .= '});';
585  }
586 
587  $setup .= $this->getAdditionalJavascript();
588 
589  if ($this->isAsync())
590  {
591  $asynccallback = $this->getAsyncCallback();
592 
593  $output = '<script type="text/javascript">';
594  $output .= "function {$asynccallback}() {";
595  $output .= $setup;
596  $output .= '}';
597 
598  $onload = "function() {";
599  $onload .= 'var script = document.createElement("script");';
600  $onload .= 'script.type = "text/javascript";';
601  $onload .= "script.src = '{$scheme}://maps.googleapis.com/maps/api/js?key={$key}&sensor={$sensor}&callback={$asynccallback}';";
602  $onload .= 'document.body.appendChild(script);';
603  $onload .= '}';
604  }
605  else
606  {
607  $output = "<script type='text/javascript' src='{$scheme}://maps.googleapis.com/maps/api/js?key={$key}&sensor={$sensor}'>";
608  $output .= '</script>';
609  $output .= '<script type="text/javascript">';
610 
611  $onload = "function() {";
612  $onload .= $setup;
613  $onload .= '}';
614  }
615 
616  switch ($this->getAutoload())
617  {
618  case 'onload':
619  $output .= "window.onload={$onload};";
620  break;
621 
622  case 'jquery':
623  $output .= "$(document).ready({$onload});";
624  break;
625 
626  case 'mootools':
627  $output .= "window.addEvent('domready',{$onload});";
628  break;
629  }
630 
631  $output .= '</script>';
632 
633  return $output;
634  }
635 
636  /**
637  * Method to retrieve the div that the map is loaded into
638  *
639  * @return string The body
640  *
641  * @since 12.3
642  */
643  public function getBody()
644  {
645  $id = $this->getMapID();
646  $class = $this->getMapClass();
647  $style = $this->getMapStyle();
648 
649  $output = "<div id='{$id}'";
650 
651  if (!empty($class))
652  {
653  $output .= " class='{$class}'";
654  }
655 
656  if (!empty($style))
657  {
658  $output .= " style='{$style}'";
659  }
660 
661  $output .= '></div>';
662 
663  return $output;
664  }
665 
666  /**
667  * Method to get the location information back from an address
668  *
669  * @param string $address The address to geocode
670  *
671  * @return array An array containing Google's geocode data
672  *
673  * @since 12.3
674  */
675  public function geocodeAddress($address)
676  {
677  $url = 'http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=' . urlencode($address);
678  $response = $this->http->get($url);
679 
680  if ($response->code < 200 || $response->code >= 300)
681  {
682  throw new RuntimeException('Error code ' . $response->code . ' received geocoding address: ' . $response->body . '.');
683  }
684 
685  $data = json_decode($response->body, true);
686 
687  if (!$data)
688  {
689  throw new RuntimeException('Invalid json received geocoding address: ' . $response->body . '.');
690  }
691  if ($data['status'] != 'OK')
692  {
693  return null;
694  }
695 
696  return $data['results'][0];
697  }
698 }