Using arrays of checkboxes to store and retrieve WordPress options

I wonder if you know what I mean...

I am into a complex task: for some time I’ve wanted to update the theme of this site and make it more versatile. Despite my obvious lack of time, the content is increasing steadily, so is the number of visitors, and I feel more and more often the need to structure better all these posts and pages.

WordPress is fun to work with, especially for a programming geek (which I am not). Since it is an open platform with all codebase available and with a comprehensive reference repository at one’s fingertip, makes it much more appealing than some other CMSs. Moreover, it has quite of a venerable age (10 years already) and matured enough to be considered a strong candidate even for some complex CMS requirements.

However, I ran into a stupid problem that I did not know to solve otherwise than using regular expressions and arrays. I assume there might be a more elegant solution but regular expressions have something so exotic and appealing in their nature. Consider the right sidebar category widget:

Sidebar category widget

I need to have the possibility to select categories that I need to display here. Not only on the landing page (home) but also depending on some other criteria.

One option would have been to enhance the widget, via the class I built that replaces the function.php file. Quite messy and I did want to have more flexibility with some admin options. Thus I create an admin page for this. On that page, I print all categories with checkboxes, even those with no posts attached:

$args = array(
	'hide_empty' => 0,
	);

Some CSS styling complete the picture (gray out and strike through checked items). Checking individual checkboxes allows exclusion of individual categories from the widget as in picture below:

Sidebar category widget admin page

I encountered several problems with this, especially at styling. God, I hate CSS ! Not per se, because it is a very cool idea, but all these rules and — most of all — exceptions, cross–browser incompatibilities and Microsoft’s stupidity with its own view on how things should be implemented, makes using CSS a nightmare. Honestly.

The problem here — and here my limitations in PHP become obvious — is that I did not find a simple and quick way to create an array of checkboxes that input an array–like entry in the options database table. They are stored under a high–level option entry and each checkbox has an unique name and id. I can customize these names and IDs but, basically, the entries in the options table have separate keys for each checkbox, and each key return an on or nothing, depending on the checkbox status. It seems obvious that, given this option structure, I cannot retrieve on the fly the entire array of values associated with the collection of checked options.

This grid of checkboxes (basically a 3–column table) is created by an utility function that has the following foreach loop:

foreach ($categories as $category_list ) {
	$counter++;
	echo $this->checkbox( $var.'_'.$category_list->cat_ID , __( $wp_cats[$category_list->cat_ID] = $category_list->cat_name . $this->alaconf_categories_posts_count( $category_list->count , $display_count ) ) );
	if ($counter > 10) :
		$counter = 0;
		?>
		</div>
		<div class="column">
		<?php
	endif;
}

The $counter variable is used for column formatting. The function that creates each individual checkbox has the following routine:

$output_input = "<input class="$class" id="'.esc_attr( $var ).'" type="checkbox" checked="checked" name="' . esc_attr( $option ) . '[' . esc_attr( $var ) .']" />';

where $var is the option attribute that is fed into the function to bind with corresponding entry in the database. The problem here is that checkboxes have the following database entry:

a:5:{s:23:"0_level_option";s:2:"on";s:22:"option_array14"; s:2:"on";s:22:"option_array15";s:2:"on";s:19:"option_test"; s:2:"on";s:17:"option_text";s:7:"testing";}

with option_arrayXX being the format of checkbox option key (“XX” are category IDs) that returns “on” if the checkbox is checked. So how can I retrieve from this database entry the IDs of the categories that I need to filter my widget in the sidebar ?

Probably a much more experienced PHP programmer would have written a better routine that generates the array of checkboxes (and probably I will seek doing so myself). But I thought that using regular expressions with array_keys could also solve the problem. And, as you will see, it did.

First thing I need to do is to retrieve the keys from the options array:

$options = get_option('0_level_option');
$keys = array_keys( $options );
$exclude = array(); // create an array to hold ID values to exclude from widget

Next, I have to loop over all keys in $options array and get only those that I am interested in, i.e. those with “array” word in their names:

foreach ( $keys as $key ) {
	if ( preg_match( '/\b(\w*array\w*)\b/' , $key ) ) :  // do something here

Next, I had to extract the category IDs from each key and fill in the array used for category exclusion, $exclude. The last step is to feed these category IDs to the function argument that will be used for my category filter:

	array_push( $exclude , substr( $key , strrpos( $key , '_' ) + 1, strlen( $key ) ) );
	endif;
}
$args["exclude"] = $exclude;
return $args;
}

Actually this worked pretty good and the dump looks like this:

var dump to check output of array_search: string(22) “alaconf_widget_array_2”
string(1)/ID: “2”
var dump to check output of array_search: string(22) “alaconf_widget_array_3”
string(1)/ID: “3”
var dump to check output of array_search: string(24) “alaconf_widget_array_188”
string(3)/ID: “188”

The numbers 2, 3 and 188 are category IDs of the excluded categories. Unfortunately I am not a regular expressions guru and it is a knowledge area that I always found more difficult to grasp than programming in assembler. For me it is completely counterintuitive, but I know people that swear by its straightforwardness. Will you give me a break ?

That’s it. Now I have a working options panel for selectively excluding what category I want from my sidebar widget. Probably I will reuse that function because this WordPress theme revamping process will take some time.

 
 
Filed in Wordpress and tagged , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *