This week we’ll be extending WordPress by adding a custom shortcode. This shortcode will allow us to add a Google Map to a post using a simple piece of text in a post or page. Shortcodes are a quick and easy way to add functionality to a post in WordPress. They look something like this:
[ gallery ids="1,2,3,4"]
We’ll also using PHP based Object Orientated Programming (OOP) to create our shortcode. We’ll create a basic class, that has some static functions with in. We’ll be using static methods because we want some level of state to be kept.
Getting started
Our basic class will be pretty simple, it needs to register the shortcode and provide functions to render the shortcode and add the API JavaScript file.
class GoogleMap_Shortcode {
static function init() {
}
static function render_shortcode($atts) {
}
static function enqueue_map_javascript() {
}
}
To create our shortcode we’ll need to first register it and then define it how it works and what HTML it creates. We’ll also need to figure out a way to add in the Google Maps API JavaScript. To add a shortcode to WordPress we use the add_shortcode function. This function takes 2 parameters, the name of the shortcode and the function to call when we want to render the shortcode. We’re going to call our shortcode “map” and our render function “render_shortcode”. Since we’re using a class, we’re going to take advantage of the PHP Magic Constant “__CLASS__”, this will maintain a reference to our class and ensure our function can be called.
add_shortcode('map', array(__CLASS__, 'render_shortcode'));
The add_shortcode needs to be called only once, so we’re going to call it from our “init” function, and then immediately after our class definition call it.
class GoogleMap_Shortcode {
static function init() {
wp_enqueue_script( 'jquery' );
add_shortcode('map', array(__CLASS__, 'render_shortcode'));
}
static function render_shortcode($atts) {
}
static function enqueue_map_javascript() {
}
}
GoogleMap_Shortcode::init();
Now we have to start getting our shortcode to render. First up we need to define the attributes of the shortcode. One of these will be the Google Maps API key, you can sign up for one here, we’ll also want to be able to specify map related settings like the map type, zoom and naturally the co-ordinates we want to center on. We can define their default values using the shortcode_atts and extract functions.
extract( shortcode_atts( array(
'api_key' => false,
'id' => 'map-canvas-1',
'class' => '',
'zoom' => '18',
'coords' => '53.339381, -6.260405',
'type' => 'roadmap',
'width' => '480px',
'height' => '480px'
), $atts ) );
Here you can see I’m defaulting all the possible attributes, this means the user doesn’t have to specify them all in the shortcode if they don’t need to. The API key is needed for all instances of the shortcode, but we can cache the key from the 1st call so it does not need to be specified on all shortcodes on a page. If we declare a static variable inside the class and use it where ever we are in the class it will only need to be set once.
class GoogleMap_Shortcode {
static $api_key = false;
static function init() {
wp_enqueue_script( 'jquery' );
add_shortcode('map', array(__CLASS__, 'render_shortcode'));
}
static function render_shortcode($atts) {
extract( shortcode_atts( array(
'api_key' => false,
'id' => 'map-canvas-1',
'class' => '',
'zoom' => '18',
'coords' => '53.339381, -6.260405',
'type' => 'roadmap',
'width' => '480px',
'height' => '480px'
), $atts ) );
if(!self::$api_key && $api_key) {
self::$api_key = $api_key;
}
}
static function enqueue_map_javascript() {
}
}
GoogleMap_Shortcode::init();
There are four default map types, to simplify the specification of which one we want to use we can use a switch statement
$map_type_id = "google.maps.MapTypeId.ROADMAP";
switch ($type) {
case "roadmap":
$map_type_id = "google.maps.MapTypeId.ROADMAP";
break;
case "satellite":
$map_type_id = "google.maps.MapTypeId.SATELLITE";
break;
case "hybrid":
$map_type_id = "google.maps.MapTypeId.HYBRID";
break;
case "terrain":
$map_type_id = "google.maps.MapTypeId.TERRAIN";
break;
}
Now we have everything we need to actually render our shortcode. First we’ll need to specify the div we are going to wrap the map in, and then we’ll need some JavaScript to initialize the map.
class GoogleMap_Shortcode {
static $api_key = false;
static function init() {
wp_enqueue_script( 'jquery' );
add_shortcode('map', array(__CLASS__, 'render_shortcode'));
}
static function render_shortcode($atts) {
extract( shortcode_atts( array(
'api_key' => false,
'id' => 'map-canvas-1',
'class' => '',
'zoom' => '18',
'coords' => '53.339381, -6.260405',
'type' => 'roadmap',
'width' => '480px',
'height' => '480px'
), $atts ) );
if(!self::$api_key && $api_key) {
self::$api_key = $api_key;
}
$return = "";
$map_type_id = "google.maps.MapTypeId.ROADMAP";
switch ($type) {
case "roadmap":
$map_type_id = "google.maps.MapTypeId.ROADMAP";
break;
case "satellite":
$map_type_id = "google.maps.MapTypeId.SATELLITE";
break;
case "hybrid":
$map_type_id = "google.maps.MapTypeId.HYBRID";
break;
case "terrain":
$map_type_id = "google.maps.MapTypeId.TERRAIN";
break;
}
if(self::$api_key) {
$return = '<div id="'.$id.'" class="map-canvas '.$class.'" style="width:'.$width.';height:'.$height.';" ></div>';
$return .= '<script type="text/javascript">';
$return .= 'jQuery(document).on("ready", function(){ ';
$return .= 'var options = { center: new google.maps.LatLng('.$coords.'),';
$return .= 'zoom: ' . $zoom . ', mapTypeId: ' . $map_type_id . ' };';
$return .= 'var map = new google.maps.Map(document.getElementById("'.$id.'"), options);';
$return .= 'var marker = new google.maps.Marker({ position: new google.maps.LatLng('.$coords.'), map: map });';
$return .= '});</script>';
} else {
$return = "<div><p>Please specify your Google Maps API key</p></div>";
}
return $return;
}
static function enqueue_map_javascript() {
}
}
GoogleMap_Shortcode::init();
I’ve also added a check here to see if the api key is set, and if not display a message to that effect. Next up we need to include the actual Map API JavaScript, to do that we’re going to use the wp_enqueue_script function. Because we’re checking that the api key is we are by default preventing the JavaScript from being loaded when the shortcode is not being used.
static function enqueue_map_javascript() {
if ( ! self::$api_key )
return;
wp_enqueue_script( 'map-js',
"https://maps.googleapis.com/maps/api/js?key=" . self::$api_key . "&sensor=true"
);
}
To make sure this script is included in the right place, we’re going to add an action to the wp_footer hook. We’ll add this to our init function
add_action('wp_footer', array(__CLASS__, 'enqueue_map_javascript'));
And that’s it, add this to your functions.php or use an include/require and you’ll be able to add Google Maps to your posts. To actually add it to a post, you can use the following:
[map api_key="INSERT YOUR API KEY"]
[map api_key="INSERT YOUR API KEY" id="map-2" coords="52.339381, -4.260405"]
[map api_key="INSERT YOUR API KEY" id="map-2" coords="52.339381, -4.260405" zoom="5" type="satellite"]
It was pointed out to me that I forgot to include the pointer for the map. I’ve updated the sample above and the download. This is the new line to add a marker.
$return .= 'var marker = new google.maps.Marker({ position: new google.maps.LatLng('.$coords.'), map: map });';