You can see a prototype version of the widget by clicking here.
Template engine
I attempted this built as single piece of php but it quickly became obvious that this was not the right approach. Instead I adapted a simple template engine from my faithful O’Reilly book. This allowed me to separate the logic from the markup
function FillTemplate($inName, $inValues = array()){
$theTemplateFile = $_SERVER['DOCUMENT_ROOT'].'/templates/'.$inName;
if($theFile = fopen($theTemplateFile, 'r')){
$theTemplate = fread($theFile, filesize($theTemplateFile));
fclose($theFile);
}
$theKeys = array_keys($inValues);
foreach($theKeys as $theKey){
$theTemplate = str_replace("\{$theKey}",$inValues[$theKey],$theTemplate);
}
return $theTemplate;
}
Map Logic
Here’s the source for the Map Logic. As an attempt to make the script secure you can see I’ve used a UK Postcode Regex from Stuart Wade to validate the form input. And also mysql_real_escape_string() on any database calls.
Any security tips would be greatly appreciated
The Map Logic uses four separate templates to handle the interaction, and the error state.
<?php
//Pin counter
connectDB();
$result = mysql_query("SELECT * FROM mapPins");
$num_rows = mysql_num_rows($result);
$bindings['PINCOUNT'] = $num_rows;
//Place Pins
$pinQuery = "SELECT Latitude,Longitude FROM mapPins";
$pinArray = mysql_query($pinQuery)or die('Query failed: '.mysql_error());
$pinCode="";
while ($row = mysql_fetch_array($pinArray, MYSQL_NUM)) {;
$i++;
$pinCode .="var latlng$i = new GLatLng($row[0] ,$row[1] );";
$pinCode .="map.addOverlay(new GMarker(latlng$i));";
}
$bindings['MAPPINS'] = $pinCode;
$bindings['DESTINATION'] = $PHP_SELF;
function centerFromDB($postcode){
//Connect to the database
connectDB();
//Convert the Postcode to all uppercase
$postcode = strtoupper($postcode);
//Break the Postcode into array
$postcode = explode(' ', $postcode);
//Pull out the relevant fields from our database
$query = "SELECT Latitude,Longitude FROM postcodes WHERE Pcode= '$postcode[0]'";
$result = mysql_query($query) or die('Query failed: '.mysql_error());
return mysql_fetch_array($result, MYSQL_ASSOC);
}
if (isset($_POST['submitPostCode']) & $_POST['code']!="") {
if(eregi("^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$",mysql_real_escape_string($_POST['code']))){
$line = centerFromDB(mysql_real_escape_string($_POST['code']));
//Grab the Postcode from the form
$postcode = mysql_real_escape_string($_POST['code']);
//Uppercase
$postcode = strtoupper($postcode);
//Break the Postcode into array
$postcode = explode(' ', $postcode);
//Output Results
$bindings['INITIALCENTER'] = "var center = new GLatLng(".$line['Latitude'].", ".$line['Longitude'].");";
$bindings['OUTCODE'] = $postcode[0];
$bindings['SECONDHALF'] = $postcode[1];
$template = "map02.template";
}else{
$template = "mapError.template";
}
}elseif(isset($_POST['plotPoints'])){
$outCode = mysql_real_escape_string($_GET['outCode']);
$secondHalf = mysql_real_escape_string($_GET['secondHalf']);
$mapLat = mysql_real_escape_string($_GET['mapLat']);
$mapLng = mysql_real_escape_string($_GET['mapLng']);
$today = date("Y-m-d");
$line = centerFromDB($outCode.' '.$secondHalf);
//connect to db
connectDB();
//add point to db
mysql_query("INSERT INTO mapPins (outCode, secondHalf, Latitude, Longitude, theDate) VALUES('$outCode', '$secondHalf', '$mapLat', '$mapLng', '$today') ") or die(mysql_error());
$pinQuery = "SELECT Latitude,Longitude FROM mapPins WHERE outCode='$outCode' AND secondHalf='$secondHalf'";
$pinArray = mysql_query($pinQuery)or die('Query failed: '.mysql_error());
$pinCode="";
while ($row = mysql_fetch_array($pinArray, MYSQL_NUM)) {;
$i++;
$pinCode .="var latlng$i = new GLatLng($row[0] ,$row[1] );";
$pinCode .="map.addOverlay(new GMarker(latlng$i));";
}
//new
$bindings['CURRENTPC'] = $outCode.' '.$secondHalf;
$bindings['MAPPINS'] = $pinCode;
$bindings['NEWCENTER'] = "var center = new GLatLng(".$line['Latitude'].", ".$line['Longitude'].");";
$template = "map03.template";
}else{
$template = "map01.template";
}
echo FillTemplate($template, $bindings);
?>
Integrating script with WordPress
After developing this script I discovered that WordPress can’t run PHP in the body of a post without a plugin. Strange. So I had to put the prototype on a loose page.
Take a look at the trick I used to capture the output of a WordPress tag so I could incorporate it into Map Logic, and then my templates. In this example I captured the footer code, then bound it to a template tag.
<?php
require('./wp-blog-header.php');
ob_start();
get_footer();
$footer = ob_get_contents();
ob_end_clean();
$bindings['FOOTER'] = $footer;
?>