<?php # $Id: serendipity_plugin_geotag.php,v 1.14 2008/03/14 08:50:38 garvinhicking Exp $

// 20050923 Zoran Kovacevic (http://www.kovacevic.nl/blog).
// The plugin is a shameless copy from Rob Antonishen (http://ffaat.pointclark.net/).
// The GMap javascript code is a shameless copy from Mikel Maron (http://brainoff.com/gmaps/rss.html).

// Wishlist
// - generate KML file to provide a fly-over in Google Earth
//   http://www.keyhole.com/kml/kml_doc.html
//   or use the Network Links option ..
// - link to larger google map


if (IN_serendipity !== true) {
    die ("Don't hack!");
}

// Probe for a language include with constants. Still include defines later on, if some constants were missing
$probelang = dirname(__FILE__) . '/' . $serendipity['charset'] . 'lang_' . $serendipity['lang'] . '.inc.php';
if (file_exists($probelang)) {
    include $probelang;
}

include_once dirname(__FILE__) . '/lang_en.inc.php';

class serendipity_plugin_geotag extends serendipity_plugin {

    function introspect(&$propbag) {
        $propbag->add('name',        PLUGIN_GEOTAG_GMAP_NAME);
        $propbag->add('description', PLUGIN_GEOTAG_GMAP_NAME_DESC);
        $propbag->add('author',      "Zoran Kovacevic");
        $propbag->add('stackable',   false);
        $propbag->add('version',     '0.9');
        $propbag->add('configuration', array('title','key','width','height','longitude','latitude','zoom','type','rss_url','geodata_source','category'));
        $propbag->add('requirements',  array(
            'serendipity' => '0.9',
            'smarty'      => '2.6.7',
            'php'         => '4.1.0'
        ));
        $propbag->add('groups',      array('FRONTEND_EXTERNAL_SERVICES'));
    }

    function introspect_config_item($name, &$propbag) {
      global $serendipity;
        switch($name) {
            case 'title':
                $propbag->add('type',        'string');
                $propbag->add('name',        PLUGIN_GEOTAG_GMAP_TITLE);
                $propbag->add('description', PLUGIN_GEOTAG_GMAP_TITLE_DESC);
                $propbag->add('default',     PLUGIN_GEOTAG_GMAP_TITLE_DEFAULT);
                break;

            case 'key':
                $propbag->add('type',        'string');
                $propbag->add('name',        PLUGIN_GEOTAG_GMAP_KEY);
                $propbag->add('description', PLUGIN_GEOTAG_GMAP_KEY_DESC.' ('.$serendipity['baseURL'].')');
                $propbag->add('default',     'XXXYYYZZZ');
                break;

            case 'width':
                $propbag->add('type',        'string');
                $propbag->add('name',        PLUGIN_GEOTAG_GMAP_WIDTH);
                $propbag->add('description', PLUGIN_GEOTAG_GMAP_WIDTH_DESC);
                $propbag->add('default',     220);
                break;

            case 'height':
                $propbag->add('type',        'string');
                $propbag->add('name',        PLUGIN_GEOTAG_GMAP_HEIGHT);
                $propbag->add('description', PLUGIN_GEOTAG_GMAP_HEIGHT_DESC);
                $propbag->add('default',     150);
                break;

            case 'longitude':
                $propbag->add('type',        'string');
                $propbag->add('name',        PLUGIN_GEOTAG_GMAP_LONGITUDE);
                $propbag->add('description', PLUGIN_GEOTAG_GMAP_LONGITUDE_DESC);
                $propbag->add('default',     0);
                break;

            case 'latitude':
                $propbag->add('type',        'string');
                $propbag->add('name',        PLUGIN_GEOTAG_GMAP_LATITUDE);
                $propbag->add('description', PLUGIN_GEOTAG_GMAP_LATITUDE_DESC);
                $propbag->add('default',     0);
                break;

            case 'zoom':
                $propbag->add('type',        'string');
                $propbag->add('name',        PLUGIN_GEOTAG_GMAP_ZOOM);
                $propbag->add('description', PLUGIN_GEOTAG_GMAP_ZOOM_DESC);
                $propbag->add('default',     16);
                break;

            case 'type':
                $propbag->add('type', 		'select');
                $propbag->add('name', PLUGIN_GEOTAG_GMAP_TYPE);
                $propbag->add('description', PLUGIN_GEOTAG_GMAP_TYPE_DESC);
                $propbag->add('default', 'G_HYBRID_MAP');
                $propbag->add('select_values', array(
                    'G_SATELLITE_MAP'=>PLUGIN_GEOTAG_GMAP_SATELLITE,
                    'G_NORMAL_MAP'=>PLUGIN_GEOTAG_GMAP_MAP,
                    'G_HYBRID_MAP'=>PLUGIN_GEOTAG_GMAP_HYBRID));
                break;

            case 'rss_url':
                $propbag->add('type',        'string');
                $propbag->add('name',        PLUGIN_GEOTAG_GMAP_RSSURL);
                $propbag->add('description', PLUGIN_GEOTAG_GMAP_RSSURL_DESC.' ('.$serendipity['baseURL'].'feeds/index.rss2?all=1)');
                $propbag->add('default',     $serendipity['baseURL'].'rss.php');
                break;

            case 'geodata_source':
                $propbag->add('type',        'select');
                $propbag->add('select_values', array('database'     => PLUGIN_GEOTAG_GMAP_DATABASE,
                                                     'rss'      => 'RSS'));
                $propbag->add('name',        PLUGIN_GEOTAG_GMAP_GEODATA_SOURCE);
                $propbag->add('description', PLUGIN_GEOTAG_GMAP_GEODATA_SOURCE_DESC);
                $propbag->add('default', 'database');

                break;

            case 'category':
                $cat = serendipity_fetchCategories();
                $cat_array = array();
                $cat_array[0] = ALL_CATEGORIES;
                foreach ($cat as $c) {
                    $cat_array[$c['categoryid']] = $c['category_name'];
                }
                $propbag->add('type',        'select');
                $propbag->add('select_values', $cat_array);
                $propbag->add('name',        CATEGORY);
                $propbag->add('description', PLUGIN_GEOTAG_GMAP_CATEGORY_DESC);
                $propbag->add('default', '0');
                break;

            default:
                return false;
        }
        return true;
    }

