techy stuff (27)


Facebook plugin for wordpress

This week in the office we’ve been playing with the Facebook SDK and seeing what it can do, with a mind to using it on an upcoming project (that I can’t talk about!).  After a bit of playing, and bouncing ideas off each other we managed to get some fairly exciting stuff working.  Since I can’t publish the code we came up with, and I wanted to try out some other aspects of the SDK (well, multiple SDKs since theres Javascript and PHP variants to get your head around…) I thought I’d see how easy it was to create a plugin for wordpress.

If my boss is reading this by the way, I did pick up some directly applicable techniques and learning how to write plugins for various frameworks and applications is always useful….

Anyway, on to the code.  There was a lot of trial and error involved in this, so how it’s set out here is nothing like the actual development process, this is a much more cleaned up version!

 

the actual facebook code is fairly straightforward.  First we need to load the facebook javascript, and initialise it:

<script type="text/javascript" src="http://connect.facebook.net/en_US/all.js"></script>
FB.init({
            appId  : '    <?php echo $FB_APP_ID; ?>',
            status : true, // check login status
            cookie : true, // enable cookies to allow the server to access the session
            xfbml  : true  // parse XFBML
        });

You’ll notice a PHP variable echoed in there, that’s the facebook app id, which we set at the top of the code.  I’ll go into some detail about how to get this ID later, but for now all you need to know is that due to limitations of the Javascript API, there’s no way to create a web apoplication and distribute it with your app ID embedded in there already, everyone who uses your plugin or app or whatever has to create their own app on facebook so they have an APP ID to use.  This is really annoying, but it kind of makes sense… for web applications facebook locks down access to specified domains, so only requests coming from those domains get serviced by the API. I’ve no idea how this works for ‘Nativeish’ apps written using something like PhoneGap.  I assume they have some way round it, maybe they allow access from localhost or something.  Anyway, moving on…

Next we need to check whether we successfully logged into facebook.  For this we use the ‘FB.LoginStatus’ call, which returns an object with a status string to tell us whether we successfully logged in or not.  Here we also do some cookie shenanigans, to check whether this is the first time you’ve logged into the app (in effect, whether you’ve just installed the app), if so we post soemthing to the user’s wall to say ‘hey, look at this cool app I’ve just installed’ with a link back to tall-paul.co.uk to drive some traffic my way.

Finally, if we’re successfully logged in AND the ‘posttofacebook’ cookie is set, we do a post to facebook.  Some explanation is required here.  Because we want to use the javascript framework and the WordPress API is php (ie: serverside) the best way I’ve found of firing javascript actions attached to a wordpress ‘publish’ action is to set a cookie on the publish action, and then when the page refreshes after the action use the presence of the cookie to kick off the javascript we want to call.

FB.getLoginStatus(function(response) {
               if (response.status === 'connected') {    
                       facebook_app_authorised = true;
                    if (jQuery.cookie("tpfbpost") == "not authorised"){
                        //post to wall because we've just authorised for the first time
                        activationPost();                        
                    }               
                    if (jQuery.cookie("postTofaceBook") > -1){
                        <?php
                        $post_id = $_COOKIE['postTofaceBook'];
                        $my_post = get_post($post_id);
                        preg_match("/<p>(.*)<\/p>/",$my_post->post_content,$matches);
                        $description = strip_tags($matches[1]);
                        $site_name = get_bloginfo('name');
                        $thumb_id = get_post_thumbnail_id($post_id);
                        if ($thumb_id > -1){
                            $picture = wp_get_attachment_url($thumb_id);
                        } else {
                            $picture = "/wp-content/plugins/tallpaulfbpost/defaultimage.jpg";
                        }                        
                        ?>
                        link = "<?php echo get_permalink($post_id);?>";
                        message =  "A new article has been published on <?php echo $site_name;?>";
                        name = "<?php echo $my_post->post_title; ?>";
                        picture = "<?php echo $picture;?>";
                        description = "<?php echo $description;?>";
                        link = "<?php echo get_permalink($post_id);?>";
                        postToFaceBook(message,picture,link,name,description,"","postTofaceBook");                            
                    }     
                    addAuthorisedText();
                } else if (response.status === 'not_authorized') {
                    //set cookie so we know we're doing authorisation
                    jQuery.cookie("tpfbpost","not authorised");
                    addAuthoriseLink();
                } else {  
                    jQuery.cookie("tpfbpost","not authorised");      
                    addAuthoriseLink();
                }
            });

 

