Gps Tracker WordPress Plugin Tutorial 1 – Map

I’ve finally begun building the Gps Tracker WordPress plugin and it is a lot of fun. The way that I’m doing this is by breaking down the functionality into separate plugins and then adding the plugins together at various stages in the build process. It’s kind of like continuous integration, for a one person team, kind of… I think it’s a really good idea to create small plugins that do just one thing, especially when you are just starting off in WordPress plugin development (like I am). I’ve already built the first three plugins, which is the map plugin, the route plugin and the database plugin. I’m currently working on the fourth plugin which is the updater plugin. The first three plugins are standalone plugins but the fourth requires two of the previous plugins (database and route) and therefor will be the first integration point.

If you are totally new to wordpress plugin development, I would like to suggest a couple of pages that will help you come up to speed. The first is “Writing a Plugin” on wordpress.org and the second is Tom McFarlin’s excellent set of tutorials.

Before we dive into the first plugin, I just want to give a brief overview of where I’m going with this, the big picture. I’m going to create a plugin that allows users to track a cell phone, store routes in a database and display the route in real time or allow the user to display previous routes using different map providers (currently set to Google, Bing and OpenStreetMaps). This is my first attempt at building a serious wordpress plugin so it will be as much a learning experience for me as it will be for you. If there are any experienced wordpress plugin developers out there who wish to correct any problems that they see, please feel free to open an issue in my github repo or comment here on any of the plugin tutorials and thank you!

Ok, on to the first tutorial. If you’d like to follow along with the code, you can download it here from github. If you have wordpress installed, you can copy the gps-tracker-map directory into your wordpress plugin directory. Then go to any page or post and add the following shortcode:

[gps-tracker-map]

and you should see a map just like this:

[gps-tracker-map]

In addition to building the map plugin, I will be setting up the structure for all future plugins in this tutorial. The first thing you see in gps-tracker-map.php is that it’s class based and that there is __construct function. This is the constructor for the class and it is always called once when the class is instantiated. Let’s take a look at it:

public function __construct() {
    register_activation_hook(__FILE__, array($this, 'activate'));
    register_deactivation_hook(__FILE__, array($this, 'deactivate'));
    register_uninstall_hook(__FILE__, array($this, 'uninstall'));
        
    // to test this plugin, add this shortcode to any page or post: [gps-tracker-map]  
    add_shortcode('gps-tracker-map', array($this,'map_shortcode'));
            
    add_action('admin_init', array($this, 'admin_init'));
    add_action('admin_menu', array($this, 'admin_menu'));
    add_filter('plugin_action_links_' . plugin_basename(__FILE__), array('Gps_Tracker_Map', 'add_action_links'));
}

The first three lines are hooks. A hook allows you to add custom code to wordpress when certain events happen. As you can see, the three events here are when you activate a plugin, deactivate it or uninstall it. When we register the activation hook, for instance, it will then call the activate function on line 29 of this plugin.

public static function activate() {
    // placeholder for future plugins
}

You’ll notice that the method doesn’t do anything yet but I am adding it now to create the structure of the plugin. The same applies to the two other hooks.

The next thing you’ll see in the constructor above is the add_shortcode function. This is another hook. When you add a shortcode to a page or a post, wordpress will replace the shortcode with code that you create in your plugin. In this case, it will call the function called map_shortcode and display and execute all of the code in that function. We’ll go into detail of what that function does in a minute. Let’s finish up looking at the constructor first. In the next line, there is an add_action function that has an admin_init hook. This event occurs when a user goes to the admin settings page of the plugin and is the first thing that is run. What happens here is that the admin_init function on line 56 of this plugin is called:

public function admin_init() {
    wp_register_style('leaflet_admin_stylesheet', plugins_url('style.css', __FILE__));
}

and what it’s doing is registering a css stylesheet for the admin settings page. The style sheet will be added later when we call wp_enqueue_style. Next we have an add_action for the admin_menu hook. This allows us to create a menu item within wordpress so that you can get to the Gps Tracker plugin settings page.

public function admin_menu() {
    add_menu_page("Gps Tracker", "Gps Tracker", 'manage_options', "gps-tracker", array(&$this, "settings_page"), plugins_url('images/satellite.png', __FILE__), 100);
}

