If you find the new Xanthia templating system or other block or templating systems a bit complex or overkill for your block placement needs, or would like to be able to use one of the many "classic" themes available but would like advanced block placement options, then check out the post below:
The following post outlines an enhancement that you can make for your
PostNuke Blocks to easily specify module and page-specific placement of blocks directly from the Admin/Blocks menu. For each block, in addition to the left/right/center zones, you will have a drop down to specify whether to display the block on all pages, display it on selected modules and pages, or to NOT display it on the selected modules and pages. Below the dropdown is a checkbox list of all available *user* modules which you can optionally check off to specify module-specific placement. Below that is a textbox where you can specify additional page-specific IDs for block placement (such as sid for News articles, artid for Sections, etc...). While not as flexible as some of the templating systems, the implementation is quite simple (all menu-driven from the Blocks admin) and compatible with the many "default"-type
PostNuke themes available. More notes on usage are at the bottom of this post.
The enhanced blocks modification involves adding an extra field to your blocks table, and altering four files: pntables.php in your root directory, advblocks.php in your includes directory, and pnadmin.php & pnadminapi.php in your modules/Blocks directory. It's basically a cut 'n paste job (with the exception of creating the new
DB field) but is not recommended for "wet behind the ears" newbies ;).
Let's get started! (P.S. If the below seems a bit daunting - PM me with your email & I can send a set of files 2 U)
NOTE: The following mods were done on
PostNuke version .726. While they will not interfere with the new Xanthia templating system, the new system circumvents the usual methods for block placement so any page-specific options will be ignored. I'm fairly certain the mods below can be done with systems that provide "extra" block zones, but have not tried them. No warranty is implied etc..., etc... MAKE BACKUP COPIES OF ANY FILES YOU MODIFY. If you sucessfully make the modifications below, you are welcome to offer them as a download on your site.
UPDATE: The modded files described below are available here: http://www.natewelch.com/postnuke/ - They are based on the "pristine" blocks module files that came with the .726 version of
PostNuke. Upload and enjoy - however you will still need to make the alteration to your blocks table as described below or in the included readme.txt.
First, you'll need to create a new column in your nuke_blocks table called "pn_placement", just after "pn_position" to store the advanced placement information. You can either do this via
phpMyAdmin [26] or manually using the following command:
ALTER TABLE `nuke_blocks` ADD `pn_placement` TEXT NOT null AFTER `pn_position`;
Note: the above command assumes you are using "nuke_" as the prefix of your table - you may have specified something different when you installed
PN (check your dbase).
In the
pntables.php file in the
PostNuke root directory, in the $pntable['blocks_column'] array (starting around line 85) just after:
'position' => $blocks . '.pn_position',
add the following line:
'placement' => $blocks . '.pn_placement',
In the
advblocks.php file in the /includes directory, look in the blocks() function (starting at around line 53) for the line:
$result = $dbconn->Execute("SELECT $column[bid] as bid, $column[bkey] as bkey, $column[mid] as mid, $column[title] as title, $column[content] as content, $column[url] as url, $column[position] as position, $column[weight] as weight, $column[active] as active, $column[refresh] as refresh, $column[last_update] AS unix_update, $column[blanguage] as blanguage FROM $pntable[blocks] WHERE $column[position]='".pnVarPrepForStore($side)."' AND $column[active]=1 $querylang ORDER BY $column[weight]");
(at around line 70) and *replace* it with:
$result = $dbconn->Execute("SELECT $column[bid] as bid, $column[bkey] as bkey, $column[mid] as mid, $column[title] as title, $column[content] as content, $column[url] as url, $column[position] as position, $column[placement] as placement, $column[weight] as weight, $column[active] as active, $column[refresh] as refresh, $column[last_update] AS unix_update, $column[blanguage] as blanguage FROM $pntable[blocks] WHERE $column[position]='".pnVarPrepForStore($side)."' AND $column[active]=1 $querylang ORDER BY $column[weight]");
In the same file, around line 82, *replace* this code:
echo [27] pnBlockShow($modinfo['name'], $row['bkey'], $row);
$result->MoveNext();
With this code (checks the advanced placement values):
// NJW MOD START
// Break out options from our placement field and reset match flag
$placement_vars = pnBlockVarsFromContent($row['placement']);
$placement_match = 0;
// Show block if set to show on all pages.
if ($placement_vars['placement'] == 0) {
echo [28] pnBlockShow($modinfo['name'], $row['bkey'], $row);
$result->MoveNext();
continue;
}
// Loop through page-specific and module vars to determine a match...
$page_vars = explode [29](',',$placement_vars['pageshow']);
// Check for page-specific match - set flag if a match
while (list [30]($key, $val) = each [31]($page_vars)) {
if ($val && !ctype_digit [32]($val)) {
if (pnVarCleanFromInput($val) == intval [33]($page_vars[$key+1]) || (pnVarCleanFromInput($val) >= intval [34]($page_vars[$key+1]) && pnVarCleanFromInput($val) <= intval [35]($page_vars[$key+2]) && intval [36]($page_vars[$key+1]) != 0 && intval [37]($page_vars[$key+2]) != 0)) {
$placement_match = 1;
break;
}
}
} // end of while/each $page_vars loop
// Check for module-specific match - set flag if a match
while (list [38]($key, $val) = each [39]($placement_vars)) {
// Skip these variables (already processed)
if ($key == 'placement' || $key == 'pageshow')
continue;
// Check for special "Home Page" module
if ($key == 'Home_Page' && !$_SERVER['QUERY_STRING'] && substr [40]($_SERVER['SCRIPT_NAME'], -9) == 'index.php') {
$placement_match = 1;
break;
}
// Check for no module setting
if ($key == 'No_Module' && !pnModGetName()) {
$placement_match = 1;
break;
}
if ($key == pnModGetName() && $placement_vars[$key] == 1) {
$placement_match = 1;
break;
}
}
// Determine whether to add or exclude block based on match flag and placement selection
if ($placement_match == 1 && $placement_vars['placement'] == 1 || $placement_match == 0 && $placement_vars['placement'] == 2) {
echo [41] pnBlockShow($modinfo['name'], $row['bkey'], $row);
$result->MoveNext();
} else {
$result->MoveNext();
}
// NJW MOD END
In the same file (advblocks.php) look for the function, pnBlockGetInfo(). Look in the SELECT statement 6-7 lines down for the line:
and add the following line just beneath it:
$blockscolumn[placement],
Further down in the same function look for the "list" statement for the line:
and add the following line just after it:
In the
pnadmin.php file in the modules/Blocks directory find the blocks_admin_modify() function (starting around line 390). Look around line 472 for the start of where the block "position" menu is output. Scroll down a bit to about line 490 where you will see this code:
Just *after* that line, paste the following code (adds the extra menu options for block placement):
// NJW MOD: Break out options from our content field
$vars = pnBlockVarsFromContent($blockinfo['placement']);
// NJW MOD: Add select list for module placement
$row = array [42]();
$output->SetOutputMode(_PNH_RETURNOUTPUT);
$row[] = $output->Text(pnVarPrepForDisplay('Block Display:'));
$row[] = $output->FormSelectMultiple('placement',
array [43](array [44]('id' => '0',
'name' => 'Show on all modules and pages'),
array [45]('id' => '1',
'name' => 'Show on only the selected modules and pages'),
array [46]('id' => '2',
'name' => 'Do not show on the selected modules and pages')),
0,
1,
$vars['placement']);
$output->SetOutputMode(_PNH_KEEPOUTPUT);
$output->SetInputMode(_PNH_VERBATIMINPUT);
$output->TableAddRow($row, 'left');
$output->SetInputMode(_PNH_PARSEINPUT);
//$output->Linebreak(2);
// NJW MOD: Add checkbox group for module placement (checkbox name is module name)
// Plus an extra checkbox for the Home Page
$row = array [47]();
$output->SetOutputMode(_PNH_RETURNOUTPUT);
$row[] = $output->Text(pnVarPrepForDisplay('Modules:'));
$mods = pnModGetUserMods();
$mod_row .= '<nobr>'.$output->FormCheckbox('Home_Page',$vars['Home_Page']).' '.$output->Text('Home Page').' </nobr>';
foreach($mods as $mod) {
if ($mod['directory'] == 'AvantGo')
continue;
$mod_row .= '<nobr>'.$output->FormCheckbox($mod['directory'],$vars[$mod['directory']]).' '.$output->Text(pnVarPrepForDisplay($mod['displayname']).' ').' </nobr>';
}
$mod_row .= '<nobr>'.$output->FormCheckbox('No_Module',$vars['No_Module']).' '.$output->Text('Other/No Module').' </nobr>';
$row[] = $mod_row;
$output->SetOutputMode(_PNH_KEEPOUTPUT);
$output->SetInputMode(_PNH_VERBATIMINPUT);
$output->TableAddRow($row, 'left');
$output->SetInputMode(_PNH_PARSEINPUT);
//$output->Linebreak(2);
// NJW MOD: Add textarea for page-specific placement string
$row = array [48]();
$output->SetOutputMode(_PNH_RETURNOUTPUT);
$row[] = $output->Text(pnVarPrepForDisplay('Page Specific ID\'s:'));
$row[] = $output->FormTextArea('pageshow',$vars['pageshow'],3,40);
$output->SetOutputMode(_PNH_KEEPOUTPUT);
$output->SetInputMode(_PNH_VERBATIMINPUT);
$output->TableAddRow($row, 'left');
$output->SetInputMode(_PNH_PARSEINPUT);
//$output->Linebreak(2);
In the same file, in the blocks_admin_update() function, look for this code:
if (phpversion [49]() >= "4.2.0") {
$_pv = $_POST;
} else {
global [50] $HTTP_POST_VARS;
$_pv = $HTTP_POST_VARS;
}
Just after it, paste in the following code:
// NJW MOD: Manually serialize vars and unset "extra" arguments
$_pv['placement'] = "placement:=".$_pv['placement']."\npageshow:=".$_pv['pageshow'];
unset [51]($_pv['pageshow']);
$mods = pnModGetUserMods();
// Special "Home Page" module
if ($_pv['Home_Page']) {
$_pv['placement'] .= "\nHome_Page:=1";
}
unset [52]($_pv['Home_Page']);
// Special vars if no module present
if ($_pv['No_Module']) {
$_pv['placement'] .= "\nNo_Module:=1";
}
unset [53]($_pv['No_Module']);
foreach($mods as $mod) {
if ($_pv[$mod['directory']]) {
$_pv['placement'] .= "\n".$mod['directory'].":=1";
}
unset [54]($_pv[$mod['directory']]);
}
$placement = $_pv['placement'];
// NJW MOD: End
Further down in the same function, look for this line:
$blockinfo['position'] = $position;
and add this line of code just beneath it:
$blockinfo['placement'] = $placement;
Lastly, in the
pnadminapi.php file in the modules/Blocks directory look in the blocks_adminapi_update function for the argument check. Look for this line:
(!isset [55]($refresh)) ||
and add the following just after it:
(!isset [56]($placement)) ||
A little further down in the same function and file, look in the UPDATE query for the line:
$blockscolumn[position]='" . pnVarPrepForStore($position) . "',
And add the following line just after it:
$blockscolumn[placement]='" . pnVarPrepForStore($placement) . "',
How do I use it?
First, a word about the theme you are using. The theme trumps all: many themes are set so that the right and/or center blocks will only show up on the News/home page. If you want *complete* control over the blocks, remove any "conditional" statements in your theme around the "blocks('right');" and/or "blocks('centre');" statements. Usually the conditional takes the form of "if ($GLOBALS['index'] { ... }". This will make all block zones appear on *every* page - until you specify otherwise. Also, any blocks you specify must be "active" and will appear in the order they are listed in the Blocks Admin (less the blocks not displayed for a given page).
Specifying Block Placement: When you go to edit a block (or just after it's created), you will have an additional drop-down menu, checkbox list and text box as described above.
If you want a block to appear on every page, such as the menu block, leave the drop-down set to "Show on all pages". Any further options you check or enter regarding placement will be ignored. Your other options are to set the block to appear on the specified modules and pages or to *NOT* show on the specified modules and pages.
Below the drop-down menu is a checkbox list representing all of the "user" modules available on your website. Modules such as "Comments", "Ratings", etc.. are not displayed as they have no direct module output pages. Simply check off the modules where you would like the block to show up on (or not show up on) as selected in the drop-down menu above.
A NOTE ON THE MODULE LIST: This is grabbed in "real-time", thus if you add a module to your
PN website, you must go back to each of the blocks you would like to associate with that module and check the box for it. Alternately, if you remove a module and go to update a block, that module will be removed from the checkbox list.
Lastly is the page-specific placement of blocks which will allow you place blocks for particular stories, polls, etc... It works by looking for ID's passed to
PostNuke via URLs... For example, when viewing a news story, you will often see "sid=5" in the
URL (or for "short URLs" story5.html - you can look in the admin to see the "long" URLs & IDs). You can specify both module-specific and page-specific placement as needed; however, the module placement takes precident - so if you specify the block to show on the News module *and* for sid #5, the block will show on all news stories. If a specified ID is not "passed" to
PN for a particular page, its placement for that ID will not be recognized (for example, a topic id is not passed when viewing a specific story (sid)).
To specify page-specific placement, you enter the page's ID marker (sid, artid, cid, etc...) followed by one or two numeric values representing either a specific page or a range of pages - separated by commas. The order is not important.
For example, to specify a block show (or not show) on a news story whose sid is 5, enter:
To specify a block show on stories with sid's from 5 to 10, enter:
Only one or two values can follow an ID marker, so if additional values are needed you must reenter the marker. For example, to specify sids from 5 through 10, 16, and 18 through 20, enter:
sid,5,10,sid,16,sid,18,20
You can also combine different id's together, so long as they are separated by commas:
sid,5,10,cid,12,14,cid,28,artid,7
You can put them on separate lines for organization purposes, however you must end the lines with a comma:
sid,5,10,
cid,12,14,cid,28,
artid,7
Note: ID markers are CASE-SENSITIVE. Most, but not all, are all lower case values. Some examples are:
sid - a news article id;
topic - a news topic id;
secid - a section id;
artid - a section article id;
catid - a category of articles;
cid - A Web Links Category;
lid - a Web Links detail page;
id - a Reviews page,
PollID - a poll results page.
You can use any ID marker that appears in a
PostNuke URL.
Remember to select the drop-down above to specify placement or *NOT* placement on specific pages. If you revert a block to show on all pages, the values you enter for page-specfic and module-specific placement will be retained.
That's it! As always, if there are any comments or questions, please post them below... While the era of theme engines and
PN .8 is upon us, the old themes will still be compatible for the foreseeable future - and I thought it'd be fun to stretch their usefulness just a bit more... ;)
--
Get PhotoGallery, PayPalCart, Dynamenu, Enhanced Blocks & other mods [57]
Cape Cod [58] Travel Info...