Changelogs: Uploader v4.4.0

A new version of Uploader has been released, version 4.4.0. Please download the new tag or view the documentation. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, report an issue on the GitHub repository.

Version: 4.4.0
Tested On: PHP 5.4.3, CakePHP 2.3.8, Composer
Requires: PHP 5.3, CakePHP 2.3, Composer
Commit Hash: cd5b91840a6910cd93bfd3a9791285be98460ffe
Changes:

  • Includes changes from previous versions
  • Fixed interface changes for CakePHP 2.4
  • Fixed an issue with file validation failing on PHP 5.3 [#136]
  • Fixed empty upload error logging problem [#152]
  • Fixed record deletion problem because of invalid model ID [#149]
  • Refactored so that defaultPath is applied in afterFind() [#147]
  • Added support for custom transformers and transporters

Changelogs: Forum v5.0.0

A new version of Forum has been released, version 5.0.0. Please download the new tag or view the documentation. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, report an issue on the GitHub repository.

Version: 5.0.0
Tested On: PHP 5.4.3, CakePHP 2.3.8, Composer
Requires: PHP 5.3, CakePHP 2.3, Composer
Commit Hash: d5ad0cdf0a133aef3e4472747242b2331e053339
Changes:

  • New design and layout using Titon Toolkit
  • Integrated more seamlessly with Admin v1.1.0
  • Includes the new post rating and access system from v4.1.0
Developer Notes

This update contains a complete rewrite of all the views. This means that all the old classes, markup and structure has changed. Be sure to update your code if you used custom layouts or views.

If you have not upgraded to 4.1.0 yet, be sure to run the upgrader from the command line or else 5.0.0 won't work correctly! If you are doing a fresh install of 5.0.0, this upgrade is not required.

Console\cake Forum.upgrade

Changelogs: Admin v1.1.0

A new version of Admin has been released, version 1.1.0. Please download the new tag or view the documentation. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, report an issue on the GitHub repository.

Version: 1.1.0
Tested On: PHP 5.4.3, CakePHP 2.3.8, Composer
Requires: PHP 5.3, CakePHP 2.3, Composer
Commit Hash: dd598ec1074cd2e63fd5ceeea86b838eec3a7c18
Changes:

  • Added ACL and roles detection into the session layer (allows for easy use between plugins)
  • Added ClassRegistry::init() in Admin::introspectModel() as it resolves includes successfully
  • Added a badge counter system to Admin.menu items
  • Replaced Twitter Bootstrap with Titon Toolkit
  • Improved usability and user experience

Changelogs: Forum v4.1.0

A new version of Forum has been released, version 4.1.0. Please download the new tag or view the documentation. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, report an issue on the GitHub repository.

Version: 4.1.0
Tested On: PHP 5.4.3, CakePHP 2.3.8, Composer
Requires: PHP 5.3, CakePHP 2.3, Composer
Commit Hash: 93d289d69281e1432150fa88d34083a565b1fcab
Changes:

  • Added new access setting to ForumToolbar.verifyAccess()
  • Added a new post rating feature which allows for up down scoring of posts
  • Added email template support to subscriptions through Forum.settings.subscriptionTemplate
  • Added custom image icon support to forums
  • Refactored Forum table so that accessRead, accessPost, accessReply, and accessPoll all point to ARO records
  • Removed aro_id column from Forum (use accessRead instead)
  • Renamed certain session variables to be prefixed with Acl instead of Forum
  • Replaced ForumHelper.gravatar() with UtilityHelper.gravatar()
Developer Notes

A new post rating feature has been implemented, which allows logged in users to rate a post up or down. When posts reach a specific negative threshold, the post will be buried and the avatar and signature of the user will be removed. Five new settings have been added for ratings: enablePostRating, showRatingScore, ratingBuryThreshold, rateUpPoints, and rateDownPoints.

The other major change is the refactoring of the forums table. The old columns accessRead, accessPost, accessReply, and accessPoll were pretty much useless after the 4.0.0 migration to ACL. In 4.1.0 I changed them to point to ARO records allowing full control over who sees and does what. With this change the aro_id column has been removed, which is mimicked by accessRead anyways.

Be sure to run the upgrade script from the command line.

Console\cake Forum.upgrade

Changelogs: Uploader v4.3.0

A new version of Uploader has been released, version 4.3.0. Please download the new tag or view the documentation. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, report an issue on the GitHub repository.

Version: 4.3.0
Tested On: PHP 5.4.3, CakePHP 2.3.6, Composer
Requires: PHP 5.3, CakePHP 2.3, Composer
Commit Hash: 6bcd77330c5e7a4ce62f60d633b19dfba05e6a50
Changes:

  • Includes changes from previous minor versions
  • Updated Transit to v1.4.0
  • Added transportDir setting for uploads and transforms which allow custom transport directory paths [Issue #125]
  • Added fit transformer that allows for fitting an image to a certain size while applying a background fill
  • Added 4th argument to AttachmentBehavior.deleteFiles() to circumvent database hit
  • Reversed move and rename logic so transformed files do not conflict
  • Fixed bug where empty file paths trigger error on deletion [Issue #126]

Persisting data through legacy routes

Usually when a website is migrated to a new version or system, old URLs will break. To circumvent this problem, legacy URLs are redirected to their new destination through some kind of router. CakePHP offers this functionality through Router::redirect() and the RedirectRoute class. But how do you persist URL parameters (like IDs) to the new URL? It's pretty simple.

When I launched the new version of this site, I had to setup legacy routes for blog posts. The old URLs were structured as so blog/read/[id]/[inflected_title], where the new ones are structured like blog/read/[slug]. From the looks of it, no parameters are the same, so this will require a middleman controller. First, I need to map the redirect using the persist option (this is crucial).

Router::redirect('/blog/read/:id/*', array('controller' => 'jump', 'action' => 'blog'), array(
	'id' => '[0-9]+',
	'pass' => array('id'),
	'persist' => array('id')
));

This route will redirect the old URL to JumpController::blog($id) while passing the ID from the URL as the first argument. The JumpController is used to power my tiny URLs — so it now serves 2 purposes. Next up is defining the action logic.

public function blog($id = null) {
	if ($blog = $this->Entry->getById($id)) {
		$this->redirect(array('controller' => 'blog', 'action' => 'read', $blog['Entry']['slug']), 301);
	}
	throw new NotFoundException();
}

When the action is called, the code attempts to find a blog entry that matches the ID. If an entry is found it will redirect with a 301 (Moved Permanently), else it throws a 404 (Not Found). That's all there is too it!

Changelogs: Uploader v4.2.0

A new version of Uploader has been released, version 4.2.0. Please download the new tag or view the documentation. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, report an issue on the GitHub repository.

Version: 4.2.0
Tested On: PHP 5.4.3, CakePHP 2.3.1, Composer
Requires: PHP 5.3.3, CakePHP 2, Composer
Commit Hash: 7164f34197bcf8844f880af714929eb9efbdfaec
Changes:

  • Updated Transit requirement to 1.3
  • Added a rotate transformer that accepts a degrees setting
  • Added a exif transformer that fixes orientation and strips Exif data (should be applied first with self)
  • Added a defaultPath setting to transforms

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);

Changelogs: Uploader v4.1.0

A new version of Uploader has been released, version 4.1.0. Please download the new tag or view the documentation. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, report an issue on the GitHub repository.

Version: 4.1.0
Tested On: PHP 5.4.3, CakePHP 2.3.1, Composer
Requires: PHP 5.3, CakePHP 2, Composer
Commit Hash: f2cad62f01c8aedc262692a54ea5d5ed272f4224
Changes:

  • Includes changes from 4.0.12 - 4.0.15
  • Updated Transit requirement to 1.2
  • Updated extension parsing to extract the value from the filename
  • Updated mimetype parsing to extract the value from multiple sources: file -b --mime command, then fileinfo, then $_FILES['type']
  • Fixed a bug where beforeUpload(), beforeTransform() and beforeTransport() callbacks were not being triggered for record deletions
  • Fixed a bug where $this->data is not available within callbacks

Changelogs: Forum v4.0.0

A new version of Forum has been released, version 4.0.0. Please download the new tag or view the documentation. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, report an issue on the GitHub repository.

Version: 4.0.0
Tested On: PHP 5.4.3, CakePHP 2.3.1, Composer
Requires: PHP 5.3, CakePHP 2.3, Composer
Commit Hash: bcea4ec25587acf89af064463088ba5eb981e8e3
Changes:

  • Replaced the custom ACL system with CakePHP's ACL
  • Replaced the admin system with the Admin plugin
  • Replaced the reporting system with the Admin plugin reporting system
  • Replaced the logging system with the Admin plugin logging system
  • Integrated the new Utility 1.4 features
  • Integrated the TreeBehavior where applicable
  • Rewrote the InstallShell and UpgradeShell
  • Removed the Profile model (the old fields should now be part of the users table)
  • Removed Spanish and Swedish locales (too many strings changed)
  • Removed user profiles (all user related code should be handled outside of the forum)
  • Added a ForumUser model that extends from the base User model
  • Added counter caching for topics and posts for the User model
  • Added counter caching for poll votes and options