It also puts a little satellite image in the menu so that we can be stylin’ like the rest of the WordPress menu items. You’ll notice the settings_page function name there. When a user clicks on the Settings menu link, that function will then be called.

public function settings_page() {
    wp_enqueue_style('leaflet_admin_stylesheet');
    include 'admin/admin.php';
}

Here we add the admin stylesheet to the admin settings page and then output the settings page with admin.php. Admin.php simply spits out a little bit of html at the moment. We’ll add more later.

<div class="wrap">
    <h3>Gps Tracker Settings</h3>
    <div class="wrap">
        <p>To test this plugin, add this shortcode to any page or post:</p> 
        <p>[gps-tracker-map]</p>    
    </div>
</div>

Finally, we have reached the last line of the constructor! I’ll put it here so that you don’t have to scroll up again:

add_filter('plugin_action_links_' . plugin_basename(__FILE__), array('Gps_Tracker_Map', 'add_action_links'));

You’ll notice that this is a little different than the others. Here we have an add_filter hook. The difference between add_action and add_filter is that add_action hooks are called during wordpress events like when you activate a plugin or when you publish a post, etc. add_filter hooks allow you to pass data through functions. This might occur when you are adding data to the database or sending data to the browser, for instance. Filters change data while actions allow you to do something. So what this filter does is it calls the plugin_action_links hook which allows you to add a link to the plugins page. It does this by calling this function in the plugin:

function add_action_links($links) {
    $links[] = '<a href="' . admin_url('admin.php?page=gps-tracker') . '">Settings</a>';
    return $links;
}

You’ll notice that it returns an array of links which is a clue that its being called by a filter since filters change content. And here is what it does, it adds a Settings link to the plugin page:

Settings Link on WordPress Plugin page

You may be wondering why I went to so much trouble to show you something that seems so trivial. I just wanted to point this out because so many wordpress plugins fail to include this link in their plugins and many times I have a really hard time finding their darn Settings page! I’m sure you’ve experienced that too.

Now we have finally gotten through the constructor and explained most of the code in the plugin and how the plugin is structured. Now we’ll take a look at the final function in the plugin, map_shortcode.

This function is what actually outputs the html, javascript and links to stylesheets and javascript files that we need to display the map. Most of it is fairly understandable if you have knowledge of html and javascript. It starts off with a couple of different function, wp_enqueue_script and wp_enqueue_style. This just outputs the link tag and the script tag to get our css and javascript files. This can include external files from other websites like getting the remote Google maps javascript file:

wp_enqueue_script('google_maps', '//maps.google.com/maps/api/js?v=3&sensor=false&libraries=adsense', false);

or the local leaflet css file:

wp_enqueue_style('leaflet_styles', plugins_url('javascript/leaflet-0.7.3/leaflet.css', __FILE__), false);

Remember that this function replaces the shortcode that you put into a page or a post with html and javascript, so next we create a big html string that contains both. First a div is created for our map (yes, with the style hardcoded into the div tag, we’ll change that later) and then a jQuery function is called that creates the map. Check out the leaflet quick start guide to get a better idea of what’s going on but I’ll briefly step through the code here. First we create a leaflet map object and center it to Seattle:

map = new L.map("map").setView([47.61,-122.33], 12);

You’ll notice that a lot of the code in this section looks similar to the Google maps API but with one big difference. It allows you to create and use different map providers, not only Google, and that is a very big win. There are many parts of the world where other map providers such as Bing or OpenStreetMaps has much better coverage than Google and in addition there are lots of very interesting map providers that you may have never seen before. Next we create our three layers like, for instance, the OpenStreetMap layer:

var openStreetMapsLayer = new L.TileLayer(
"//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", 
{attribution: "&copy;2014 <a href=\'http://openstreetmap.org\'>OpenStreetMap</a> contributors", maxZoom: 18}
).addTo(map);

There is a known error in leaflet that makes the map freeze up under certain conditions when the zoom buttons are clicked. They have provided a simple workaround until this is fixed and here it is:

// https://github.com/shramov/leaflet-plugins/issues/62
L.polyline([[0, 0], ]).addTo(map);

