Facebook Credits, the Order ID, and dealing with large integers in 32 bit PHP

So, currently at work I’ve been rewriting all our Payment Gateways for Your Members. Making them more better Class based an abstracting out the common functions to a base class, to save memory footprint and code etc.

And came across a problem when rewriting the Facebook Credits handler.

The order ID that gets passed around, as well as the Application ID is too long for a 32 Bit PHP installation to handle when treating it as an Integer.

So a number like “239724439419867” was ending up as “1.7592246582797E+14” when stored/processed, or converted to a string.
Now the obvious way to process this is to convert it to a string another way, which is somewhat difficult since before you even start it is in a format that you can’t handle.

The saving grace here is the fact that data is passed to you as a JSON packet (aside from the fact the Order ID is in the $_POST variable and thus a string, so I could of used it from there).

This led to me to look at the JSON packet, which starts as a string but when decoded the large integers are still a larger integer than can be processed (whether you json_decode to a Array or to an Object, the problem persists). So I thought about how to process the raw JSON packet and make sure the order ID, and other large integers are treated as strings.

If you look at a Raw JSON packet you can easily spot whats a string, integer, object or array.

Take this example Facebook Credits JSON Packet, (wrapped for readability):

{"order_id":239724439419867,"buyer":197803678,"app":148748711865470,
"receiver":197803678,"amount":5,"update_time":1320075413,
"time_placed":1320075408,"data":"","items":[{"item_id":"<item_id>","title":"Post",
"description":"A New Purchasable Post",
"image_url":"<some url>","product_url":"<some other url>",
"price":5,"data":"<data>"}],"status":"<status>"}
  • order_id is an integer as it has no ” around it
  • status is a string as its surrounded by “
  • Items is an array as its surrounded by [, in this case containing a single object, entries/items are comma separated.

So after thinking about this I decided the best way to sort this out was to convert the integers in the raw JSON packet to strings before decoding.

In pseudo code.

Lop off the { and } from the start and end
Explode around ,
array walk each item
split on :
check if there are no " in the second bit
if none wrap in "
glue back together

Something alone the lines of:

function largeint($rawjson) {
  $rawjson = substr($rawjson, 1, -1);
  $rawjson = explode(',' , $rawjson);
  array_walk($rawjson, 'strfun');
  $rawjson = implode(',', $rawjson);
  $rawjson = '{', . $rawjson . '}';
  $json = json_decode($rawjson);
  return $json;
}

function strfun(&$entry, $key) {
  $data = explode(':', $entry);
  if (FALSE === strpos($data[1], '"')) {
    $data[1] = '"' . $data[1] . '"';
    $entry = implode(':', $data);
  }
}

I’m not sure in terms of memory footprint if its cheaper to do a substr of $data[1] and check if its a ” or not.
I suppose it could test the string length of the detected integer to see if its invalid/unable to process, but then you would be performing a string function on an integer and again the problem would arise.

But as a block of code is does the job, its obviously not ideal for all situations, since in this case I want the integer as a string, I’m not using it for math, but if I did, we probably need to do some bizarre unpack-ing or something.

Any opinions or improvements give us a comment below 😀

Thoughts on working on a different computer when your normal one is not available

So currently my Mac Book Pro is in with Clockwork Leeds getting its Hard Drive replaced as it failed/has failed/is failing.

So currently at work, I am sans my normal Development machine and find myself on the Mac Mini server that sits and does our File Server and System Monitoring.

Its quite odd having to get used to a system that for starts is the Server build of Mac OSX as well as having none of my personal preferences.
Its bringing to light how slightly useless some of the things I have setup on my Personal machine are that I thought were useful.

For example, I’m stuck with a single screen, so no dual screen lovely-ness. So I’m very restricted to the screen real estate I have available.
So not having new Terminal Windows opening to fill half the screen like on my mac is quite useful. Whereas before having the secondary screen with two terminal windows full height, half width was the norm, as well as using a little app I’ve forgotten the name of which allows me to press ctrl + ~ to get a window appear from the top, is a bit of a pain, but resolved now with having three default sized terminals and chrome open.

So far its seemed to work just about fine like that.

I also find myself using Spaces/Expose a lot less, I’m doing a lot less jumping between spaces all the time. But I also don’t have the “App only opens in space x” setup so I get a lot less forced jumping.

Finally tho I miss my music collection, so I’ve switched to plugging my headphones into my iPad and listening to Spotify. Tho I could just plug in my external drive thats in the office and have most of my older music on hand….

I’m also on a different desk which is nice.
I’m not by the door and have the window behind me and I’m in the corner.
I quite like it over here. Seems a bit more separated from everyone else. Which is a good thing and a bad thing in its own right.

I love working with the team, *can’t think of right words to express feelings will just skip to post summary*.

Summary

My Mac is in the repair shop getting fixed.
The hard drive was failing and is pending spare parts from Apple.
Clockwork are amazing for Apple Repairs.
I’m in a corner at work
I have no home machine to really play or work on. (I made my home windoze laptop blue screen just by looking at it….)

I watched last nights Torchwood on my iPad using the BBC iPlayer Application and it worked perfectly.

Finally my local dev environment is shafted as that was my Mac Book Pro. Luckily everything is in offsite repo’s and I have a Server in a Server Room down the corridor to talk to 😀

-End-

WordPress and the Admin Bar

So WordPress 3.1 introduced the new admin bar. Essentially its another way to navigate around your WordPress Blog’s inner workings, the bar itself can be enabled and disabled both inside and outside the admin system, for I like to have it enabled on both the admin and non admin sides of WordPress.

The WordPress.com Stats Plugin makes quite good use, on the non admin side, by showing a graph of site visits over the last 48hours:

This led me to think about how to put my own links on, so I turned to adding the navigation from YourMembers to the admin bar (but in this case on Both Sides, admin and non admin).

Won’t show you a admin side one as it looks exactly the same 😛

Actually writing the code to make the YourMembers navigation be added to the nav bar, is actually relatively simple, since the admin bar itself has been written rather nicely in its own class.

Opening up the admin-bar.php file in wp-includes is a bit messy, but looking at the first function (_wp_admin_bar_init) shows the class function add_menus() and further down add_menu, so off I went to find them…. A quick grep later finds that is class-wp-admin-bar.php and from there just a matter of reading what add_menu wants….

<?php

	function add_menu( $args = array() ) {
		$defaults = array(
			'title' => false,
			'href' => false,
			'parent' => false, // false for a root menu, pass the ID value for a submenu of that menu.
			'id' => false, // defaults to a sanitized title value.
			'meta' => false // array of any of the following options: array( 'html' => '', 'class' => '', 'onclick' => '', target => '', title => '' );
		);

I went thru and checked to see where the other “normal admin” links were being added, the function add_menus in the same class file shows that. The key thing to be aware of is the use of priority on those do_actions (line 182 thru 194) in order to order the links, so needing/wanting the YourMembers links to be at the end I went for a sensible priority of 90 since the last normal admin was set to 80.

Then it was just a matter of setting up my own add_action on the same hook (‘admin_bar_menu’) and then globalising the pre existing class method and adding my menus to it.

Since it is a drop down menu, needed to add the top menu as a parent and then adding the child nodes.

Its quite a clever class since the class function of add_menu can handle both parents and childs at the same time with little fuss, as long as you pass it the right ID variables.

Heres a copy of my function:

<?php

function ym_admin_bar() {
	global $wp_admin_bar;

	if (ym_admin_user_has_access(TRUE)) {
		$wp_admin_bar->add_menu(
			array(
				'id'		=> 'yourmembers_adb',
				'title'		=> 'Your Members',
				'href'		=> YM_ADMIN_INDEX_URL
			)
		);
		global $ym_nav;
		foreach ($ym_nav as $page => $subpages) {
			if (is_array($subpages)) {
				$first = array_shift($subpages);
			} else {
				$first = '';
			}
			$id = 'ym_adb_' . strtolower($first);
			$url = strtolower($first);
			if (substr($first, 0, 5) == 'other') {
				$url = 'ym-other&action=' . substr($first, 6);
			}
			$wp_admin_bar->add_menu(
				array(
					'parent'	=> 'yourmembers_adb',
					'id'		=> $id,
					'title'		=> $page,
					'href'		=> YM_ADMIN_INDEX_URL . '&ym_page=' . $url
				)
			);
		}
	}
	return;
}
add_action('admin_bar_menu', 'ym_admin_bar', 90);
?>

There are a couple of funky bits in there due to the method we currently generate the nav items.
The essential bit to consider is the array passed to $wp_admin_bar->add_menu at the start (the parent element note, no parent key) and the $wp_admin_bar->add_menu at the end, specifying a child element.

The function ym_admin_user_has_access just checks to see if the user is of the correct level or not.

You might want to throw in a switch on is_admin() to return different navigational items depending on if you are in the admin or not.

I’m sure there is a lot more you can do with the class function but when I installed WordPress 3.1 and saw the admin bar and WordPress.com Site stats this was the first thing I thought of and implemented, tho why its taken me this long to blog about it I don’t know…..

Travels of a Commercial WordPress Plugin Developer 1

My job at the moment is updating and coding YourMembers, which is a commercial plugin for WordPress.

Recently I’ve been working on a method to Auto Upgrade the plugin, since commercial plugins cannot go on Extend, and there is no commercial equivalent. Extend being the WordPress plugin repository.

Commercial plugins get no nice little “Plugin needs updating Circle” on the plugins tab, or a nice little message on the plugins page, let alone access to the auto updater!

Which leaves us (commercial plugin devs) to write our own version checkers and hook in accordingly.

So now I have a nice little PHP class which will detect whether it can fwrite/rename and if not if it can FTP instead, much the same as the WordPress updater does.

Now this is all well and good, but I needed a method to download and unzip the new plugin file. Grabbing the file is easy, either file_get_contents (heaven forbid), or curl (yay for curl), and write the file (being a zip) to the web servers temporary directory and process from there.

Now the problem here is how to unzip. A Brief look at how WordPress does it seems to show it has three different methods of unzipping. So dump that.

Didn’t feel the need to use PHP’s ZipArchive class, since I don’t need to edit the zip, just extract its contents.

Off to php.net I go and I find some nice handy functions, and quite surprised to find that the zip_read function can handily recurs into directories within the zip file to return their paths/names. Mildly annoying at the time as I had gone and written a recur loop to go inside directories…. and got thrown a error, nice headdesk moment!

So basically the Zip functions, the basic ones of PHP, are actually quite nice, handy and useful!

Heres my code snippet:

<?php
class someclass() {
	private function unpack() {
		$from = $this->tmp_write;
		$to = $this->tmp_out;
		@mkdir($to);
		
		$zip = zip_open($from);
		if (is_resource($zip)) {
			$this->readzip($zip);
			zip_close($zip);
		} else {
			// failed to open
			$this->error = 1;
		}
	}
	
	private function readzip($zip) {
		$from = $this->tmp_write;
		$to = $this->tmp_out;
		
		echo '</pre><textarea style="width: 100%; height: 100px;">';
		
		while (FALSE !== ($file = zip_read($zip))) {
			$name = zip_entry_name($file);
			echo $name . "\n";
			if (!strpos($name, '.')) {
				// is dir
				@mkdir($to . '/' . $name);
			} else {
				// it recurs into directorys on its own!
				$item = zip_entry_open($zip, $file);
				$size = zip_entry_filesize($file);
				
				$read = zip_entry_read($file, $size);
				$fp = fopen($to . '/' . $name, 'w');
				fwrite($fp, $read);
				fclose($fp);
			}
		}
		
		echo '</textarea><pre>';
	}
}
?>

I just installed this code snippet plugin, which I might need to change its background colours…..

Any suggestions for code snippet plugins greatly appreciated!

SOLD and All Change!

So I left my job at Vanguard SEO as the start of this year for two reasons, one got a better job offer, and two the company went bankrupt. Not very lolworthy.


Anywho, I have been contracting for NewMedias, as a PHP Developer, since September Freelance style, and more 9-5 contracting during January and then NewMedias overlord Apeei, sold the company for mere bananas to CodingFutures, and then they offered me a job, so there I am now as a PHP Developer! And now we are nearly at the end of week two of my new job.


This week we had some nice photos done heres me and the rest of the team!

So these days I find myself working on YourMembers a WordPress plugin for Subscription and post control among other things. As well as the plugins for it. I built from the ground up YSS – Your Secure Stream, which can create links with expiry for Amazon S3 Hosted content, so people who use WordPres can provide Audio and Video, whilst protecting that content too! It plugs in to FlowPlayer and Longtails JWPlayer, some of the more commonly used players.

This week I’ve been working on the Mail/AutoResponder Plugin. Its been going well and should hopefully be finished soon 😀

Thru my work I’ve been getting to know WordPress more and the most useful link I’ve found today, is how to integrate TinyMCE, the Visual/HTML editor for WordPress, into your own Plugins. I’ve expanded on some of the code from the second link for the Visual/HTML editor switch, in order to handle multiple instances of TinyMCE on a page, as well as the core code. Mainly since the page I am using TinyMCE on, is generated thru a Form Generation Class I didn’t write and should at some point redo, its a nice class but has some interesting caveats and limitations. Let along the fact I havn’t managed to get WordPress using my usual jQuery DateTime Picker I like, since WordPress uses a old version of jQuery and jQuery UI, and if you load latest, its gonna break someone else’s plugin, installed on a client site, and to top it all WordPress loads the jQueryUI CSS for the latest version for Google CDN.

On a side note using Google CDN’s jQuery is very good and better, check this link for reasoning, and this one for implementation (in general not just WordPress).

I think the key point for using Google Code hosted jQuery, is that pages will load quicker, since more domains mean more open HTTP connections, as browsers limit the connections open to a single domain at once. About 6 according to the reasoning link, so more domains means more open HTTP connections which means pages can load more quickly. Let alone the fact that if everyone loads from Google Code, then its cached on the users machine, which means from site a to site b, on site b, user doesn’t have to load jQuery as its already in the Cache. Thus making page loads quicker!

Still need to find a link explaining how to use the WordPress collapse a box, that all the WP-Admin grey bars and boxes do. I have built my own function in jQuery to do it, but it doesn’t (yet) have the cookie elements that WordPress’es own has to remember which are open/closed when the page reloads. Since seem there is no easy documented way on how to use the in built functionality.

Either that or I’ve missed it.

Also lately been working with the MailChimp API, had to laugh at the URL: http://apidocs.mailchimp.com/rtfm/.

On that bomb shell, catch you later, I’ve felt like I’ve rambled on a lot when this post was looking quite short…. Must blog more. Keep an eye on my Tumblr for more real time snippets of stuff, I’m assuming you already follow me on Twitter…..