First party Pages module is wonderful to handle static content and to provide unique URL. Unfortunately, it is a one trick pony as it is lacking any hierarchy structure to build a traditional menu builder as one would love.
Thankfully, Mark Huot’s plugin Page Nested Menu helps to build the navigation menu in the template and with a little hack in one single core file, I can get the page hierarchy showing up in proper order in the control panel.
Below is how I build a 2-level menu navigation for my site using strictly Pages module.
1. I assume you know how to run Pages module. If not, you should see the Pages module Quick Guide somewhere in this Wiki.
2. Create a custom field to determine the desired order to associated with your weblog. I called it “page_weight” and it should take a numeric value.
3. Install Mark’s Pages-Nest Menu plugin and use it to drive the menu. My codes look like this. Please notice that it is sorted by my specified field “page_weight” here.
<ul id="nav">
{exp:pages_nested_menu include_ul="no" status="open" include_root="yes" depth="2" order="page_weight"}
<a href="{pnm_page_url}" title="{pnm_title}">{pnm_title}</a>
{/exp:pages_nested_menu}
</ul>
4. You need to figure out the actual EE field id that is associated with the sorting field, probably using tool like phpMyAdmin. In my case, it is “field_id_5”.
5. Now, open up the file modules/pages/mcp.pages.php, add the following codes right AFTER the statement natcasesort($pages[‘uris’]). The line should be around line 140. You must replace any instance of field_id_5 to the one you actually use in your weblog.
// - the codes work only for 2-level menus
$query = $DB->query("SELECT entry_id, field_id_5 FROM exp_weblog_data WHERE weblog_id='$default_weblog'");
foreach($query->result as $row) {
$orders[$row['entry_id']] = $row['field_id_5'];
}
$parent_order=0;
foreach($pages['uris'] as $id=>$url) {
$segments = array_filter(preg_split('/\//', $url));
if (count($segments)==1) {
// root level
$pages['uris'][$id] = sprintf("d***",$orders[$id]).$url;
$parent_order = $orders[$id];
} else {
// second level
$pages['uris'][$id] = sprintf("d-d***",$parent_order, $orders[$id]).$url;
}
}
natcasesort($pages['uris']);
foreach($pages['uris'] as $id=>$url) {
$real_url = explode("***", $url);
$pages['uris'][$id] = $real_url[1];
}
6. The pages should now show up in order in the control panel. Enjoy!
EDIT: 2008.07.03
Similarly, if you are working on a three-level menus, your codes may look like this;
// - the codes work for a 3-level menus
$query = $DB->query("SELECT entry_id, field_id_5 FROM exp_weblog_data WHERE weblog_id='$default_weblog'");
foreach($query->result as $row) {
$orders[$row['entry_id']] = $row['field_id_5'];
}
$parent_order=0;
$parent2_order=0;
foreach($pages['uris'] as $id=>$url) {
$segments = array_filter(preg_split('/\//', $url));
if (count($segments)==1) {
// root level
$pages['uris'][$id] = sprintf("d***",$orders[$id]).$url;
$parent_order = $orders[$id];
} else if (count($segments)==2) {
// second level
$pages['uris'][$id] = sprintf("d-d***",$parent_order, $orders[$id]).$url;
$parent2_order = $orders[$id];
} else {
// third level
$pages['uris'][$id] = sprintf("d-d-d***",$parent_order, $parent2_order, $orders[$id]).$url;
}
}
natcasesort($pages['uris']);
foreach($pages['uris'] as $id=>$url) {
$real_url = explode("***", $url);
$pages['uris'][$id] = $real_url[1];
}
