User:George Drummond/SpecialGoogleEarth.php
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();
}
}