User:George Drummond/SpecialGoogleEarth.php
From MediaWiki.org
THIS IS AN ALPHA RELEASE.
<?php /* * Google Earth Exporter for Google Maps Extension * http://www.mediawiki.org/wiki/Extension:Google_Maps * Written for Wikipaddle.org * * Copyright (c) 2006 by George Drummond, georgedrummond@wikipaddle.org * * Expanding Google Maps Extension by Evan Miller, emmiller@gmail.com * * Version 0.1 ALPHA - 2 Feb 2007 * * ----------------------------------------------------------------------- * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/copyleft/gpl.html * ----------------------------------------------------------------------- */ if(!defined('MEDIAWIKI')) die('This is not a stand alone file ;)'); /* * * Define the defaults * */ define ('GME_DEFAULT_ICON', 'http://maps.google.com/mapfiles/kml/pal4/icon57.png'); define ('GME_ICON_PATH', 'http://maps.google.com/mapfiles/kml/pal2/'); define ('GME_POLYLINE_OPACITY', '7f'); define ('GME_POLYLINE_WIDTH', '4'); define ('GME_EXPORT_VERSION', '0.1 ALPHA'); /* * * Special page stuff * */ $wgExtensionFunctions[] = 'GoogleEarthExportSetup'; $wgExtensionCredits['specialpage'][] = array( 'name' => 'Google Earth Export', 'author' => '[http://wikipaddle.org/wiki/User:George_Drummond George Drummond]', 'version' => GME_EXPORT_VERSION, 'url' => 'http://www.mediawiki.org/wiki/Extension:Google_Maps', 'description' => 'Google earth exporter for GoogleMaps plugin' ); function GoogleEarthExportSetup( $par = '' ) { global $wgMessageCache; SpecialPage::addPage(new SpecialPage('GoogleEarthExport', '', true, 'GoogleEarthExportSpecial', true)); $titleObj = Title::makeTitle( NS_SPECIAL, 'GoogleEarthExport' ); $action = $titleObj->escapeLocalURL(); $wgMessageCache->addMessages( array( "googleearthexport" => "Google Earth Export", "ge-title" => "Google Earth Exporter for Google Maps", "ge-pagenoexist" => "=== We couldnt find the page that you requested ===", "ge-nomapfound" => "=== We couldn't find a map on the page that you requested ===", "ge-formdescription" => "To export a google map to google earth format, enter the '''page name''' into the box bellow and press export.", "ge-form" => "<form method=\"get\" action=\"$action\"><input name=\"page\" type=\"text\" /> <input name=\"export\" type=\"submit\" value=\"Export\" /></form><br />", "ge-information" => "'''This is a alpha version and is currently still being tested and developed.'''", ) ); } function GoogleEarthExportSpecial(){ global $wgRequest; $page_name = textSqlSafe( $wgRequest->getText( 'page', $par ) ); // Make input safe to put in SQL. ***THIS MIGHT BECOME A PROBLEM WITH PAGES WITH STRANGE NAMES?** if( $page_name != "" ){ $page_name = str_replace(" ", "_", $page_name); // Replace spaces in page name with "_" GoogleEarthExporter( $page_name ); } else { GoogleEarthForm(); } // If no page requested just show form } function GoogleEarthForm(){ global $wgOut; $wgOut->addWikiText( wfMsg( 'ge-formdescription') ); $wgOut->addHTML( wfMsg( 'ge-form' ) ); $wgOut->addWikiText( wfMsg( 'ge-information' ) ); } /* * * SQL Functions * */ function pageFromTitle( $title ) { return "page_namespace= '".$title->getNamespace()."' AND page_title= '".$title->getDbKey()."'" ; } function pageByName2( $name ) { $title = Title::newFromText( $name ); if( is_null( $title ) ) { return new WikiError( "Can't export invalid title" ); } else { return pageFromTitle( $title ); } } function pageByTitle( $title ) { // Not in current use return $this->dumpFrom('page_namespace=' . $title->getNamespace() . ' AND page_title=' . $this->db->addQuotes( $title->getDbKey() ) ); } function textSqlSafe( $value ){ // Make text safe to form sql query. if( get_magic_quotes_gpc() ) $value = stripslashes( $value ); if( function_exists( "mysql_real_escape_string" ) ) $value = mysql_real_escape_string( $value ); else $value = addslashes( $value ); return $value; } /* * * Pull page from database * */ function GoogleEarthExporter( $page_name ){ global $wgRequest, $wgExportAllowListContributors; global $wgExportAllowHistory; $dbr =& wfGetDB( DB_SLAVE ); $page = $dbr->tableName( 'page' ); $revision = $dbr->tableName( 'revision' ); $text = $dbr->tableName( 'text' ); $page_title = pageByName2( $page_name ); // Could this SQL could do with some cleaning up? $geSqlSelect = "SELECT page_namespace, page_title, page_id, page_latest, old_text"; $geSqlSelectFrom = " FROM $page, $revision, $text"; $geSqlWhere = " WHERE $page_title AND page_id=rev_page AND page_latest=rev_id AND rev_text_id=old_id"; $geSqlOrderby = ' ORDER BY page_id'; $sql = $geSqlSelect.$geSqlSelectFrom.$geSqlWhere.$geSqlOrderby; $res = $dbr->query( $sql ); $row = $dbr->fetchObject( $res ); if( !$row->page_title ) // If page dosen't exist pageNotExist(); elseif( isRedirect( $row->old_text ) ) // If it is a redirect handleRedirects( $row->old_text, $page_name ); else makeKml( $row->page_title, $row->old_text ); // If page exists and isnt a redirect go to makeKml } /* * * Page errors * */ function pageNotExist(){ global $wgOut; $wgOut->addWikiText( wfMsg( 'ge-pagenoexist' ) ); GoogleEarthForm(); } function isRedirect( $old_text ){ // Check if page is a redirect if(preg_match('/#REDIRECT \[\[([^<]*)\]\]/', $old_text, $new)) return true; } function handleRedirects( $old_text, $page_title ){ preg_match('/#REDIRECT \[\[([^<]*)\]\]/', $old_text, $redirect); if($page_name == $redirect[1]) echo "double redirect"; else{ $titleObj = Title::makeTitle( NS_SPECIAL, 'GoogleEarthExport' ); $url = $titleObj->escapeLocalURL(); header("Location: ".$url."?page=".$redirect[1]); } } /* * * Rendering wiki text. See hacky link fixers, know any better way feel free to change. * */ function renderWikiText( $text ){ // This code was taken from somewhere but i forgot source. global $wgOut, $wgUser, $wgTitle, $wgParser, $wgServer, $wgAllowDiffPreview, $wgEnableDiffPreviewPreference; $parserOptions = ParserOptions::newFromUser( $wgUser ); $parserOptions->setEditSection( false ); $parsed = $wgParser->parse( $text, $wgTitle, $parserOptions ); $output = str_replace('<img src="/', '<img src="'.$wgServer.'/', $parsed->mText); // Image link fix $output = str_replace('<a href="/', '<a href="'.$wgServer.'/', $output); // Url link fix return $output; } /* * * Map Making stuff * */ function mime_type( $page_title ){ $output .= header("Cache-Control: no-cache, must-revalidate"); // We dont want file to be cached. $output .= header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Expires in the past. $output .= header("Content-type: application/vnd.google-earth.kml+xml"); $output .= header('Content-Disposition: attachment; filename="'.$page_title.'.kml"'); return $output; } function xml_header( $page_title ){ global $wgServer, $wgVersion; $output = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; $output .= "<kml xmlns=\"http://earth.google.com/kml/2.1\">\n"; $output .= "<!-- Source: ".$wgServer.", Generated by Special:GoogleEarthExport -->\n"; // This might be usefull when trying to debug $output .= "<!-- Page: ".$page_title.", Mediawiki: ".$wgVersion.", Version: ".GME_EXPORT_VERSION.", Time: ".date('Y-m-d, H:i:s')." -->\n"; $output .= "<Document>\n<open>1</open>\n"; return $output; } function addMarker( $lat, $lon, $icon, $description, $marker_count ) { $output .= "<Placemark>\n"; $output .= "<name>point ".$marker_count."</name>"; $output .= "<Style><Icon><href>"; if ($icon) $output .= GME_ICON_PATH.$icon."png"; else $output .= GME_DEFAULT_ICON; $output .= "</href></Icon></Style>\n"; $output .= "<Point><coordinates>".$lon.", ".$lat.", 0</coordinates></Point>\n"; if ($description) $output .= '<description><![CDATA[<table width="333">'.$description.'</table>]]></description>'; $output .= "</Placemark>\n"; return $output; } function addPolyline( $polyline, $color ){ $output .= "<Placemark>\n<name>Polyline</name>\n<Style><LineStyle> <color>".GME_POLYLINE_OPACITY.ltrim($color, "#")."</color> <width>".GME_POLYLINE_WIDTH."</width> </LineStyle></Style><LineString><tessellate>1</tessellate><altitudeMode>clampedToGround</altitudeMode>\n"; //Might want to change this later on. $output .= "<coordinates>\n"; $output .= implode("\n", $polyline); $output .= "\n</coordinates>\n</LineString>\n</Placemark>\n"; return $output; } /* * * Map maker, taken from google maps extension * */ function makeMap( $map ) { $lines = preg_split("/[\r\n]+/", $map); $doAddMarker = false; $marker_count = 0; // Just name markers numerically for now, starting at 1 foreach($lines as $line) { if (preg_match("/^(#[0-9a-fA-F]{6})/", $line, $matches)) { //if ($wgGoogleMapsEnablePaths) { if (isset($color)) { // i.e., we were just making a path, so dump and reset $polyline $output .= addPolyline($polyline, $color); $polyline = array(); } $color = $matches[1]; //} } elseif (preg_match('/^\/([^\\\\]+)\\\\ *(.*)$/', $line, $matches)) { $tab_description = renderWikiText( $matches[2] ); $description .="<hr /><h2>".$matches[1]."</h2>".$tab_description; $doAddMarker = true; // we want a marker there if it has tabs } elseif (preg_match("/^(?:\(([.a-zA-Z0-9_-]*?)\) *)?([^,]+), *([^ ,]+)(?:, (.+))?/", $line, $matches)) { if ($doAddMarker) { // first create the previous marker, now that we have all the tab/caption info $output .= addMarker($lat, $lon, $icon, $description, $marker_count); $doAddMarker = false; } $icon = $matches[1]; $lat = $matches[2]; $lon = $matches[3]; $description = addslashes(renderWikiText($matches[4])); // This parse function above lets us insert wiki markup into the map markers. //} if (is_numeric($lat) && is_numeric($lon)) { if ($icon || $caption || !isset($color)) { // we don't actually put down a marker for anonymous points along a path $doAddMarker = true; $marker_count++; } // If we're making a path, record the location and move on. if (isset($color)) { $polyline[] = "{$lon}, {$lat}"; } } } } if( isset($color) ) // Close polylines $output .= addPolyline( $polyline, $color ); if ($doAddMarker) { // we've been waiting $output .= addMarker($lat, $lon, $icon, $description, $marker_count); } return $output; } /* * * KML maker * */ function makeKml( $page_title, $old_text ){ global $wgOut, $wgRequest; if(preg_match("/(<googlemap[^>]*>)([^<]*)(<\/googlemap>)/", $old_text)){ preg_match_all("/<googlemap([^>]+)>*([^<]+)<\/googlemap>/", $old_text, $source); $maps = $source[2]; $maps_attributes = $source[1]; $map_number = $wgRequest->getText( 'map_number', $par ); $output = ""; $output .= xml_header( $page_title ); if( $map_number != "" && is_numeric($map_number) && $map_number <= count($maps) ) { $output .= makeMap( $maps["$map_number"] ); } elseif( !$map_number ){ // if no map is requested then just display all $i = 0; // Maps dont have any title at the moment. Lets just label them numerically for now, starting at 1. foreach($maps as $map){ preg_match("#name=\"(.*?)\"#s",$maps_attributes[$i], $title_tag); if( $title_tag[0] = "" || !$title_tag[0] ){ $title = "Map ".($i+1); } else { $title = $title_tag[1]; } $output .= "<Folder>\n<name><![CDATA[".$title."]]></name>\n"; $output .= makeMap( $map ); $output .= "</Folder>"; $i++; } } else {// Map number isnt found on this page. $wgOut->setPageTitle( wfMsg( 'ge-title' ) ); // If no map is found on page $wgOut->addWikiText( "=== We couldn't find that map number on the page that you requested ===" ); GoogleEarthForm(); return true; } $output .= "</Document>\n"; $output .= "</kml>"; // Output mime type now $wgOut->disable(); mime_type( $page_title ); echo $output; } else { $wgOut->setPageTitle( wfMsg( 'ge-title' ) ); // If no map is found on page $wgOut->addWikiText( wfMsg( 'ge-nomapfound' ) ); GoogleEarthForm(); } }