Tuesday, August 17, 2010

Blizzard maintenance still blows

Tuesday night. Date night. So called, because it's the one night of the week where WoW servers go down for maintenance, and I can spend some quality time with my better half. That is, until she goes to bed, or I have one of those sleep deprivation catch up moments where I can't keep my eye open past 9:30pm.

Assuming I haven't just fallen asleep, I tottle off to the computer and play... something else. Because WoW is down for maintenance.

Well, I thought StarCraft II might change that a little. I thought it would give me the option of another quality Blizzard game that I could play when WoW servers are down.

But not tonight. Even though I just want to play the single player campaign, or even a couple of matches against the A.I., I can't because SCII requires signing into Battle.net. And even though I'm located in the South East Asia (SEA) region of Battle.net, which is unable to communicate with the Americas & Oceanic region of Battle.net (for cross game Real ID chatting, as most Americans get to experience), the SEA Battle.net servers have also been taken down for maintenance during peak play time for the SEA region.

Makes me wonder if there really is a physical SEA Battle.net server hosted locally to this region, or if they plonked it in L.A. or Hawaii to get it as close to the region as possible without having to invest in any infrastructure outside of the U.S.A.

Maybe I'll be looking forward to Guild Wars 2 for my WoW downtime play. A second MMO where all you pay is the price of the game, without the "what's the catch?" feel of a Free 2 Play/Try is looking to be my idea of a tasty cuppa. That, or Portal 2, whenever that gets released.

Monday, August 16, 2010

What about the people on the boats?

I've been thinking about this post for the better part of 24 hours, and have decided I can't structure it nicely to make any sort of constructive, informed, coherent argument. So I'm just going to post it like the splatter pattern it represents: the latest LNP radio jingle about "stopping the boats" is giving me the shits!

I'm not really a politically minded person. Political discussion doesn't excite me, and I'm not informed enough to give constructive comment (I may have mentioned that just sentences ago). But we've got a national election this Saturday, and if the LNP can come up with "stopping the boats" as an election standpoint, then I reckon I could garble on about all sorts of crap.

So, this radio jingle I heard on the weekend goes on about how Labor couldn't "stop the boats". And that's about it. No informative policy on what LNP are going to do. But that's not what shat me the most. It was that I just find the whole "stop the boats" argument bloody insulting and inhumane.

My initial selfish take is that I'm a boat person. Difference is, I arrived by plane, and with my parents when I was 10 years old. They came to Australia, looking for a fresh start and new opportunities. My parents weren't even trying to escape an oppressive regime: they arrived from New Zealand.

My second take is that the whole jingle sounds like one of those racist viral emails trying to disguise itself as humor or insightful commentary. It's really disappointing, but not so surprising. The Ugly Australia is still alive and kicking, and the scary thing is, there might be enough ugly Australians out there that they may even win.

I'd rather hear about a constructive policy that deals with efficient processing of immigrants, and people looking for refugee status. I'd rather hear about plans for diplomacy that address the root causes of why people are leaving their home countries, looking for a better life. I'd rather hear about the life stories of these people, willing to risk their lives to a shoddy boat and the wild seas for a chance in a place where, by all accounts, they're not welcome.

LNP will be getting preference votes somewhere around Family First and the pro Christian lobby groups, from me.

Friday, August 13, 2010

Integrating CakePHP with legacy and CodeIgniter

This post will discuss how I integrated CakePHP with a legacy application that had already been integrated with CodeIgniter.


Sometime ago, I decided to make a legacy application a bit more of a pleasure to maintain by introducing MVC. At the time, CodeIgniter offered the best flexibility, with regards to integration in the realms of session management, and models. I was already doing projects in CakePHP, but at the time, it didn't seem to be flexible enough. The might have been back in late 2008.

So I kicked off the initial integration, then ended up passing alot of the work on to my minions (Hi minions!). Earlier this year, my minions ceased being my minions (bye minions. I miss you!) and I've had to do a bit of maintaining and new project work with the legacy application. Having worked so long with CakePHP, CodeIgniter was like a very unwelcome swim in the middle of winter. The thing that erked me the most was the lack of a built in ORM. I went looking for some, but the recommended ones were quite strict, and that wouldn't do for integrating with the legacy database.

I had already done some work with integrating CakePHP with CKEditor (for sessions), and CakePHP 1.3.3 did seem to be at a point where you could use it's models for legacy database table naming conventions. So I bit the bullet, loaded it, and pointed it firmly at the existing CodeIgniter part of the application and said "No more".