And finally we add our layers to the control in the top right hand corner of the map which allows us to select which map provider to view. Check the live map above to see what I’m talking about.

map.addControl(new L.Control.Layers({
    "Bing Maps":bingMapsLayer,
    "Google Maps":googleMapsLayer,
    "OpenStreetMaps":openStreetMapsLayer
}));

And that about covers it for our map plugin. Next on board, we’ll take a look at the route plugin which allows us to send gps data from our phone to the Gps Tracker plugin. For the full list of tutorials in this series, please visit the tutorial page here on websmithing.

14 thoughts on “Gps Tracker WordPress Plugin Tutorial 1 – Map

  1. Tom

    You’re a talented programer.

    I especially like the ” so that we can be stylin’” approach. So many progrmers be lackin swag.

    Reply
  2. carlos rodriguez

    Hi there;

    I’m interested in your tutorial from the programming side of the fence. I need to get some sample GPS code for the android phone. If you could send me some of the code as a sample i’d be indebted to you. things that I’m looking for is 1: how to read a GPS message, 2: how to track a GPS device like a phone or an object.

    if you don’t have the code, but you have some links to where I can find the code, I can use that.

    thanks for your help.

    Reply
      1. carlos rodriguez

        thanks Nick; just downloaded your samples from github and now looking at them, will let you know.

        I’m also working with the Intel XDK (too many things to learn) and will try to use your sample using the Intel platform….

        Thanks a bunch, really appreciate it.

        Regards,

        Carlos

        Reply
  3. Brian Aderer

    Hi Nick
    Awesome plugin, thank you!

    A couple of questions: I am sort of modifying this functionality for a site I’m building. It’s for a traveling technician, and I want to give his clients the ability to know where he is in order to be able to more easily schedule visits. The prototype is here: http://www.brianaderer.com/hudsongrafik

    There are a couple options I’m working on changing to modify this according to my specs, and I’m having trouble figuring out how. First, Min, Max, and default zooms are important – I want this to be more of a global view, and I don’t really want them to be able to get more accurate than the city level in order to maintain his privacy.

    Also, I notice that when the app is restarted it’s creating a new route (or route history?), which adds another pin on the map. I’d like to (ideally) set it to ignore past routes so we don’t clog up the database, but if that’s not possible, only display the current position with no history.

    I’ve tried looking into this myself but seems these are controlled by variables and I’m getting lost. Any help, much appreciated!

    Thanks

    Brian

    Reply
    1. Nick Fox Post author

      Hey Brian

      As far as zoom is concerned. I think you would be able to lock it down with javascript. I would have to look into it to give a definite answer. The easiest way to only display your most recent location is to a) put one row in the database with your phone’s location and instead of continually adding new locations just update the location on that one single row. That is the easiest way to solve the problem.

      Fixing both of these things is going to require a programmer.

      n

      Reply
  4. Jack Kane

    Do you have a functioning version for Windows Desktop??? Is there a way to run this program in a Java IDE environment.

    Thanks, looking forward to post.

    Reply
  5. Frank

    Hello,

    very good programm 🙂

    I will use it for my iceland tour with my caravan – so the working people at home know where I am 😉

    Is there a chance to show the map in wordpress as satellite image?
    The google-maps menu for changing the map to satellite isn’t shown…

    Thanks.
    Frank

    Reply
  6. Leslie

    Hi Nick,

    Great plugin and documentation! Can’t say how much I appreciate your contribution and efforts to get this project off the ground and freely so. Feel that its sorely needed with the increased mobile usage and hardware capabilities available on virtually every device nowadays.

    I am currently attempting to use the tracker to display a local taxi route for a handful of db members and notice that the markers disappear from my other (non-leaflet) google maps objects when I enable the plugin. Would you by chance know of this issue and what would be the best way to approach it?

    Thanks a mil for your guidance/help re above…Leslie

    Reply
  7. Ahmed Gamal

    Hello

    I am not developer and I installed the plugin in my wordpress site then I installed the app and I made the configurations but it doesn’t work, so can you help me please ?

    I already activate the google map in my wordpress website with the Google API key but when I activate this plugin the Google map disappears and I don’t know why ?

    Thanks

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.