Plugin loading quirks

On a daily basis I will receive emails pertaining to my Admin plugin, Utility plugin or my Forum plugin. Most of the time the problem they are having is related to plugin loading, and the failure to bootstrap or apply routes. But loading plugins is easy! One would think so, it does look pretty straight forward, but there are some weird cases where loading just does not work as you would assume.

In my documentation, I state that plugin loading should be done after CakePlugin::loadAll(), for the reasons listed below.

Using loadAll()

By default, CakePlugin::loadAll() does not include bootstrap or routes files. Passing an array with bootstrap and routes set to true will include them, but any plugin that does not have those files will throw missing errors. A setting ignoreMissing was added in CakePHP 2.3.0 to solve this. This approach works correctly, but not for versions below 2.3.0.

CakePlugin::loadAll(array(
	array('bootstrap' => true, 'routes' => true, 'ignoreMissing' => true)
));
Calling loadAll() last

One would think that calling CakePlugin::loadAll() after other plugins would work normally, but that's wrong. When called this way, previously loaded routes will be reset. This happens because loadAll() cycles through each plugin and re-loads them (even if a plugin was already loaded), and since both bootstrap and routes are false by default (point above) in loadAll(), the values get reset. Honestly, I believe this to be a bug in CakePHP, so when I have time I will track it down. Currently, this approach does not work correctly.

CakePlugin::load('Utility', array('bootstrap' => true, 'routes' => true));
CakePlugin::load('Admin', array('bootstrap' => true, 'routes' => true));
CakePlugin::load('Forum', array('bootstrap' => true, 'routes' => true));
CakePlugin::loadAll();
Calling loadAll() first

If calling it last doesn't work correctly, then calling it first will. By calling CakePlugin::loadAll() first, all the problems listed in the point above are invalid and plugin loading works correctly. Both routes and bootstrapping successfully triggers. This approach works correctly.

CakePlugin::loadAll();
CakePlugin::load('Utility', array('bootstrap' => true, 'routes' => true));
CakePlugin::load('Admin', array('bootstrap' => true, 'routes' => true));
CakePlugin::load('Forum', array('bootstrap' => true, 'routes' => true));
Passing an array to load()

Many don't know this, but an array of plugins can be passed to CakePlugin::load(). I tried many different combinations with no failures. This approach works correctly.

CakePlugin::load(array(
	'Uploader',
	'Utility' => array('bootstrap' => true, 'routes' => true),
	'Admin' => array('bootstrap' => true, 'routes' => true),
	'Forum' => array('bootstrap' => true, 'routes' => true)
));
CakePlugin::load(
	array('Utility', 'Admin', 'Forum'),
	array('bootstrap' => true, 'routes' => true)
);
How did you debug this?

It was rather easy. In Config/bootstrap.php I would attempt different variations of plugin loading to test the outcome. In my controller I had a few debug() statements that spit out Configure and Router information to verify that loading was working.

debug(App::objects('plugin'));
debug(Configure::read());
debug(Router::$routes);

Single or multiple feed aggregation?

I recently published a beta version of my feeds plugin for CakePHP. This plugin was previously the FeedAggregator component, but it made more sense to break it up into a datasource and model, and finally package as a plugin. The datasource is pretty straight forward as it accepts an array of URLs (RSS feeds), fetches each one through an HTTP request, parses the XML into an array, and then returns the result. The model is simply there for your convenience.

Now the dilemma I am running into is whether or not the datasource should only parse one feed at a time or multiple feeds (currently this). It can go either way: the datasource parses multiple feeds and uses the model to return them, or the datasource parses one feed and the model manages multiple connections and merging. Now the big question for you guys... Should the datasource parse one feed at a time or multiple feeds?

Currently you use the model to pass an array of URLs (through the conditions option), the limit, which fields (elements in the XML) you want returned, and some cache/feed settings. Here is a quick example:

// Multiple feed parsing
$feeds = $this->Aggregator->find('all', array(
	'conditions' => array(
		'Starcraft 2 Armory' => 'http://feeds.feedburner.com/starcraft',
		'Miles Johnson' => 'http://feeds.feedburner.com/milesj'
	),
	'feed' => array(
		'cache' => 'feedCacheKey',
		'expires' => '+24 hours',
		'explicit' => true
	)
));

And I am assuming single feed parsing would look something like this:

$feed = $this->Aggregator->find('first', array(
    'conditions' => array('http://feeds.feedburner.com/milesj'),
    'feed' => array(
        'cache' => 'feedCacheKey',
        'expires' => '+24 hours',
        'explicit' => true
    )
));

I am kind of split on how I should go about this and would really love your opinion. I am currently leaning towards multiple feed parsing (current implementation), but if someone has a good argument in not doing so, I will change it.

Upgrading the forum plugin to 1.8

I have been working on the new 1.8 version of the forum for almost 2 months, simply because version 1.7 was completely broken. It used PHP 5.3 constants which didn't work on 99% of the users machines. This problem has now been corrected in the new 1.8 version, but that's not all that changed. All topics, forums and forum categories now use the sluggable behavior for pretty URLs. Furthermore, the Installer has been rewritten completely for faster and easier usage. The main purpose of this post is to direct you in the 1.8 upgrade process as there are many things you need to do.

