Databasic 2.1, now with more operator support!

I got pretty bored the other day and also noticed this contest over at NetTuts, and thought to myself, "Why not enter Databasic into the contest?". Well that is my plan, but I also wanted to fix some problems and restraints in the current version. The new version supports AND/OR operators in the conditions, as well the column operators (!=, <=, etc) have been rebuilt. With this change the new version is not backwards compatible! Sorry, but it shouldn't be too hard to fix your scripts to work correctly.

Here's a quick example of the new operator support in conditions.

$conditions = array(
    'OR' => array(
        array('name' => 'Miles'),
        array('name' => 'Johnson')
    ),
    'status' => 'active',
    'age >=' => 21
);

Download the new 2.1!
View the full change log and features

Toggling all checkboxes with JavaScript

Update You can view the comments for alternative and quicker ways to do this, enjoy!

Say you have a list of messages, and on the left of each message is a checkbox. This checkbox is used for a mass deletion or mass insert function here. Now to make it easier on the user, its nice to add a checkbox outside of the list that either checks them all, or dechecks them all. The following function can achieve that effect, using jQuery or regular JavaScript of course.

// Javascript
function toggleCheckboxes(current, form, field) {
	var val = current.checked;
	var cbs = document.getElementById(form).getElementsByTagName('input');
	var length = cbs.length;
	for (var i=0; i < length; i++) {
		if (cbs[i].name == field +'[]' && cbs[i].type == 'checkbox') {
			cbs[i].checked = val;
		}
	}
}
// jQuery
function toggleCheckboxes(current, form, field) {
	$("#"+ form +" :checkbox[name='"+ field +"[]']").attr("checked", current.checked);
}

Lets set up a quick example of how our form should be and how this function should be used properly. We will begin by adding the form tag with an id (required) and the message checkboxes.

<form action="" method="post" id="messageForm">
<input type="checkbox" name="messages[]" /> Message 1
<input type="checkbox" name="messages[]" /> Message 2
</form>

Let me explain the functions arguments before we finish up. The first argument should always be "this" so it can reference itself, the second argument would be the id of the containing form and the final argument would be the name of the checkboxes input name attribute (without the []). Now with that, we can finish this up by placing the following code anywhere on your page. Enjoy!

<label for="messages"><input type="checkbox" onclick="toggleCheckboxes(this, 'messageForm', 'messages');" /> Toggle all checkboxes</label>

Stripping HTML automatically from your data

About a week ago I talked about automatically sanitizing your data before its saved. Now I want to talk about automatically stripping HTML from your data before its saved, which is good practice. Personally, I hate saving any type of HTML to a database, thats why I prefer a BB code type system for this website. To strip all tags from your data, add this method to your AppModel.

/**
 * Strip all html tags from an array
 *
 * @param array $data
 * @return array
 */
public function cleanHtml($data) {
	if (is_array($data)) {
		foreach ($data as $key => $var) {
			$data[$key] = $this->cleanHtml($var);
		}
	} else {
		$data = Sanitize::html($data, true);
	}
	return $data;
}

Pretty simple right? The next and final step is to add it to AppModel::beforeSave(). In the next example, I will use the code snippet from my previous related article. Once you have done this your are finished, now go give it a test drive.

function beforeSave() {
	if (!empty($this->data) && $this->cleanData === true) {
		$connection = (!empty($this->useDbConfig)) ? $this->useDbConfig : 'default';
		$this->data = Sanitize::clean($this->data, array('connection' => $connection, 'escape' => false));
		$this->data = $this->cleanHtml($this->data);
	}
	return true;
}

Feed Aggregator Component officially released!

I recently needed the ability to display a list of feed items, but the catch was I needed them to be combined from multiple feeds, a feed aggregator. At first I was expecting to find this in the bakery, but was saddened when there was none. So I sat down and began coding. I've never created a feed aggregator before, but it was relatively easy.

Its really simple, the script is a CakePHP Component that will take a list of feeds and aggregate them into a single array based on their timestamp. It works with RSS 1.0 (RDF), RSS 2.0 and Atom 1.0 and has the ability to cache its results.

View full documentation and download version 1.1

Enjoy! Let me know if there are any bugs.

Automatically sanitizing data with beforeSave()

So if you are like me and hate having to sanitize or clean your data manually within each action, and was hoping there was an easier way, there is. Simple combine the magic of Model::beforeSave() and the powerful strength of Sanitize::clean().

function beforeSave() {
	if (!empty($this->data) && $this->cleanData === true) {
		$connection = (!empty($this->useDbConfig)) ? $this->useDbConfig : 'default';
		$this->data = Sanitize::clean($this->data, array('connection' => $connection, 'escape' => false));
	}
	return true;
}

The previous code will attempt to clean all data before it is saved. Secondly it will convert HTML, it will not strip tags completely. So if you do not want HTML in your database, you will need to add some extra functionality and set encode to false in the clean() options.

But that's not it, were not finished just yet. You may have noticed a $cleanData variable and are probably wondering what it does. This is a custom property that should be placed in your AppModel and IS NOT a CakePHP property. By placing it in the AppModel we will receive no error notices and all data will be cleaned, additionally you can disable cleaning in certain models by setting the property to false in the respective model.

public $cleanData = true;
Known Errors

So far this has worked smoothly, except for the following exception:

- Serialized arrays will be escaped incorrectly and will break when trying to unserialize(), simply set $cleanData to false to not escape the serialized arrays.

- When escape is set to true, all data will have slashes added on top of the slashes already added with the Model class, so its best to turn escaping off.