Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Manu/Navigation helper functions
#1
Hi-

I am using a few custom functions in my site that I thought others might find handy.

I use child pages like so:
Gallery
-page1
-page2
-etc

And want gallery to be in my main menu, but all the child pages are NOT. I wanted to generate the gallery page dynamically, based on the child pages (add a new child page and the gallery page just updates) and I wanted navigation in the child pages (perv/next).

You can see the working code in my gallery page:


http://www.cartocopia.com/portfolio/


These calls parse all the pages' files so can be slow. I use my simplecache plugin, so after the first cache it is quite efficient:

Code:
<?php
/**
* custom function to return all the children of the page the function
* is called on.  Returns an array consisting of ('slug', 'title', 'order')
* sorted by order (which comes from the menuorder field of pages.  As
* a tip, you need to check "show page in menu" to set the menuorder value
* and then the display in menu can be unset so the childpage doesn't
* show up in the menu.
* ----
* call like:
* $childpages = return_child_data;
*
* optionally provide a different page slug as a parameter to get the children of a
* different slug.  This method is used in the prev and next functions:
* $childpages = return_child_data('differentpageslug');
* ----
* access data like:
* foreach($childpages as $page) {
*   echo "Slug: " . $page['slug'];
*   echo "Title: " . $page['title'];
*   echo "Order: " . $page['order'];
*  }
*/
function return_child_data($slug='') {
  if ($slug == '') {
    $slug = return_page_slug();
  }
  $path=GSDATAPAGESPATH;
  $data='';
  
  $count=0;
  $morderArray = array();
  if (is_dir($path)) {
      if ($dh = opendir($path)) {
         while (($file = readdir($dh)) !== false) {
             if($file!='.' AND $file!='..' AND $file!='.htaccess') {
                    $pathtofile=$path . $file;            
                    $da = @fopen($pathtofile,'r');
                    $data=getXML($pathtofile);  
                    if ($data->parent != '') {                              
                if ((strcasecmp($data->parent, $slug) == 0) && ($data->private !='Y')) {        
                $node=$data->children();
                $morderArray[$count]['slug'] = (string)$node->url;
                $morderArray[$count]['title'] = (string)$node->title;
                $morderArray[$count]['order'] = (string)$node->menuOrder;
                $count++;
                 }    
                        }
            @fclose($da);
                }
         }  
         closedir($dh);
      }
  }

  $morderArray = subval_sort($morderArray,'order');
  
  return($morderArray);
}
/** end of function return_child_data() ---------------------*/


/**
* custom function to return the slug of the next page in a group of child pages
* this will wrap around so the "next" page from the last page is the "first" page
* The order is based on the menuorder of the pages.
* ----
* example usage in a template:
* <a href="<?php get_parent(TRUE); echo '/'; return_next_slug(); ?>">Next Page</a>
*/
function return_next_slug() {
  $slug = return_page_slug();
  $peers = return_child_data(get_parent(FALSE));

  $size = count($peers);
    foreach($peers as $count => $pagedata) {
    if ($pagedata['slug'] == $slug) {
      return($peers[($count + 1) % $size]['slug']);
    }
  }
  return(FALSE);
}
/** end of function return_next_slug() ---------------------*/

/**
* custom function to return the slug of the previous page in a group of child pages
* this will wrap around so the "previous" page from the first page is the "last" page
* The order is based on the menuorder of the pages.
* ----
* example usage in a template:
* <a href="<?php get_parent(TRUE); echo '/'; return_prev_slug(); ?>">Previous Page</a>
*/
function return_prev_slug() {
  $slug = return_page_slug();
  $peers = return_child_data(get_parent(FALSE));
  
  $size = count($peers);
  foreach($peers as $count => $pagedata) {
    if ($pagedata['slug'] == $slug) {
      return($peers[($count + $size - 1) % $size]['slug']);
    }
  }
  return(FALSE);
}
/** end of function return_prev_slug() ---------------------*/

?>

Hopefully others might find this useful.

