Last updated May 13, 2014. Created on September 19, 2008.
Edited by LeeHunter, sepgil, Tauran. Log in to edit this page.

Custom Page Types For Pageroute

Please note that this API documentation is currently obsolete, since there were major changes in the the newest beta release of Pageroute.

Pageroute allows each module to provide own page types. This file shows you how to do this and where you can adapt pageroute's default behaviour.

You might also have a look at the existing implementations, which can be found in the pageroute.page_*.inc files. If you are creating page types, which should contain node forms consider reusing existing functions.

We will take the 'node add form' page type as example to explain the process of implementing your own page type.

1. Subclass pageroute_page

Let's look at the functions in pageroute.page.inc one has to implement.

<?php
abstract class pageroute_page {

 
/**
   * Returns the form to display the page type.
   * @param $args
   *    Can be used to customize the form.
   *  @return
   *    The form to display.
   */
 
abstract public function get_form(&$form_state, &$args);

 
/**
   *  Include stuff your page type needs.
   */
 
abstract protected function set_up();

 
/**
   *  Return the default action, if a cancel button is clicked.
   *  @return
   *    PAGEROUTE_CURRENT: stay on current page
   *    PAGEROUTE_FORWARD: go to next page
   *    PAGEROUTE_BACK: go to previous page
   */
 
public function get_cancel_target() { ... }
 
 
/**
   * These form fields are quite common for node forms, so page
   * types, which are also displaying node forms can use it.
   * @param $delete
   *    Wheter the "delete checkbox" should be added.
   */
 
public static function node_ui($page, &$form, $delete = TRUE) { ... }

 
/**
   * Handles all button clicks from your specific form.
   *  Set $args['default_target'] ( = $form_state['storage']['args']['default_target']) to specify what to do:
   *    PAGEROUTE_CURRENT: stay on current page
   *    PAGEROUTE_FORWARD: go to next page
   *    PAGEROUTE_BACK: go to previous page
   *  To customize get_form(...) set $args['todo'] ( = $form_state['storage']['args']['todo']).
   */
 
public static function form_submitted(&$form_state) { ... }

 
/**
   * Describes the page type.
   *  @return
   *    array('name' => t('Human readable page type name'));
   */
 
public abstract static function info();

 
/**
   * Provides a help text for the pageroute user interface.
   *  @return
   *    t('Help text.')
   */
 
public abstract static function help();
?>

2. Node Adding Form As An Example

<?php
// $Id$

/**
 * @file
 * Page add type
 */
?>

Include the base class.

<?php
include_once(drupal_get_path('module', 'pageroute') .'/pageroute.page.inc');

class
pageroute_page_add extends pageroute_page
 
/**
   * Returns the node adding form for the configured node type.
   */
 
function get_form(&$form_state, &$args) {
   
   
$form = array();

   
$args['hide_pageroute_buttons'] = FALSE;
   
$args['default_target'] = PAGEROUTE_FORWARD;
   
    return
pageroute_page_add::get_node_add_form(&$form_state, $this);
  }
?>

$args has the following elements:

$args['hide_pageroute_buttons']
TRUE to hide the pageroute buttons for the returned form.
$args['default_target']
Specify the default submit action.
$args['todo']
Optionally save information for the next form build.

You can add more variables if needed. They will be saved during the whole route.

<?php
 
// This function is static so it can be reused by other page types that want to display a node add form
 
public static function get_node_add_form(&$form_state, &$page) {
   
$type = $page->options['content-type'];

   
// If a node type has been specified, validate its existence.
   
if (node_access('create', $type)) {
     
$account = user_load(array('uid' => pageroute_page_get_uid($this, 'administer nodes')));

     
// Initialize settings:
     
$node = array('uid' => $account->uid, 'name' => $account->name, 'type' => $type);
     
      unset(
$form_state['node']);
     
// Set the form you want to display
     
$form = drupal_retrieve_form($type .'_node_form', $form_state, $node);
     
drupal_prepare_form($type .'_node_form', $form, $form_state);

     
// Call the pageroute configure function which applys standard options for all pagetypes
     
$page->configure_form(&$form);
     
      return
$form;
    }
    else {
     
drupal_access_denied();
     
pageroute_exit_now();
    }
  }

 
/**
   *  Show the content type option for the node add form.
   */
 
public static function ui($page, &$form) {
   
$form['options']['content-type'] = array(
     
'#type' => 'select',
     
'#title' => t('Content type'),
     
'#options' => node_get_types('names'),
     
'#required' => TRUE,
     
'#default_value' => $page->options['content-type'],
     
'#weight' => 2,
    );
    if (!isset(
$page->options['cancel'])) {
     
// we default to show the cancel button on add node forms
     
$form['options']['cancel']['#default_value'] = t('Cancel');
    }
   
pageroute_page::node_ui($page, $form, FALSE);
  }

