Not sure whether other WP theme makers will disagree with me but the sidebar content was always – don’t get me wrong – crippled. Especially when we talk about single.php and page.php template files. It’s true, you can assign different sidebar to each and every template, make it widget ready but there’s not much left than having the very same sidebar content for all of your Posts or all of your Pages. What I am talking about is to have an option to control the sidebar content straight from Post/Page write panel and to be able to even set unique content for a certain Post or Page. To be honest, widgets are quite hard to be made, even for experienced WP programmer and the process takes time. And even if you are skilled enough and damn quick all of your Posts or Pages still have to share the same sidebar.
The main question was how to make an easy and acceptable solution even for an average WP theme maker? I guess an average WP theme maker is at least familiar with basic WP functions (methods, properties, objects) and knows how to include external file. On the other side are theme end users and these people are mostly tied to a common article publish routine. According to that fact, adding sidebar content to Post or Page must be as easy as mouse click.
After thinking a little bit I’ve came across quite acceptable solution: code snippets. More precisely, one snippet = one page which can be included in sidebar whenever is required, straight from Post/Page Write panel. Such ‘tiny’ pages should be placed in separate folder and share common prefix in file name because we are about to ease our job for the future. Let’s now consider the following situation…
As a theme coder you would like to enable your theme user an easy way to include latest comment in sidebar. You’ve made a piece of code which may look like this:
<?php
$cout_comments = 0; // internal counter
$show_comments = 1; // how many latest comments to display?
// get all approved comments but in reverse order; the latest one on top
$comment_array = array_reverse( get_approved_comments( $post->ID ) );
// any comments?
if( $comment_array ) {
foreach( $comment_array as $comment ) {
// we need $show_comments comment(s) only
if( $cout_comments < $show_comments ) {
// use predefined styles, widgets use'em as well
?>
<div class="box">
<h1>Latest comment by <?php comment_author_link(); ?></h1>
<p>
<?php
// get user gravatar - if any
$comment_text = get_comment_text();
$author_email = $comment->comment_author_email;
echo get_avatar( $author_email, '80' );
echo $comment_text;
?>
</p>
</div>
<?php
break;
}
$cout_comments ++;
}
}
?>
Now we need to save our code snippet. As already mentioned before, we’ll create new folder within our theme folder named ‘pluggers’ and save this code snippet as ‘plugger_LatestComment.php’. All other code snippets will be saved in ‘pluggers’ folder and use ‘plugger_’ in name prefix. However, if you don’t like to use phrase ‘plugger’ – go ahead and make up your own. In this tutorial we’ll keep using ‘plugger’.
Let’s now build user-friendly interface in Admin panel which will be used to insert our code whenever is required. This part is based on great tutorial published by WeFunction and I strongly recommend to read it for better understanding of what we are about to do here. The following code must be included in functions.php, that’s how we make it available to Post or Page write panel.
<?php
$array_values_post_page = array();
function sidebar_meta_boxes() {
global $post, $array_values_post_page;
// anything already writen in Custom Field?
if( get_post_meta( $post->ID, 'plugger_value', false ) ) {
$plugger_values_post_page = implode( ",", get_post_meta( $post->ID, 'plugger_value', false ) );
} else $plugger_values_post_page = "";
echo '<p style="padding: 5px 0;"><em>Tick the checkbox for each Plugger you want to be visible in sidebar, next to this article/page. Add sorting number to change the appearance order.</em></p><h4>List of available Pluggers:</h4><hr style="border: 1px dashed #F1F1F1; height: 1px;" />';
echo "<input type='hidden' name='plugger_value' id='plugger_value' value='" . $plugger_values_post_page . "' size='33'></input>";
if( $plugger_values_post_page != "" ) {
$array_values_post_page = explode( ",", $plugger_values_post_page );
}
// get all available Pluggers from a certain folder
$path = TEMPLATEPATH . "/pluggers";
$dir = opendir( $path );
while( ( $plugger_file = readdir( $dir ) ) !== false ) {
if( $plugger_file != "." && $plugger_file != ".." ) {
$data_aray = explode( "_", $plugger_file );
if( $data_aray[ 0 ] == "plugger" ) {
$checked = "";
$suffix = explode( ".", $data_aray[ 1 ] );
$val = "";
$in_position = key( preg_grep( "/{$suffix[ 0 ]}/i", $array_values_post_page ) );
// pluggers are sorted by numbers, sorting position writen after plugger name like pluggerName:n
if( strlen( $in_position ) > 0 ) {
$in_p_arr = explode( ":", $array_values_post_page[ $in_position ] );
$val = $in_p_arr[ 1 ];
$checked = ' checked="checked"';
}
echo "<div style='width: 266px; clear: both; overflow: hidden; padding: 5px 0; border-bottom: 1px solid #F1F1F1;'>";
echo "<div style='float: left; display: inline; width: 170px; padding-top: 8px;'>";
echo "<input style='margin-right: 5px;' type='checkbox' id='" . $suffix[ 0 ] . "' name='plugger_names' value='" . $suffix[ 0 ] . "' " . $checked . " onchange='addPostPagePluggers()' />";
echo "<label for='" . $suffix[ 0 ] . "'>" . $suffix[ 0 ] . "</label>";
echo "</div>";
echo "<div style='float: left; display: inline; width: 95px;'>";
echo "<input type='text' style='margin-right: 5px; width: 26px;' name='sort_" . $suffix[ 0 ] . "' id='sort_" . $suffix[ 0 ] . "' value='" . $val . "' size='2' onchange='addPostPagePluggers()'></input>";
echo "<label for='sort_" . $suffix[ 0 ] . "'>sort num.</label>";
echo "</div>";
echo "</div>";
}
}
}
closedir( $dir );
?>
<script language="javascript" type="text/javascript">
function addPostPagePluggers() {
// watch for checkbox activity and sort out elements for the frontend
var val = "";
var old = document.getElementById( "post" ).plugger_value; // hidden field which holds an array of name-value pairs
var cbs = document.getElementById( "post" ).plugger_names; // an array (names) of available pluggers represented via check boxes
for( var n = 0; n < cbs.length; n ++ ) {
if( cbs[ n ].checked ) {
var sort_field = eval( "document.getElementById( 'post' ).sort_" + cbs[ n ].id );
var sort_num = parseInt( sort_field.value );
if( isNaN( sort_num ) ) sort_field.value = n + 1;
val += cbs[ n ].value + ":" + sort_field.value + ",";
} else {
var sort_field = eval( "document.getElementById( 'post' ).sort_" + cbs[ n ].id );
sort_field.value = "";
}
}
var temp = val.split( "," );
temp.pop();
// sort by :n
temp.sort( function compareStrnum( a, b ) { return a.replace( /[^.0-9]/g, "" ) - b.replace( /[^.0-9]/g, "" ) } );
old.value = temp.toString();
}
</script>
<?php
}
// save settings on Admin level routine
function create_meta_box() {
if ( function_exists('add_meta_box') ) {
add_meta_box( 'sidebar_meta_boxes', 'Pluggers to include in Page Sidebar', 'sidebar_meta_boxes', 'page', 'side', 'high' );
add_meta_box( 'sidebar_meta_boxes', 'Pluggers to include in Post Sidebar', 'sidebar_meta_boxes', 'post', 'side', 'high' );
}
}
function save_postdata( $post_id ) {
global $post, $array_values_post_page;
if ( 'page' == $_POST[ 'post_type' ] ) {
if ( !current_user_can( 'edit_page', $post_id ) ) return $post_id;
} else {
if ( !current_user_can( 'edit_post', $post_id ) ) return $post_id;
}
$data = $_POST[ 'plugger_value' ];
if( get_post_meta( $post_id, 'plugger_value' ) == "" ) {
add_post_meta( $post_id, 'plugger_value', $data, true );
} elseif( $data != get_post_meta( $post_id, 'plugger_value', true ) ) {
update_post_meta( $post_id, 'plugger_value', $data );
} elseif( $data == "" ) {
delete_post_meta( $post_id, 'plugger_value', get_post_meta( $post_id, 'plugger_value', true ) );
}
}
add_action( 'admin_menu', 'create_meta_box' );
add_action( 'save_post', 'save_postdata' );
?>
What this code is supposed to do? First, it’ll seek for all files in ‘pluggers’ folder whose name starts with ‘plugger_’. In the same time it checks whether a current Post or Page already has any of available Pluggers aassigned to it. Settings are kept in Custom Field of a current Post or Page so every time you are about to edit one of those the list of available Pluggers and already selected ones is properly populated.
Javascript watches for all the changes made to the list and sorts it out immediately. That’s how we can get all of selected Pluggers properly sorted in frontend. The last two functions are used to insert our meta box to Post/Page sidebar write panel and save settings to database.
So far we’ve created Plugger unit called ‘plugger_LatestComment.php’ and meta box which will be displayed in Post/Page write panel (sidebar). Now we just have to get certain Custom Field value out of the Post/Page and display it in frontend. For a case you didn’t notice in save_postdata() function is the name of our Custom Field plugger_value which is either supposed to be created, updated or deleted – according to meta box selected value(s). Here is the piece of code used to pull required meta values out of the Post or Page:
<?php
$post_data = get_post_custom_keys( $post->ID );
foreach( $post_data as $postKey ) {
// remove orphans
$value_trimmed = trim( $postKey );
if ( '_' == $value_trimmed{0} ) continue;
// what we have here?
$postKey_data[ $postKey ] = get_post_meta( $post->ID, $postKey );
// check for checkbox values
if( $postKey == "plugger_value" ) {
// compile file name
$filename_arr = explode( ",", $postKey_data[ $postKey ][ 0 ] );
$c = 0;
while( $c < count( $filename_arr ) ) {
$file_to_include = explode( ":", $filename_arr[ $c ] );
// include in sidebar
include( TEMPLATEPATH . "/pluggers/plugger_" . $file_to_include[ 0 ] . ".php" );
$c ++;
}
}
}
?>
For a case you want to display Pluggers above other widgets in sidebar – paste the code on the top of sidebar-single.php or sidebar-page.php. Otherwise paste it below widget reserved area – if any.
Hi!
Thanks for this great tut. I was wondering, what code should I use in functions.php to have options page to include available pluggers anywhere else (on homepage for example, homepage sidebar or wherever the pluggers code is)
Thanks.