Overwriting an older version

You will need to overwrite ALL files within the plugin. Basically every view, every model, every controller, etc has been modified in some way; primarily to support the new slugs. Sorry to all those who have changed the HTML.

Patching your plugin

The new installer system creates a legacy config file to be used for future upgrades and to maintain the current installation. If you are doing a fresh install, you can skip this step. Once you have updated all the files, you will need to patch your installation to build that config file. You can do this from within the install controller.

yourdomain.com/forum/install/patch

The patch process will require 3 things: the database config you want to use, the table prefix value (if you have one) and a checkbox that determines if you used the plugins native user table or a pre-existing one.

Upgrading the database

With the new slug changes, it requires you to upgrade your database tables with the new column and all rows to be populated with their slug equivalent. This process takes 2 steps to achieve, the first having you run an SQL command from within the installer. You can access this process at the URL below.

yourdomain.com/forum/install/upgrade_1_8

The second step requires you to use the Cake console and to run the slugify shell. This shell will populate all the empty slug rows (it can be used any time, not just the upgrade process). Your shell command may look like the following.

cake -app /path/to/app slugify
Fresh install

If you are running a fresh install, the process is extremely simply. Just go to the install controller, hit the "Begin Installation" button and follow the steps. The process will check your database for conflicts, create the tables, patch the install and create the admin user. I tried to make it as simply and straight forward as possible.

See if it's working!

Whether you did a fresh install, or patched an old one, the last thing to do is actually use the forum. You should be checking to make sure all the slugs were generated, the pages work, the links link correctly, so on and so forth. If you find a bug or problem, PLEASE report it to me so I can fix it.

Enjoy! (Sorry for the long wait time)

Cupcake and Uploader plugins updated

I want to thank everyone who has tested my forum plugin, and thanks again for all the people who reported bugs and features! The plugin is coming along nicely and I have a few features planned for the future. Cupcake has been updated again to provide more multi-byte character support and fix all the reported bugs. Additionally, I have added a quick-reply feature which can be enabled or disabled through the settings.

The Uploader plugin has also received an update, for there was a major bug, the validation never worked! This was my fault because it seems like I removed a reference variable to the parent model (&$Model) which would never update the primary model outside of the behavior, and in turn the validation never worked. I also updated the plugin with multi-byte support.

Come have a Cupcake, open beta released!

The time has arrived, I have pushed my Cupcake Forum plugin into public beta. You may now download and use the plugin as you wish, but be weary because its still in beta, so problems may arise. If you run into a bug, please post it on the GitHub issues. I also want to thank Matt Curry for testing the plugin beforehand, just like he tested the Uploader plugin, so give him your thanks as well. Heres a quick overview of Cupcake:

The Cupcake Forum is a slimmed down version of the popular bulletin board system, packaged into a plugin. The plugin can be dropped into any CakePHP application and will run smoothly with a bit of configuration. The plugin comes bundled with all the basic features of a stand-alone system, some of which include topics, posts, users, polls, moderators, staff and more. For a full list, view the chapter regarding Features.
Donations

I was originally going to only sell the plugin, but chose against that, simply because it doesn't deserve to be purchased, if anything CakePHP as a whole does. So instead I have added a donation button underneath all the download buttons. So if you really really love my scripts, donate, or else ill take all my scripts down! Yeah maybe.

Cupcake forum plugin, it's pretty delicious

If you have been following me on Twitter, you may of heard me mention a new CakePHP plugin I am developing, a forum plugin. Well I am officially announcing it as the Cupcake Forum Plugin. It is basically complete, but I would like to run a few more tests and perhaps get an "installer" type script. Alongside this announcement, I have uploaded the forum plugin onto this domain as a demo, and will be using it as a support forum for all my scripts. Click the screenshot of the forum to view the demo.

Cupcake isn't as robust as regular forum systems, that would be absurd. Instead it has all the necessary basic features for fully utilizing a forum. Some of those features include: users and profiles, topics, replying, sub-forums, read topics, flood protection, topic auto lock, hourly post and topic limitations, access levels and permissions, moderators, searching, locking mechanisms, sticky and important topic types, topic and post reporting and many more. Oh and that's not all, it also comes bundled with a built in administration panel where you can manage all aspects of the forum, instead of having to do it manually in the database.

I will be releasing the plugin sometime this week. If you have any suggestions for features, be sure to send me an email or reply to this entry. Looking forward to all your feedback on this, it took quite a while to develop!

Uploader Plugin officially released!

For the past month I have been talking about CakePHPs lack of a built in uploader component or mechanism, and how I wanted to build one. Well wouldn't it be great if I actually did build it? Oh wait, what is this? I did build one? Yes. Is it released? Yes. May I use it? Of course! The Uploader is primarily used as an all purpose file uploader and was built to not interact with a model/database. Here is a quick rundown of the plugin.

The plugin comes bundled with an uploader component and a validation behavior. The component is used to upload the files to a destination, resize or generate images, validate against mime types, log errors, scan for viruses and more. The behavior is used to add validation rules to a model to check against image uploads.

A big thank you to http://mark-story.com/ and Matt Curry for beta testing and giving input and ideas.

- Download Uploader v1.3 and view full documentation