  public static function
help() {
    return
t('A page of this type will present a common node adding form '.
            
'of a configurable content-type. The id of the new node will be '.
            
'added as new argument to the current path, so that other pages '.
            
'like a node view page can make use of it.');
  }
 
  public static function
info() {
    return array(
'name' => t('Node adding form'));
  }
 
  public function
get_cancel_target() {
    return
PAGEROUTE_FORWARD;
  }
 
?>

Handle button clicks from your form here. In this example the preview button changes the default behaviour to stay on the current page. It is remarkable that no $todo variable is set because the get_form function has no need to be customized.

<?php
 
public static function form_submitted(&$form_state) {
 
    switch (
$form_state['clicked_button']['#value']) {
      case
t('Preview'):
       
$form_state['storage']['args']['default_target'] = PAGEROUTE_CURRENT;
        break;
    }
  }
 
  protected function
set_up() {
    include_once(
drupal_get_path('module', 'node') .'/node.pages.inc');
  }
}
?>

3. Node Managment Page As An Example

We will only look at two important functions to clarify the use of the $args variable.

<?php
 
/**
   * Shows a node management page for the given content type
   * It determines from $args['todo'] what has to be displayed (overview, add/edit/delete form).
   */
 
public function get_form(&$form_state, &$args) {
   
$form = array();

    switch (
$args['todo']['action']) {
      case
t('Add'):
       
$args['hide_pageroute_buttons'] = TRUE;     
       
$args['default_target'] = PAGEROUTE_CURRENT;       
        return
pageroute_page_add::get_node_add_form(&$form_state, $this);

      case
t('Edit'):
       
$args['hide_pageroute_buttons'] = TRUE;     
       
$args['default_target'] = PAGEROUTE_CURRENT;       
       
$args['nid'] = $args['todo']['target'];
        return
pageroute_page_edit::get_node_edit_form(&$form_state, $this, $args);

      case
t('Delete'):
       
$args['hide_pageroute_buttons'] = TRUE;     
       
$args['default_target'] = PAGEROUTE_CURRENT;
        if (!
is_numeric($args['todo']['target']) || !($node = node_load($args['todo']['target']))) {
         
drupal_not_found();
         
pageroute_exit_now();
        }

        return
pageroute_node_delete_confirm($node, $form, $this, $args);

      default:
       
$args['default_target'] = PAGEROUTE_CURRENT;
       
$args['hide_pageroute_buttons'] = FALSE;
        return
pageroute_page_manage::pageroute_page_manage_overview($form_state, $this, $this->options['content-type']);
    }
  }
?>

Here $args['todo'] is set. $args['todo']['action'] specifys the form that will be showed and $args['todo']['target'] a node id if needed.

<?php
 
public static function form_submitted(&$form_state) {
 
    switch (
$form_state['clicked_button']['#value']) {
      case
t('Preview'):
       
$todo = $form_state['storage']['args']['todo'];
        break;
      case
t('Delete'):
        if (
is_numeric($form_state['clicked_button']['#name'])) {
         
$target = $form_state['clicked_button']['#name'];
        }
        else {
         
$target = $form_state['storage']['args']['todo']['target'];
        }
       
$todo = array('action' => $form_state['clicked_button']['#value'], 'target' => $target);
        break;
      case
t('Save'):
        unset(
$form_state['todo']);
       
$todo = NULL;
        break;
      default:
       
$todo = array('action' => $form_state['clicked_button']['#value'], 'target' => $form_state['clicked_button']['#name']);
    }

   
$form_state['todo'] = $todo;
  }
?>

4. Tell Pageroute Module about your Page Types

<?php
/**
 *  'your_module' hook of page types
 */
function {your_module}_pageroute_info() {
  return array(
   
'your_module' => array(
     
'page_type_1' => 'file_to_include'// multiple page types can be in the same include file
     
'page_type_2' => 'file_to_include',
      ...
    )
   );
}
?>

Note: page type classes have to be named {your_module}_page_{page_type_1} and be in file {your_module}.page_{page_type_1}.inc .

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.