Thursday, May 5, 2011

Fun with the new Facebook PHP SDK and WordPress

As I've mentioned, I started this blog with the intention of being able to claim research and development credits at work when I come across particularly hairy issues, and good news, as today I have something to write about.

Today, more and more people want social integration with their website, and who can blame them? Facebook has hundreds of millions of users and integrating that with your website can allow users to interact with your site easier than ever.

I do a lot of work with WordPress, which is a great little CMS that is flexible enough to adapt to almost any type of site, and since I can remember, I have used a great plugin from a fellow who goes by the name "Otto", called Simple Facebook Connect.

Simple Facebook Connect works great. It makes it easy to set up "Like" buttons, user registrations via Facebook, comments for users through Facebook who aren't members of your site, and more, however, Facebook has recently introduced the newest versions of their "Social Plugins", which introduce some increased functionality for the older items, and some completely new items.

Naturally, a client wanted us to implement some of these new plugins into an existing site which was built using WordPress. At first, I had hoped this would be a simple transition, however, this was not the case.

The biggest problem is that in order to use the new plugins the new JavaScript SDK must be loaded into the site. The old SDK and new SDK do not work nicely together, so in order to use the new features, we would have to rebuild all of the old functionality, while making sure the new functionality would work as well.

A lot of the problems were fairly simple to figure out. Although Facebook's documentation is notorious for being incomplete, I was able to reproduce most of the functionality needed that I would lost in removing "Simple Facebook Connect". The biggest issue with logging users in however, was that I couldn't easily just "hook" into the WordPress actions system, and needed to tell the JavaScript SDK to reload the page when a user logged in via Facebook, pointing them to a PHP file that would receive the Facebook Session as a query parameter in order to properly log the user into our site and Facebook simultaneously. This was much easier than what was to come...

Facebook specifies in their documentation that if you log a user into a site via a Facebook login, then when they log out, they MUST also be logged out of Facebook. This makes sense, so that if a user is at a public machine they won't "accidentaly" leave their Facebook account logged in for the next person who comes to use the machine.

The biggest problem is that when you use the new PHP SDK for Facebook, you're using something that's still in development, and still missing some features. In the older SDK, you could simply create a Facebook object and call a "logout()" method which would log the user out of Facebook, the new SDK didn't have this feature, and so I was out of luck.

I searched long and hard, spending between 14 - 16 hours trying to get different solutions that were mentioned online to work. The client we were doing this work for even had a contact at Facebook, who couldn't give us an answer, and could only point me back to solutions that I had already investigated.

The solution that made the most sense to me that was online was that when the user logs out, delete the cookie which is storing the Facebook session. I knew that this would work, as if I deleted the cookie manually, using my browser's cookie viewer, I would be successfully logged out of both sites, but obviously, that wasn't something we could write on the page on the way to log out.

I knew that I could hook into the "wp_logout" action generated by WordPress. This action is called when the WordPress user session has been destroyed.

Over and over I tried different ways of deleting the cookie. Setting it's content to empty, expiring the cookie, using external libraries to delete cookies (which was basically just trying to do the same things I had been trying).

I knew there was a "Facebook Logout Url" that I could grab from the PHP SDK, however, trying to redirect this would not work. However, I did find that if I was to manually hit that address, it would accept the fact that the cookie had been expired, and my Facebook account would be logged out.

I found, by going into the WordPress source, that it throws a redirect after "doing" the "wp_logout" action. This made sense. If I try and redirect to the logout url from Facebook, and then WordPress throws it's redirect, the headers would cause an error, and the cookie isn't properly cleared.

The final solution was to "exit()" the custom logout function which redirected to the Facebook URL, thus completely eliminating the call to WordPress' integrated wp_logout redirect.

There have also been some other lessons I've learned with the new Social Plugins, with the most important being that the "FB.Share" JS will cause the new JS to fail. Hopefully I'll have more on another Facebook Social Plugin issue soon!

Wednesday, January 19, 2011

WordPress Conflicts (and what I did to make them go away)

I, with the help of a co-worker, made an interesting discovery today while installing a plugin for a client at work.

The client wished to have custom WordPress registration emails sent to their users when they sign up to the site. I can't say as I blame them, as the drub emails they send off with just a username and password are boring as heck.

Anyway, while I had always found online that "Register Plus" was the best plugin to use for this in the world of WordPress, I was asked to use the "Welcome Email Editor", which was a very nice, simple looking plugin. I installed it on my sandbox blog, it worked exactly as one would like it to, so I pushed it to the live site, activated it and saw an ominous message...

Welcome Email Editor can not function because another plugin is conflicting. Please disable other plugins until this message disappears to fix the problem.

Well poop, I thought. I wanted to get this issue off my plate, as it seemed simple enough. However, I had a conflicting plugin.

The first thing I thought I could do was check out the Email Plugin to see why the error was being thrown. I searched the code and found the following, which was setting a boolean to false, thus displaying the conflict message...

if (!function_exists('wp_new_user_notification')) {
function wp_new_user_notification($user_id, $plaintext_pass = '') {
...
}
}
else {
$sb_we_active = false
}

I figured out which plugin was the cause of the conflict quite easily. I thought it was being caused by my call in that plugin to wp_new_user_notification, however, upon commenting it out, I realized that wasn't the problem.

I asked a colleague to help out, he was also a bit puzzled. After some searching on the web, we found this ticket in WordPress' trac system. It was then clear what the problem was...

As long as your plugin file has the function in the global scope when its included, that error shouldnt occur. I think theres 1 or 2 dodgy plugins which do a include_once('pluggables.php'); when they shouldnt.
That told us that it was likely that somewhere in the plugin, I was including "pluggable.php". I never remembered doing it (or even why I would have done it), and doing a search I found the following function...

if ( !function_exists('wp_get_current_user') ) {
function wp_get_current_user() {
// Insert pluggable.php before calling get_currentuserinfo()
require (ABSPATH . WPINC . '/pluggable.php');
global $current_user;
get_currentuserinfo();
return $current_user;
}
}

There was a good reason that I didn't remember doing it, because it wasn't me. I had been given this code by someone at the start of the project to "help" with some of the problems I was running into*. What happens, is that "pluggable" loads first, which will make it impossible for the Welcome Email Editor to overwrite the function it needs to in order to work.

With some quick changes to my plugin, I was able to remove that include, get everything working and learn a valuable lesson about not ever, EVER including "pluggable.php" in a plugin again.

* I realize it seems very cheap to blame someone else for a problem I have run into, but at the same time, I believe that everyone should be held accountable. It would be easy to blame all my problems on others, but I don't do that, only in cases where someone else is actually at fault.

Friday, January 14, 2011

Getting All Friends of a Facebook Application

Everyone loves Facebook.

Well almost everyone anyway...

Developer's are among those who've grown to hate Facebook and their constant API changes, although the new "Graph API" does appear to be making constant strides toward being a solid, stable environment for developers.

One of the problems I have run into when working with the API, is that I want my application to get all of a user's friends who also use the application. After scouring the (still incomplete) API docs, I turned to the forums, where I found the following function.


$facebook->api(array('method' => 'friends.getAppUsers'));


This, although currently undocumented, is a great feature for any application you build for Facebook where you want to see friend's scores, results, etc.

Hope it helps someone out there as it has helped me!

What it is!

This is a personal blog I am keeping to describe problems I have had in my programming life and the solutions I have found to said problems.

I am not out to answer anyone's questions but my own, but hopefully you may find some answers to questions you have.