    function generate_content(&$title) {
      global $serendipity;

      //get config vars
      $title = $this->get_config('title');
      $key = $this->get_config('key');
      $width = $this->get_config('width',220);
      $height = $this->get_config('height',150);
      $longitude = $this->get_config('longitude',0);
      $latitude = $this->get_config('latitude',0);
      $zoom = $this->get_config('zoom',17);
      $type = $this->get_config('type');
      $rss_url = $this->get_config('rss_url');
      $geodata_source = $this->get_config('geodata_source','rss');
      $category = $this->get_config('category');
      $showtext = serendipity_db_bool($this->get_config('showtext',true));

      //errorcheck config vars
      $key = trim($key);

      if (!is_numeric($width)) {
            $width = 220;
      } else {
            $width = (int)$width;
      }

      if (!is_numeric($height)) {
            $height = 150;
      } else {
            $height = (int)$height;
      }

        if (!is_numeric($longitude)) {
            $longitude = 0;
        } else {
            $longitude = (float)$longitude;
        }

        if (!is_numeric($latitude)) {
            $latitude = 0;
        } else {
            $latitude = (float)$latitude;
        }

        if (!is_numeric($zoom)) {
            $zoom = 2;
        } else {
            $zoom = min(max((int)$zoom,0),8);
        }

      $dir = $serendipity['serendipityHTTPPath'];
?>
<script src="http://maps.google.com/maps?file=api&v=2&key=<?php echo $key ?>" type="text/javascript"></script>
<div id="serendipity_geotag_gmap" style="width: <?php echo $width ?>px; height: <?php echo $height ?>px"></div>
<script type="text/javascript">
//<![CDATA[

	if (GBrowserIsCompatible()) {
		var map = new GMap2(document.getElementById("serendipity_geotag_gmap"));
		map.addControl(new GSmallMapControl());
		//map.addControl(new GMapTypeControl());
        map.setCenter(new GLatLng(<?php echo $latitude ?>, <?php echo $longitude ?>), <?php echo $zoom ?>, <?php echo $type ?>);

		// Create a "tiny" marker icon MUST BE WORLD READABLE URL. See the Google API Dics to change this
		var icon = new GIcon();

		// Wish I could figure a better way to do the next two lines.  Hope plugin dirs don't change....
		icon.image = "<?php echo $serendipity['baseURL'] ?>plugins/serendipity_event_geotag/marker_r.png";
		icon.shadow = "<?php echo $serendipity['baseURL'] ?>plugins/serendipity_event_geotag/marker_s.png";
		icon.iconSize = new GSize(10, 10);
		icon.shadowSize = new GSize(10, 10);
		icon.iconAnchor = new GPoint(5, 7);
		icon.infoWindowAnchor = new GPoint(5, 7);

<?php
        if ($geodata_source == 'database') {

            if ($category == 0) {
                $cat_query = "";
                $cat_join = "";
            } else {
                $cat_query = "AND categoryid = $category";
                $cat_join = "LEFT JOIN {$serendipity['dbPrefix']}entrycat as c ON (c.entryid = id)";
            }
            $q = "SELECT id, title, e1.value as lng, e2.value as lat, permalink
                FROM {$serendipity['dbPrefix']}entries
                LEFT JOIN {$serendipity['dbPrefix']}entryproperties as e1 ON (e1.entryid = id AND e1.property='geo_long')
                LEFT JOIN {$serendipity['dbPrefix']}entryproperties as e2 ON (e2.entryid = id AND e2.property='geo_lat')
                LEFT JOIN {$serendipity['dbPrefix']}permalinks ON (entry_id = id AND type='entry')
                $cat_join
                WHERE e1.property='geo_long' AND e2.property='geo_lat' $cat_query";
            $tt = serendipity_db_query($q);
            foreach ($tt as $i => $t) {

            $url = serendipity_archiveURL($t['id'], $t['title']);
        ?>
        		point = new GPoint(parseFloat('<?echo $t['lng'];?>'), parseFloat('<?echo $t['lat'];?>'));
        		marker<?echo $i;?> = new GMarker(point, icon);
        		GEvent.addListener(marker<?echo $i;?>, "click", function() {
        			marker<?echo $i;?>.openInfoWindowHtml('<a href=\"<?echo $url;?>\"><?echo $t['title'];?></a>');
        		});
        		map.addOverlay(marker<?echo $i;?>);

<?php
            }
        } else {
?>
    	rss_url = "<?php echo $rss_url ?>";

		function createMarker(item) {
			var title = item.getElementsByTagName("title")[0].childNodes[0].nodeValue;
			var pubDate = item.getElementsByTagName("pubDate")[0].childNodes[0].nodeValue;
			var link = item.getElementsByTagName("link")[0].childNodes[0].nodeValue;

			/* namespaces are handled by spec in moz, not in ie */
			if (navigator.userAgent.toLowerCase().indexOf("msie") < 0) {
				// Is there a geo:lat defined?
				if (item.getElementsByTagNameNS("http://www.w3.org/2003/01/geo/wgs84_pos#","lat").length>0) {
					item.getElementsByTagNameNS("http://www.w3.org/2003/01/geo/wgs84_pos#","lat")[0].normalize();
					// Is there a value for geo:lat
					if (item.getElementsByTagNameNS("http://www.w3.org/2003/01/geo/wgs84_pos#","lat")[0].hasChildNodes()) {
						// Then there probably is a geo:long too
						var lat = item.getElementsByTagNameNS("http://www.w3.org/2003/01/geo/wgs84_pos#","lat")[0].childNodes[0].nodeValue;
						var lng = item.getElementsByTagNameNS("http://www.w3.org/2003/01/geo/wgs84_pos#","long")[0].childNodes[0].nodeValue;
					}
				}
			} else {
				var lat = item.getElementsByTagName("geo:lat")[0].childNodes[0].nodeValue;
				if (lat == undefined) {
					lat = item.getElementsByTagName("icbm:lat")[0].childNodes[0].nodeValue;
				}
				var lng = item.getElementsByTagName("geo:long")[0].childNodes[0].nodeValue;
				if (lng == undefined) {
					lng = item.getElementsByTagName("icbm:long")[0].childNodes[0].nodeValue;
				}
			}

			var point = new GPoint(parseFloat(lng), parseFloat(lat));
			var marker = new GMarker(point, icon);
			var html = '<a href=\"' + link + '\">' + title + '</a>';
			GEvent.addListener(marker, "click", function() {
				marker.openInfoWindowHtml(html);
			});
			return marker;
		}

		var request = GXmlHttp.create();
		request.open("GET",rss_url,true);
		request.onreadystatechange = function() {
			if (request.readyState == 4) {
				var xmlDoc = request.responseXML;
				var items = xmlDoc.documentElement.getElementsByTagName("item");
				for (var i = 0; i < items.length; i++) {
					try {
						var marker = createMarker(items[i]);
						map.addOverlay(marker);
					} catch (e) {
					}
				}
			}
		}
		request.send(null);
<?php
}
?>
	}
//]]>
</script>
<?php

    }

}