(I' really like a standard way of caching all of the menu data as an XML file to get into the core rather than various plugins all doing variations of the same things, such as the i18n, the multilevel menu plugin, the pagecache plugin, etc.)

-Rob A>
Reply
#2
Rob,

I just checked out the demo and it could really come in handy! (And your colour map of Ascadia rocks, too.) I like how the gallery updates after adding a page. That's an idea that could be useful for adding other content like blog entries as well.

I agree that putting caching right into the core and exposing this to plugin developers would be practical.
Reply
#3
The I18N (navigation) plugin also supports this functionality.
However, you need to know the level of the page.

If your current page is on the top level, you get the information with:
Code:
$childpages = return_18n_menu_data(return_page_slug(),1,1);
or - if the child pages do not show in the menu - with:
Code:
$childpages = return_18n_menu_data(return_page_slug(),1,1,I18N_SHOW_PAGES);
I18N, I18N Search, I18N Gallery, I18N Special Pages - essential plugins for multi-language sites.
Reply
#4
RobA Wrote:(I' really like a standard way of caching all of the menu data as an XML file to get into the core rather than various plugins all doing variations of the same things, such as the i18n, the multilevel menu plugin, the pagecache plugin, etc.)

In this case all meta data (including additional fields included by e.g. the Custom Field plugin) of the pages must be included in the cache, i.e. everything but the content.
if everything is accessible in an array indexed by slug, whose values are arrays with the meta data (values indexed by the names), this would be really useful.
I18N, I18N Search, I18N Gallery, I18N Special Pages - essential plugins for multi-language sites.
Reply
#5
mvlcek Wrote:
RobA Wrote:(I' really like a standard way of caching all of the menu data as an XML file to get into the core rather than various plugins all doing variations of the same things, such as the i18n, the multilevel menu plugin, the pagecache plugin, etc.)

In this case all meta data (including additional fields included by e.g. the Custom Field plugin) of the pages must be included in the cache, i.e. everything but the content.
if everything is accessible in an array indexed by slug, whose values are arrays with the meta data (values indexed by the names), this would be really useful.

Off the top of my head I'd prefer a simplexml file/variable rather than a flat array, set up something like this:
Code:
<pages>
  <page attributes (hidden, etc.)>
      <title>This is the Title</title>
.
.
.
      <customfield1>whatever</customfield1>
      <subpages>
        <page attributes (hidden, menu order, etc)>
...
        </page>
      </subpages>
  </page>
</pages>

So every page has a set of children that are the fields of the page, and a <subpage> child that can recursively hold more pages.

I'd also like to see the page nodes arranged as per the menu-order parameters. so it would be ewasy to get a next/previous page from the structure.

-Rob A>
Reply
#6
RobA Wrote:Off the top of my head I'd prefer a simplexml file/variable rather than a flat array, set up something like this:

...

So every page has a set of children that are the fields of the page, and a <subpage> child that can recursively hold more pages.

I'd also like to see the page nodes arranged as per the menu-order parameters. so it would be ewasy to get a next/previous page from the structure.

-Rob A>

From my experience the best approach is to have a flat XML file with each entry looking like a page file without content.

On the first request for cached data the core would read the file and build a structure like this:
Code:
$cached_data = array(
  'url1' => array( 'url' => 'url1', 'parent' => 'parenturl1', ...,
            'date' => <Unix timestamp, not string>,
            'children' => array('childurl1', 'childurl2', ...)
  'url2' => array(...),
  ...
  '' => array('children' => array('toplevelurl1', 'toplevelurl2', ...))
);

(slug = url)
The order of the children entries should represent the order as defined by priority.
Additionally there is an "empty" entry with the toplevel pages.

This way you can
  • easily access any page data by slug: $cached_data['slug']
  • easily sort the entries by any metadata like publication date or name
  • easily traverse from any page upwards to the toplevel page (bread crumbs):$url = 'url'; while ($url = $cached_data[$url]['parent']) do something;
  • easily create a full menu by starting with $cached_data['']['children']
  • easily create a child menu of any page by starting with $cached_data['pageurl']['children']
I18N, I18N Search, I18N Gallery, I18N Special Pages - essential plugins for multi-language sites.
Reply
#7
mvlcek Wrote:From my experience the best approach is to have a flat XML file with each entry looking like a page file without content.

On the first request for cached data the core would read the file and build a structure like this:
Code:
$cached_data = array(
  'url1' => array( 'url' => 'url1', 'parent' => 'parenturl1', ...,
            'date' => <Unix timestamp, not string>,
            'children' => array('childurl1', 'childurl2', ...)
  'url2' => array(...),
  ...
  '' => array('children' => array('toplevelurl1', 'toplevelurl2', ...))
);

(slug = url)
The order of the children entries should represent the order as defined by priority.
Additionally there is an "empty" entry with the toplevel pages.

This way you can
  • easily access any page data by slug: $cached_data['slug']
  • easily sort the entries by any metadata like publication date or name
  • easily traverse from any page upwards to the toplevel page (bread crumbs):$url = 'url'; while ($url = $cached_data[$url]['parent']) do something;
  • easily create a full menu by starting with $cached_data['']['children']
  • easily create a child menu of any page by starting with $cached_data['pageurl']['children']

That looks simpler to use than an XML structure... Now, how do we get it in the core Wink

Or a stand-alone plugin that does nothing else but generate the xml file?

-Rob A>
Reply
#8
Isn't this what my PageCache plugin does?

Creates a single xml file, without the content, and reads it into an array for use.

M
My Github Repos: Github
Website: DigiMute
Reply
#9
n00dles101 Wrote:Isn't this what my PageCache plugin does?

Creates a single xml file, without the content, and reads it into an array for use.

M

My Bad.

From the name of the plugin I assumed it was caching pages (front-end - the same as my cache plugin) not creating a single page index file. I took a read through the code to figure it out.


I noticed that you have added a "returnPageContent" function to supplement the built in get_page_content function.

Admins can close/merge this - please refer to http://get-simple.info/forum/post/12656/

-Rob A>
Reply




Users browsing this thread: 3 Guest(s)