Finally we need to bind to the ‘publish_post’ action, and set our cookie to trigger off the facebook post when the page refreshes:

//set a cookie so we do a facebook post when the page reloads
function facebook_post_hook($post_id){
    setcookie("postTofaceBook",$post_id);
}

//hook into the publish post action
add_action('publish_post','facebook_post_hook',8)

There’s a lot more in there, but you can download the plugin and have a look at the finer details at the end of the article.

Now how to use the plugin?  First off you’ll need to download it and install it on your wordpress site like any other plugin.  Once you’ve done that head over to facebook and search for ‘developer’ in the top search bar.  That should take you to the lovely Developer app as shown below.  Click ‘create new app’ and fill in the required fields (see below for how the ‘Tall-paul.co.uk’ one is setup:

The only thing you really need to worry about are the ‘App domain’ and ‘Website’ fields.  These must match the domain / address of your wordpress blog or the plugin won’t work.  If you want to use it on multiple domains you’ll need a seperate facebook app for each domain.  Again, this isn’t my choice, it’s just how the facebook javascript API works.

Once that’s done copy the APP ID from the app page and paste it into ‘tallfbpost.php’  (replacing the current $FB_APP_ID) at the top of the file.

Now if you go to ‘Settings->writing’ in your wordpress control panel you should see a link at the bottom saying ‘click here to authorise the app’.  Click the link, accept the permissions and you’re done.

Publish a new post and you should see it appear on your facebook wall.

Future enhancements:

  • Add setting for app ID in the settings area
  • change behaviour so only newly published items are posted to facebook

Download (v0.1)




Job Hunting!

Thought I might as well post something here, you never know who reads these things…

I am currently on the hunt for a job.  Ideally something in PHP / Web development that pays around £30k (or slightly less for the right role) and is based somewhere near Manchester (UK).  Working from home would be nice though if you’re based on the other side of the world.

email me for a CV if you have any opportunities that might fit the bill.




Upcoming stuff

Just a quick rundown of what’s going on with jNag this week.  And a strange picture, which does actually have some context later on, so you should probably click the read more link if you’re wondering what that’s all about.

A flying pig. Why? Intrigued? read on....




ObNag: nagios plugin for Obsys building management system

For my day job I work for a specialist engineering company, tyrrell systems ltd who work in the field of intelligent building management systems.

One of the systems we spend a lot of time with is Obsys, from North Building technologies.  Basically this software allows wide ranging integration of building systems (air conditioning, intruder detection, lighting etc) and Tyrrell Systems add our own software and front ends to the system.  We also produce a hardware platform (communicator) for running obsys and all our software.

Anyway, I was looking for a way to pull information from the Building management system into my nagios install, so I could keep an eye on various things (like outside air temperature for example) from jNag.  There wasn’t a pre-existing plugin to do this, so I wrote one myself that gets called by Nsclient++ on the Obsys machine, reads a point from Obsys and returns the information to Nagios. Here’s jNag displaying some output from our building management system:

It’s written in c# and requires the Obsys active x control from North BT to work.

Repository here




CPU / GPU temperature gadgets

Just a quick post today, I found these handy desktop gadgets (for windows 7 and probably vista too) and thought I’d share:

The top one, which monitors CPU temperatures is an add on available for CoreTemp. You need to have the coretemp program running for the gadget to work, but the program is fairly unobtrusive and just sits in the taskbar doing it’s thing.

CoreTemp download
CoreTemp add-ons page

The bottom Gadget is monitoring my GPU (graphics card) temperature. Useful if you have an overclocked box and want to keep an eye on your temperatures while gaming. This gadget works for ATI & Nvidia cards, it automagically detects which card you have so there’s no setup needed… just drop it on your desktop. The homepage for this is in German, but if you scroll down a bit you can easily spot the download link

GPU observer gadget




VirtualBox seamless mode

This is my current desktop in the office:

As you can see, KDE4 taskbar on the right, windows 7 taskbar on the left.  Windows from the right can move onto the left screen freely (note the linux terminal on the left screen).  Unfortunately due to limitations in the virtualbox seamless mode windows from the left screen (from windows 7) are limited to that screen.  Also, there’s no fancy aero 3D effects.

Still, it’s a nice way to run windows and Linux side by side.

virtualbox




PHP Javascript / CSS loader

I’m currently working on an in-house management system here at Tyrrell Systems, and employ a lot (seriously, a lot) of javascript for everything from ajax loading of information to various layout tweaks and so on.

When I inherited the project (a good 2 years ago now) the previous coders had made use of various scripts they’d found on the web, as well as a lot of hand crafted stuff.  I started swapping things over to the rather spiffy Jquery library and added a load more functionality.

However, the system has inevitably started to slow down over the last year or so, loading in all those javascript libraries has taken its toll on page load times.  As well as the javascript overhead there’s also around 30 different css files to load in (I like to keep things well segregated!).  This leads to the following problem:

As you can see, it was taking nearly 30 seconds just to load in the css & javascript for a typical page.

So, I started looking for a solution.  Now, the general (and rather obvious) approach to this is to ‘munge’ all your css (or javascript) files into one big file, run that through some kind of optimiser and then serve the resulting file instead.  This reduces page requests & bandwidth used in one go.  This is a good example of this general approach.  Unfortunately, 90% of these scripts rely on using mod_rewrite to redirect calls to css / js files through a PHP script.  My site runs on IIS, so they’re no good for me.  To cut a long story short, I decided to write a class that would:

  • Allow me to merge multiple css / js files into 1.
  • optionally optimise that file before serving it.
  • Cache the output so I only have to do this process when I actually change any of the css / javascript.

This is what I came up with.  It makes use of jsmin-php for javascript minification, and css-tidy for well, css-tidying so you’ll need to have those if you want to use optimisation.  Or you can optionally turn it off.  To use the class:

First initialise it:

$main-css = new cacher("main.css","css");

The first parameter is a filename (can be anything you like) and the second is the type (must be css or js).

Next we add our files:

$main-css->add_file("path/to/my/file.css");

or we can add every css/js file in a folder like so:

$main-css->add_folder("path/to/my/folder/");

then when we’ve added everything, we output the files:

$main-css->output();

The output file will be cached (in /theme/cache by default) until you delete the cached copy from that folder. So if you change any of the files included using this class, remember to delete your cached file!

and that’s it.

Just to complete the before / after theme here’s what this did to my loading times:

Here’s the code (as usual, it’s free to use but please give some credit if you do).

nb: the variable $cfg used here is a global class used in the project this came from. Basically, $cfg->root needs to point at the webroot for your project.

<?php
class cacher{	    
	function __construct($filename,$type)
	    $this->type = $type;
            $this->filename = $cfg->root."\theme\cache\".$filename;
            $this->url = "/theme/cache/$filename";
            $this->optimise = $optimise;
            if (file_exists($this->filename)) {
                $this->output();
                $this->cached = true;
            } else {
                $this->cached = false;
                $this->fh = fopen($this->filename,"a") or die("unable to open file $this->filename");
            }
        }

        function add_folder($newfolder){
            global $cfg;
            if ($this->cached == true){
                return;
            } else {
                $dh = opendir($cfg->root.$newfolder);
                while (false !== ($file = readdir($dh))){
                     $ext = substr($file,strrpos($file,'.')+1);
                     if ($this->type == $ext){
                         fwrite($this->fh,file_get_contents($cfg->root.$newfolder."\".$file));
                         fwrite($this->fh,"n");
                     }
                }
                closedir($dh);
            }
        }

        function add_file($newfile){
            if ($this->cached == true){
                return;
            } else {
                fwrite($this->fh,file_get_contents($newfile));
                fwrite($this->fh,"n");
            }
        }

        function output(){
             if ($this->cached == true){
                 return;
             } else {
             if ($this->type == "css"){
                    fclose($this->fh);
                    if ($this->optimise == true){
                        require("lib/csstidy/class.csstidy.php");
                        $css_out = new csstidy();
                        $css_out->parse(file_get_contents($this->filename));
                        $this->fh = fopen($this->filename,"w");
                        fwrite($this->fh,$css_out->print->plain());
                        fclose($this->fh);
                    }
                    echo "";
             } elseif ($this->type == "js") {
                    fclose($this->fh);
                    if ($this->optimise == true){
                        require("lib/jsmin/jsmin.php");
                        $js_out = JSMin::minify(file_get_contents($this->filename));
                         $this->fh = fopen($this->filename,"w");
                        fwrite($this->fh,$js_out);
                        fclose($this->fh);
                    }
                    echo "";
             }

            }
        }

    }

?>