Unlike my previous article regarding integration of CakePHP and CKEditor, I won't be posting alot of code in this article. If you're going to do something similar with your legacy product, you really need to understand how your legacy app works, and you need to understand how CodeIgniter works (if you're looking at that bit too).

Now, before reading much further, you might want to read about integrating CodeIgniter with a legacy application. This will give you a run down on the existing structure. Then have a read of integrating CakePHP and CKEditor, and a few of the same methods from that will be used here.

The Big Picture

So what's novel about what I'm doing? Well, I've got one existing framework that works with mod_rewrite and some legacy mush that calls the PHP directly, and now I'm about to introduce a second framework that also uses mod_rewrite, and all three will need to be able to share the same session, and not trip up on each others virtual directories. Let us take a look at the directory structure.

To protect the guilty (that would be me), I'm going to give the legacy app an imaginative name, different but not far removed, from the actual name of the legacy application. Lets call it LDS for Legacy Database System. Recently, it had a rename, but hasn't actually been formally rebranded. This has helped a little with the real application. We'll go with a rebranding of NDS for New Database System.

Here's a sample of the tree structure:

src This is the root of the application. It's has an index.php, plus ci_index.php, ci_open.php and ci_close.php that was used for CodeIgniter integration.

src/lds This is the main directory of the legacy application. When I first started, there were only a few subdirectories and a whole bunch of programs sitting in here. Yucko. There are a few more directories now, trying to group like portions of the legacy app, but there are still quite a few programs floating around in there. When you visit the website, you'll visit http://localhost/lds/. Anything with the lds in the URL is legacy code.

src/lds/codeigniter This is the CodeIgniter directory, as per the normal CodeIgniter directory structure.

src/lds/system This is the CodeIgniter system directory, as per the normal CodeIgniter directory structure. There's a libraries and language as well, and whatever others ones are required, however, I thought I'd just list this one so you get the picture.

src/lds/application This is the CodeIgniter application directory for the pure CodeIgniter code. If you were visiting the Documents controller, implemented with CodeIgniter application, you would visit http://localhost/documents.

src/lds/legacy This is the CodeIgniter legacy application directory. It's a cutdown version of src/lds/application used by the legacy application to establish a CI instance for session access.

src/nds This is the main directory of our new CakePHP stuff.

src/nds/cake This is the CakePHP directory.

src/nds/app This is the CakePHP app directory. When you visit the Documents controller, implemented with CakePHP, you would visit http://localhost/nds/documents.

With this arrangement, I didn't have to change the .htaccess file in src.

Having already applied changes to src/nds/app/webroot/index.php to cater for external applications, the next hurdle is logins and session sharing. Since most of the new work will be done with CakePHP, I've decided to use CakePHPs sessions, and allow the legacy app and the CI framework to access them.

CakePHP and the Legacy App

For the legacy app, following the same method as described in the CKEditor article, I modified the code that does the session check to declare an external app, include the src/nds/app/webroot/index.php, import the Session class, start a session and read the Auth.User. For new sessions, I created a new login screen via CakePHP, providing login and logout methods.

As a side note, the legacy app doesn't have tricky ACLs, and users passwords are stored as plain text in the database. To this end, I overloaded the default AuthComponent with a NDSAuthComponent that assigns itself to $this->Auth during initialisation (so you can pretend you're playing with the default Auth component), and does not hash the password.

In my travels, I also came across something else that was interesting. I needed to call session_write_close() during the destruction of the CakeSession object. I thought I'd try and "do it right" by extending CakeSession, and overriding the __destruct() method, and then create a new Session.save type called nds_session. However, database connections seem to be semi-hardcoded for cake_session types only, so I also had to override the __construct() method, and copy the same processing for nds_session, has happens for cake_session, with regards to connecting the default Session class to the datasource. In turn, I then had to replace the SessionComponent with a version that extended NDSSession instead of CakeSession.

That almost covers the easy stuff for CakePHP and the legacy application. There's one last change regarding accessing legacy code. There are some nice library calls in there that I'd like to access from CakePHP, instead of having to copy the code into a Component or Helper or Library and maintain it twice. So I needed a way to include the legacy app on the CakePHP include path.

Also CakePHP and CodeIgniter do not play well together. I could not include both frameworks within the legacy code, so I had to remove all references to CI in the legacy code, and replace them with calls to CakePHP. This was mostly for session calls anyway, so it's no biggy. However, I did have one component, written in CI that handled a recently accessed client list. I haven't dealt with it yet, but will probably have to write an equivalent helper/component in CakePHP.

To do this, I altered src/nds/app/webroot/index.php to define a LDS_ROOT and include it in the include_path setup. I also added some define statements to prevent legacy code from reconnecting to the database if called from CakePHP, since this reconnection tends to ruin the database connection for the remainder of the CakePHP processing.

CakePHP and CodeIgniter

The next part was to integrate CakePHP and CodeIgniter. Unfortunately, these two frameworks to not play well together, so the only real integration I could achieve was to provide a Session class to CodeIgniter that could read CakePHP sessions.

This involves overwriting the CI_Session class with a version that conforms to the method signature of the original CI_Session class, but also handles session management the same way that the CakeSession does. That includes timeouts, Security.salt config, User Agent checking, Session regeneration, and Flash messaging. This is the code I'm not going to give over.

It's a horrible hack.. a mish mash of the CakeSession and CI_Session, using CI for database access, and including the CakePHP String and Set classes for reuse. So while you've not got the code, you've got the basics of how to create your own CI_Session to use CakeSessions.

The End!

Now, I'm still in the middle of the development, and not everything has been tested, especially passing Flash messages from CakePHP to CI and visa versa. Hopefully, it's not something I'll have to deal with, but it's something on the list to take a look at.

I hope this has given you a little insight into how to integrate CakePHP with your legacy application.