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

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

add possibility to add maps in descriptions
feature:1937

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