source: extensions/GMaps/gmaps_pip.class.inc.php @ 12153

Last change on this file since 12153 was 10551, checked in by grum, 13 years ago

bug:2148 - compatibility with piwigo 2.2
bug:2062 - compatibility with IE7

  • Property svn:executable set to *
File size: 21.2 KB
Line 
1<?php
2/* -----------------------------------------------------------------------------
3  Plugin     : GMaps
4  Author     : Grum
5    email    : grum@piwigo.org
6    website  : http://photos.grum.fr
7
8    << May the Little SpaceFrog be with you ! >>
9  ------------------------------------------------------------------------------
10  See main.inc.php for release information
11
12  GMaps_PIP : classe to manage plugin public pages
13
14  --------------------------------------------------------------------------- */
15
16include_once('gmaps_root.class.inc.php');
17
18class GMaps_PIP extends GMaps_root
19{
20  const CAT_ID_HOME = 0;
21  const CAT_ID_TAGS = -1;
22
23  protected $category=array(
24    'id' => 0,
25    'bounds' => array(
26      'N' => -90,
27      'S' => 90,
28      'E' => -180,
29      'W' => 180
30    ),
31    'icon' => array(
32      'style' => true,
33      'file' => '',
34      'width' => -1,
35      'height' => -1
36    )
37  );
38  protected $picture=array(
39    'geolocated' => false,
40    'forceDisplay' => false,
41    'coords' => array('lat' => 0, 'lng' => 0),
42    'content' => array(
43      'I' => array(), // icon display mode
44      'M' => array(), // meta display mode
45    ),
46    'properties' => array(),
47    'icon' => array(
48      'style' => true,
49      'file' => '',
50      'width' => -1,
51      'height' => -1
52      )
53  );
54  protected $css2;
55
56  public function __construct($prefixeTable, $filelocation)
57  {
58    parent::__construct($prefixeTable, $filelocation);
59    $this->css2 = new GPCCss(dirname($this->getFileLocation()).'/'.$this->getPluginNameFiles()."2.css");
60    $this->loadConfig();
61    $this->initEvents();
62    $this->load_lang();
63  }
64
65  public function __destruct()
66  {
67    unset($maps);
68    unset($picture);
69    parent::__destruct();
70  }
71
72  /*
73    load language file
74  */
75  public function load_lang()
76  {
77    global $lang;
78
79    load_language('plugin.lang', GMAPS_PATH);
80  }
81
82  /*
83    initialize events call for the plugin
84  */
85  public function initEvents()
86  {
87    parent::initEvents();
88
89    add_event_handler('loc_begin_index', array(&$this, 'displayCategoryPageMap'));
90    add_event_handler('loc_begin_picture', array(&$this, 'displayPicturePageMap'), EVENT_HANDLER_PRIORITY_NEUTRAL+5);
91    add_event_handler('amd_jpegMD_loaded', array(&$this, 'preparePictureMaps'));
92    add_event_handler('loc_end_page_header', array(&$this->css2, 'applyCSS'));
93    add_event_handler('render_category_description',  array(&$this, 'categoryMarkup'), EVENT_HANDLER_PRIORITY_NEUTRAL-5, 2);
94  }
95
96
97
98  /* -------------------------------------------------------------------------
99    FUNCTIONS TO MANAGE GMAPS
100  ------------------------------------------------------------------------- */
101
102
103  /**
104   * this function display maps defined as markup in the categories description
105   * [gmaps=id:999;with:999;height:999;kmlId:999;kmlUrl:"xxx";kmlZoom:y|n;markerImg:xxx;markerVisible:y|n;allowBubble:y|n;]
106   *
107   * the function is called on the 'render_category_description' event
108   * maps are displayed only for 'main_page_category_description' page
109   *
110   * @param String $desc : category description
111   * @param String $param : category page (expected value: 'main_page_category_description')
112   * @return String : the modified description
113   */
114  public function categoryMarkup($desc, $param='')
115  {
116    global $template, $page;
117
118    $mapParams=array();
119    if(preg_match_all('/\[gmaps=(?:id:(?P<id>\d+);|width:(?P<width>\d+);|height:(?P<height>\d+);|markerImg:(?P<markerImg>[a-z0-9\-\._]+);|kmlId:(?P<kmlId>\d+);|kmlUrl:"(?P<kmlUrl>.+)";|allowBubble:(?P<allowBubble>y|n);|kmlZoom:(?P<kmlZoom>y|n);|markerVisible:(?P<markerVisible>y|n);)+\]/i',$desc,$mapParams,PREG_SET_ORDER)>0)
120    {
121      if($param!='main_page_category_description')
122      {
123        // if not main page, just remove the [gmaps] markup
124        $desc = preg_replace('/\[gmaps=(?:.*)\]/i','',$desc);
125        return($desc);
126      }
127
128      GPCCore::addHeaderJS("jquery", "themes/default/js/jquery.min.js");
129      GPCCore::addHeaderJS("maps.google.com/api", "http://maps.google.com/maps/api/js?sensor=false");
130      GPCCore::addHeaderJS("gmaps.markup", "plugins/GMaps/js/gmapsMarkup".GPCCore::getMinified().".js", array('jquery'));
131
132      $desc = preg_replace(
133        '/\[gmaps=(?:id:(?P<id>\d+);|width:(?P<width>\d+);|height:(?P<height>\d+);|markerImg:(?P<markerImg>[a-z0-9\-\._]+);|kmlId:(?P<kmlId>\d+);|kmlUrl:"(?P<kmlUrl>.+)";|allowBubble:(?P<allowBubble>y|n);|kmlZoom:(?P<kmlZoom>y|n);|markerVisible:(?P<markerVisible>y|n);)+\]/i',
134        "<div class='gmapsMarkup' id='gmapsMarkupId$1'></div>", $desc);
135
136      $scripts=array();
137
138      foreach($mapParams as $mapParam)
139      {
140        $nb=$this->prepareCategoryMap($page['category']['id'], $mapParam['id']);
141
142        if(!isset($mapParam['allowBubble'])) $mapParam['allowBubble']='y';
143        if(!isset($mapParam['kmlZoom'])) $mapParam['kmlZoom']='n';
144        if(!isset($mapParam['width'])) $mapParam['width']='';
145        if(!isset($mapParam['height'])) $mapParam['height']='';
146        if(!isset($mapParam['markerImg']) or $mapParam['markerImg']=='') $mapParam['markerImg']='mS01_11.png';
147        if(!isset($mapParam['markerVisible']) or $mapParam['markerVisible']=='') $mapParam['markerVisible']='y';
148        if(isset($mapParam['kmlId']) and $mapParam['kmlId']!='')
149        {
150          $sql="SELECT file
151                FROM ".$this->tables['kmlfiles']."
152                WHERE id=".$mapParam['kmlId'];
153          $result=pwg_query($sql);
154          if($result)
155          {
156            while($row=pwg_db_fetch_assoc($result))
157            {
158              $mapParam['kmlUrl']=$_SERVER['SCRIPT_URI'].PWG_LOCAL_DIR.self::KML_DIRECTORY.$row['file'];
159            }
160          }
161        }
162        if(!isset($mapParam['kmlUrl'])) $mapParam['kmlUrl']='';
163
164        foreach($this->maps as $map)
165        {
166          $scripts[]="
167            {
168              id:'gmapsMarkupId".$mapParam['id']."',
169              mapId:".$mapParam['id'].",
170              zoomLevel:".$map['zoomLevel'].",
171              markerImg:'".$mapParam['markerImg']."',
172              markerVisible:".($mapParam['markerVisible']=='y'?'true':'false').",
173              mapType:'".$map['mapType']."',
174              mapTypeControl:'".$map['mapTypeControl']."',
175              navigationControl:'".$map['navigationControl']."',
176              scaleControl:'".$map['scaleControl']."',
177              streetViewControl:'".$map['streetViewControl']."',
178              kmlFileUrl:'".$mapParam['kmlUrl']."',
179              displayType:'".$map['displayType']."',
180              width:".($mapParam['width']==''?$map['width']:$mapParam['width']).",
181              height:".($mapParam['height']==''?$map['height']:$mapParam['height']).",
182              markers:[],
183              fitToBounds:true,
184              zoomLevelMaxActivated:".($map['zoomLevelMaxActivated']=='y'?'true':'false').",
185              mapBounds:
186                {
187                  north:".$this->category['bounds']['N'].",
188                  south:".$this->category['bounds']['S'].",
189                  east:".$this->category['bounds']['E'].",
190                  west:".$this->category['bounds']['W']."
191                },
192              geolocated:".($nb>0?'true':'false').",
193              kmlZoom:".($mapParam['kmlZoom']=='y'?'true':'false').",
194              allowBubble:".($mapParam['allowBubble']=='y'?'true':'false')."
195            }
196          ";
197        }
198      }
199
200      $template->append('head_elements',
201        "<script type=\"text/javascript\">
202        var gmapsMarkup =
203          {
204            categoryId:".$page['category']['id'].",
205            maps:
206            [".implode(',', $scripts)."]
207          };
208        </script>", false);
209    }
210    return($desc);
211  }
212
213
214
215  /**
216   * this function display the map on the category page
217   */
218  public function displayCategoryPageMap()
219  {
220    global $page, $prefixeTable, $template, $user, $conf;
221
222    if($page['section']=='categories' or $page['section']=='tags')
223    {
224      if(isset($page['category']))
225      {
226        $nb=$this->prepareCategoryMap($page['category']['id'], null);
227      }
228      else
229      {
230        $nb=$this->prepareCategoryMap(0, null);
231      }
232
233      if(count($this->maps)>0)
234      {
235        $scripts=array();
236
237        if($nb>0 or $this->forceDisplay>0)
238        {
239          /*
240           * prepare js script for each map
241           */
242
243          foreach($this->maps as $keyMap => $map)
244          {
245            if($nb>0 or
246               $map['forceDisplay']=='y' and ($map['kmlFileUrl']!='' or $map['kmlFileId']!=0)
247              )
248            {
249              $scripts[]="
250              {
251                id:'iGMapsIcon',
252                zoomLevel:".$map['zoomLevel'].",
253                markerImg:'".$map['marker']."',
254                mapType:'".$map['mapType']."',
255                mapTypeControl:'".$map['mapTypeControl']."',
256                navigationControl:'".$map['navigationControl']."',
257                scaleControl:'".$map['scaleControl']."',
258                streetViewControl:'".$map['streetViewControl']."',
259                kmlFileUrl:'".$map['kmlFileUrl']."',
260                displayType:'".$map['displayType']."',
261                sizeMode:'".$map['sizeMode']."',
262                title:'".addslashes( ($map['title']=='')?l10n('gmaps_geolocation'):$map['title']  )."',
263                markers:[],
264                fitToBounds:true,
265                zoomLevelMaxActivated:".($map['zoomLevelMaxActivated']=='y'?'true':'false')."
266              }";
267
268              preg_match('/^i(\d+)x(\d+).*/i', basename($map['icon']), $result);
269              $this->category['icon']['iconStyle']=$map['iconStyle'];
270              $this->category['icon']['file']=$map['icon'];
271              $this->category['icon']['width']=isset($result[1])?$result[1]:-1;
272              $this->category['icon']['height']=isset($result[2])?$result[2]:-1;
273            }
274          }
275
276          $template->assign('maps', $this->maps);
277          $template->set_filename('gmapsCatMap',
278                      dirname($this->getFileLocation()).'/templates/gmaps_category.tpl');
279          $template->append('footer_elements', $template->parse('gmapsCatMap', true), false);
280
281          if(is_array($this->category['icon']))
282          {
283            $template->assign('mapIcon', $this->category['icon']);
284            $template->set_filename('gmapsIconButton',
285                        dirname($this->getFileLocation()).'/templates/gmaps_category_iconbutton.tpl');
286            $template->concat('PLUGIN_INDEX_ACTIONS', $template->parse('gmapsIconButton', true), false);
287            $template->assign('mapIcon');
288          }
289
290          $template->append('head_elements',
291"<script type=\"text/javascript\">
292var gmaps =
293  {
294    geolocated:".($nb>0?'true':'false').",
295    forceDisplay:".($nb==0?'true':'false').",
296    lang:{
297      boundmap:'".l10n('gmaps_i_boundmap')."',
298      boundkml:'".l10n('gmaps_i_boundkml')."',
299      loading:'".l10n('gmaps_loading')."'
300    },
301    requestId:'',
302    categoryId:".$this->category['id'].",
303    bounds:
304      {
305        north:".$this->category['bounds']['N'].",
306        south:".$this->category['bounds']['S'].",
307        east:".$this->category['bounds']['E'].",
308        west:".$this->category['bounds']['W']."
309      },
310    maps:
311    [".implode(',', $scripts)."],
312    popupAutomaticSize:".$this->config['popupAutomaticSize']."
313  };
314</script>", false);
315
316        }
317
318      }
319    }
320  }
321
322
323  /**
324   * this function prepare data ($this->category var) for a category map
325   *  $this->maps must be initialized
326   *
327   * if a map id is given, datas are prepared for the given map otherwise maps
328   * are automatically searched from the current category
329   *
330   * @param Integer $catId : category id
331   * @param Integer $mapId : mapId if already know ; otherwise null
332   * @return Integer : number
333   */
334  private function prepareCategoryMap($catId, $mapId=null)
335  {
336    global $page, $prefixeTable, $template, $user, $conf;
337
338    if($catId>0)
339    {
340      $this->category['id']=$catId;
341
342      if($mapId!=null)
343      {
344        $this->buildMapList($mapId, 'C', self::ID_MODE_MAP);
345      }
346      else
347      {
348        $this->buildMapList($catId, 'C', self::ID_MODE_CATEGORY);
349      }
350
351      // check if there is picture with gps tag in the selected category
352      $sql="SELECT paut.tagId, MAX(CAST(pait.value AS DECIMAL(20,17))) AS maxValue, MIN(CAST(pait.value AS DECIMAL(20,17))) AS minValue
353            FROM (((".USER_CACHE_CATEGORIES_TABLE." pucc
354              LEFT JOIN ".CATEGORIES_TABLE." pct ON pucc.cat_id = pct.id)
355              LEFT JOIN ".IMAGE_CATEGORY_TABLE." pic ON pic.category_id = pucc.cat_id)
356              LEFT JOIN ".$prefixeTable."amd_images_tags pait ON pait.imageId = pic.image_id)
357              LEFT JOIN ".$prefixeTable."amd_used_tags paut ON pait.numId = paut.numId
358            WHERE pucc.user_id = '".$user['id']."'
359             AND (paut.tagId = 'magic.GPS.LatitudeNum' OR paut.tagId = 'magic.GPS.LongitudeNum')
360             AND pic.image_id IS NOT NULL
361             AND FIND_IN_SET(".$catId.", pct.uppercats)!=0
362             GROUP BY paut.tagId";
363    }
364    elseif($catId==self::CAT_ID_TAGS and isset($page['items']))
365    {
366      if(count($page['items'])==0) return(false);
367      // 'tags'
368      $sql="SELECT paut.tagId, MAX(CAST(pait.value AS DECIMAL(20,17))) AS maxValue, MIN(CAST(pait.value AS DECIMAL(20,17))) AS minValue
369            FROM ".$prefixeTable."amd_images_tags pait
370                  LEFT JOIN ".$prefixeTable."amd_used_tags paut ON pait.numId = paut.numId
371            WHERE (paut.tagId = 'magic.GPS.LatitudeNum' OR paut.tagId = 'magic.GPS.LongitudeNum')
372             AND pait.imageId IN (".implode(',', $page['items']).")
373             GROUP BY paut.tagId";
374      $this->category['id']=0;
375      $this->buildMapList(0, 'C', self::ID_MODE_CATEGORY);
376    }
377    elseif($catId==self::CAT_ID_HOME)
378    {
379      // 'home'
380      $this->category['id']=0;
381      $this->buildMapList(0, 'C', self::ID_MODE_CATEGORY);
382      // check if there is picture with gps tag in the selected category
383      $sql="SELECT paut.tagId, MAX(CAST(pait.value AS DECIMAL(20,17))) AS maxValue, MIN(CAST(pait.value AS DECIMAL(20,17))) AS minValue
384            FROM (((".USER_CACHE_CATEGORIES_TABLE." pucc
385              LEFT JOIN ".CATEGORIES_TABLE." pct ON pucc.cat_id = pct.id)
386              LEFT JOIN ".IMAGE_CATEGORY_TABLE." pic ON pic.category_id = pucc.cat_id)
387              LEFT JOIN ".$prefixeTable."amd_images_tags pait ON pait.imageId = pic.image_id)
388              LEFT JOIN ".$prefixeTable."amd_used_tags paut ON pait.numId = paut.numId
389            WHERE pucc.user_id = '".$user['id']."'
390             AND (paut.tagId = 'magic.GPS.LatitudeNum' OR paut.tagId = 'magic.GPS.LongitudeNum')
391             AND pic.image_id IS NOT NULL
392             GROUP BY paut.tagId";
393    }
394    else
395    {
396      return(0);
397    }
398
399    $nb=0;
400    if(count($this->maps)>0)
401    {
402      $result=pwg_query($sql);
403      if($result)
404      {
405        while($row=pwg_db_fetch_assoc($result))
406        {
407          switch($row['tagId'])
408          {
409            case 'magic.GPS.LatitudeNum':
410              $this->category['bounds']['N']=$row['maxValue'];
411              $this->category['bounds']['S']=$row['minValue'];
412              break;
413            case 'magic.GPS.LongitudeNum':
414              $this->category['bounds']['E']=$row['maxValue'];
415              $this->category['bounds']['W']=$row['minValue'];
416              break;
417          }
418          $nb++;
419        }
420      }
421    }
422    return($nb);
423  }
424
425
426  /**
427   * this function display the map on the picture page
428   *
429   * the 'amd_jpegMD_loaded' event is triggered before the 'loc_begin_picture'
430   * event so, when this function is called the $this->picture var was already
431   * initialized
432   */
433  public function displayPicturePageMap()
434  {
435    global $page, $template;
436
437    if($this->picture['geolocated']==false and $this->picture['forceDisplay']==false) return(false);
438    if(isset($this->picture['content']['MP']) and count($this->picture['content']['MP'])>0)
439    {
440      // there is maps in meta display mode
441      $template->set_filename('gmapsMeta',
442                  dirname($this->getFileLocation()).'/templates/gmaps_picture_meta.tpl');
443      $template->assign('maps', $this->picture['content']['MP']);
444
445      $metaTitle='';
446      foreach($this->picture['content']['MP'] as $map)
447      {
448        if($metaTitle=='') $metaTitle=$map['title'];
449      }
450
451      $metadata=array
452        (
453          'TITLE' => ($metaTitle=='')?l10n('gmaps_geolocation'):$metaTitle,
454          'lines' =>
455            array(
456              /* <!--rawContent-->  is a trick to display raw data in tabs
457               * for the gally template
458               *
459               * on the default template, the displayed content is done
460               * normally
461               */
462              '<!--rawContent-->' => $template->parse('gmapsMeta', true)
463            )
464        );
465      $template->append('metadata', $metadata, false);
466    }
467
468    if(isset($this->picture['content']['IP']) and count($this->picture['content']['IP'])>0)
469    {
470      // there is maps in icon display mode
471      $template->assign('map', $this->picture['content']['IP'][0]);
472      $template->assign('mapIcon', $this->picture['icon']);
473
474      $template->set_filename('gmapsIconMap',
475                  dirname($this->getFileLocation()).'/templates/gmaps_picture_icon.tpl');
476      $template->append('footer_elements', $template->parse('gmapsIconMap', true), false);
477
478      $template->set_filename('gmapsIconButton',
479                  dirname($this->getFileLocation()).'/templates/gmaps_picture_iconbutton.tpl');
480      $template->concat('PLUGIN_PICTURE_ACTIONS',  $template->parse('gmapsIconButton', true), false);
481    }
482
483    if(count($this->picture['properties'])>0)
484    {
485      $template->append('head_elements',
486"<script type=\"text/javascript\">
487  var gmaps =
488    {
489      geolocated:".($this->picture['geolocated']?'true':'false').",
490      forceDisplay:".($this->picture['forceDisplay']?'true':'false').",
491      lang:{
492        centermap:'".l10n('gmaps_i_centermap')."',
493        boundkml:'".l10n('gmaps_i_boundkml')."'
494      },
495      coords:
496      {
497        latitude:'".$this->picture['coords']['lat']."',
498        longitude:'".$this->picture['coords']['lng']."'
499      },
500      maps:
501      [".implode(',', $this->picture['properties'])."],
502      popupAutomaticSize:".$this->config['popupAutomaticSize']."
503    };
504</script>", false);
505    }
506  }
507
508
509
510
511  /**
512   * prepare the maps for the picture page
513   *
514   * this function is called when the plugin AdvancedMetadata has finished to
515   * read the metadata ; if picture is not geolocated, there is no map to display
516   *
517   * @param JpegMetadata $jpegMD : a JpegMetadata object
518   */
519  public function preparePictureMaps($jpegMD)
520  {
521    global $template, $page, $user;
522
523    $isGeolocated=true;
524
525    if(is_null($jpegMD->getTag('magic.GPS.LatitudeNum')) or
526       is_null($jpegMD->getTag('magic.GPS.LongitudeNum'))) $isGeolocated=false;
527
528
529    if(isset($page['category']))
530    {
531      $this->buildMapList($page['category']['id'], 'P', self::ID_MODE_CATEGORY);
532    }
533    else
534    {
535      $sql="SELECT GROUP_CONCAT(pict.category_id)
536            FROM ".IMAGE_CATEGORY_TABLE." pict
537            WHERE pict.image_id=".$page['image_id'];
538      if($user['forbidden_categories']!='') $sql.=" AND pict.category_id NOT IN (".$user['forbidden_categories'].")";
539
540      $result=pwg_query($sql);
541      if($result)
542      {
543        while($row=pwg_db_fetch_row($result))
544        {
545          $cats=explode(',', $row[0]);
546        }
547      }
548
549      $cats[]=0;
550      $i=0;
551      while(count($this->maps)==0 and $i<count($cats))
552      {
553        $this->buildMapList($cats[$i], 'P', self::ID_MODE_CATEGORY);
554        $i++;
555      }
556    }
557
558    if($this->forceDisplay==0 and !$isGeolocated) return(false);
559
560    $this->picture['geolocated']=$isGeolocated;
561    $this->picture['forceDisplay']=!$isGeolocated;
562    if($isGeolocated)
563    {
564      $this->picture['coords']['lat']=$jpegMD->getTag('magic.GPS.LatitudeNum')->getValue();
565      $this->picture['coords']['lng']=$jpegMD->getTag('magic.GPS.LongitudeNum')->getValue();
566    }
567
568
569    foreach($this->maps as $map)
570    {
571      if($isGeolocated or
572         $map['forceDisplay']=='y' and ($map['kmlFileUrl']!='' or $map['kmlFileId']!=0)
573        )
574      {
575        if($map['displayType']=='IP')
576        {
577          preg_match('/^i(\d+)x(\d+).*/i', basename($map['icon']), $result);
578          $this->picture['icon']=array(
579            'iconStyle' => $map['iconStyle'],
580            'file' => $map['icon'],
581            'width' => isset($result[1])?$result[1]:-1,
582            'height' => isset($result[2])?$result[2]:-1
583          );
584        }
585
586
587        $this->picture['content'][$map['displayType']][]=array(
588          'id' => $map['id'],
589          'width' => $map['width'],
590          'height' => $map['height'],
591          'style' => $map['style'],
592          'displayType' => $map['displayType'],
593          'title' => $map['title'],
594        );
595
596        $this->picture['properties'][]="
597        {
598          id:'iGMaps".(($map['displayType']=='IP')?'Icon':$map['id'])."',
599          zoomLevel:".$map['zoomLevel'].",
600          markerImg:'".$map['marker']."',
601          mapType:'".$map['mapType']."',
602          mapTypeControl:'".$map['mapTypeControl']."',
603          navigationControl:'".$map['navigationControl']."',
604          scaleControl:'".$map['scaleControl']."',
605          streetViewControl:'".$map['streetViewControl']."',
606          kmlFileUrl:'".$map['kmlFileUrl']."',
607          displayType:'".$map['displayType']."',
608          sizeMode:'".$map['sizeMode']."',
609          title:'".addslashes( ($map['title']=='')?l10n('gmaps_geolocation'):$map['title']  )."'
610        }";
611      }
612    }
613  }
614
615
616
617
618} //class
619
620?>
Note: See TracBrowser for help on using the repository browser.