Hi,

I'm trying to write a module that will allow me to display the node content across 2 pages.

I have set up a custom content type 'stadt' with defined pathauto path '/country/city' for which I wish to register a sub-page to be available under /country/city/info.

On this sub-page I wish to display the body and other cck fields for that content type and hide them on the regular path.

Here is the code for my custom module:

<?php
/**
* Implements hook_permission().
*
* Since the access to our new custom pages will be granted based on
* special permissions, we need to define what those permissions are here.
* This ensures that they are available to enable on the user role
* administration pages.
*/
function stadtinfo_page_permission() {
  return array(
    'access stadtinfo page' => array(
      'title' => t('Access Stadtinfo Page'),
      'description' => t('Allow users to access Stadtinfo page - a subpage for stadt content types'),
    )
  );
}

/**
*  Implements hook_menu().
*
*  @see: http://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_menu/7
*
*  'title':              the title of the page being created
*  'page callback':      function to be called when the link is clicked
*  'page arguments':     the arguments for the callback function 'page callback'
*                        in this case the node id from the url using the $args eg: domain.com/[1]/[2]/[3] ...
*                        which equals /node/$node_id/stadtinfo
*  'access callback':    permission to view page
*  'access arguments':   same as 'page arguments' send the arg value to the function defined in 'access callback'
*                     
*/
function stadtinfo_page_menu() {

  $items['node/%stadt_node/info'] = array(
    'title' => 'Info',
    'page callback' => 'stadt_node_load',
    'page arguments' => array(1),
    'access callback' => 'stadtinfo_page_access',
    'access arguments' => array(1),
    'type' => MENU_CALLBACK,
  );
 
  // don't forget this
  return $items;
 
} // end function

/**
*  access function
*/
function stadtinfo_page_access($node) {
  if($node->type == 'stadt'){
    return user_access('access stadtinfo page');
  } // end if
  else {
    return FALSE;
  }
}

/**
*  Function to load the node from the nid
*/
function stadt_node_load($nid) {
  if (is_numeric($nid)) {
$node = node_load($nid);
    if ($node->type == ‘stadt’) {
        return $node;
    }
  }
return FALSE;
}

Can anyone tell me why I can not get this to work?

Comments

Right, I back-tracked a bit

Right, I back-tracked a bit to try and start back at the basics.
I used a fresh d7 install and used the predefined content type - 'article' - to try and add an info page to it that simply displays the exact same info as the article page itself.

I also tried to add a 'tab' using
'type' => MENU_LOCAL_TASK,

rather than just registering it using (i was going to add a custom link in the template for that content type)
'type' => MENU_CALLBACK

I called the module article_page with a simple .info file just so I can test it.
So, now I have a tab that is called 'info' and is shown only for content types 'article' - which when clicked displays the same content as the node page.

And here is the code:

<?php
/**
* Implements hook_menu().
*/
function article_page_menu() {

  $items['node/%/info'] = array(
    'title' => 'Info',
    'page callback' => 'article_page_load',
    'page arguments' => array(1),
    'access callback' => 'article_page_access',
    'access arguments' => array(1),
    'type' => MENU_LOCAL_TASK, // tab instead of MENU_CALLBACK
    'weight' => '1000', // last tab item
  );
 
  return $items;
}

/**
* Constructs a descriptive page.
*/
function article_page_load($nid) {
  if (is_numeric($nid)) {
$node = node_load($nid);

    if($node->type == 'article') {
      // convert object to array
      // else we get an error
      $node = node_view($node);
      // render array
      return drupal_render($node);
    }
    drupal_not_found();
    return;
  }
return FALSE;
}


/**
*  Create the access callback
*/
function article_page_access($nid) {
  if (is_numeric($nid)) {
$node = node_load($nid);
    // only show for article types
    if($node->type != 'article'){
      return FALSE;
    } else {
      return TRUE;
    }
  }
  return FALSE;
}

Now I need to try and get pathauto to work for this module ... so i'll post back with the results when done. I am going to work through this example: http://envisioninteractive.com/drupal/using-the-pathauto-api-drupal-modu...

Ok, so here is another update

Ok, so here is another update for this module.

First off, in the 'hook_menu()' function it is better to use %node in the path as this will automatically expose the $node object to us, which means we do not need to call node_load($nid); on all our callbacks.

I also got the template file to work, however, I couldn't get node.tpl.php constants to work, such as $content or $teaser or $page. But since these are pretty mcuh all available in the $node object anyway, it just needed some rewriting.

I implemented pathauto into it, so it creates the url aliases for the tab link, however I don't know how to make the tab actually link there.

Here is the code so far. It is applied to 'article' type so it should work fine on a fresh d7 install.

<?php
/**
* Implements hook_menu().
*/
function node_subpage_menu() {

  // use %node so we have the full $node for use
  // without having to use load_node($nid) on callbacks
  $items["node/%node/info"] = array(
    'title' => 'Information',
    'page callback' => 'node_subpage_page_callback',
    'page arguments'   => array(1),
    'access callback' => 'node_subpage_access_callback',
    'access arguments' => array(1, 'access content'),
    'type' => MENU_LOCAL_TASK, // creates a tab
    'weight' => '1000', // last tab item
  );
 
  return $items;
}

/**
*  Page Callback
*/
function node_subpage_page_callback($node) {

    if($node->type == 'article') {
      drupal_set_title('Nodeinfo: ' . $node->title);
      return theme('node_subpage_template', array('node' => $node));
    }

    drupal_not_found();
    return;
}

/**
*  Create the access callback
*/
function node_subpage_access_callback($node) {

  if($node->type != 'article' || arg(2) == 'edit'){
    return FALSE;
  } else {
    return TRUE;
  }

}

/**
* Implements hook_theme().
*/
function node_subpage_theme($existing, $type, $theme, $path) {
  return array(
    'node_subpage_template'  => array(
      'template' => 'node_subpage_template',
      'variables' =>  array('node' => NULL),
    ),
  );
}

function theme_node_subpage_template($variables) {
  $node = $variables['node'];
  $build = node_view($node);
  $output = drupal_render($build);
  return $output;
}



/**
* Implements hook_pathauto.
*/
function node_subpage_pathauto($op) {
  $settings = new stdClass();
  $settings->module = 'node_subpage';
  $settings->groupheader = t('Article Subpage Paths');
  $settings->patterndescr = t('Default path pattern');
  $settings->patterndefault = 'article/[node:nid]/info';
  $settings->token_type = 'node';
  $settings->patternitems = array('infos' => 'Article Subpage pattern');
  $settings->batch_update_callback = 'node_subpage_pathauto_bulkupdate';
  return $settings;
}

/**
* helper function to create the alias
*/
function node_subpage_create_alias($node, $op) {
  module_load_include('inc', 'pathauto');
  pathauto_create_alias('node_subpage', $op, 'node/' . $node->nid . '/info', array('node' => $node), 'infos');
}

/**
* Implements hook_node_insert.
*/
function node_subpage_node_insert($node) {
  if($node->type == 'article') {
    node_subpage_create_alias($node, 'insert');
  }
}

/**
* Implements hook_node_update.
*/
function node_subpage_node_update($node) {
  if($node->type == 'article') {
    node_subpage_create_alias($node, 'update');
  }
}

/**
* Implements hook_pathauto_bulkupdate.
*/
function node_subpage_pathauto_bulkupdate() {
  // find all node ids for the store content type
  $query = db_select('node', 'n');
  $query
    ->condition('n.type', 'article')
    ->fields('n', array('nid'));
  $results = $query->execute()->fetchCol();
  $count = 0;
  foreach($results as $nid) {
    $node = node_load($nid);
    node_subpage_create_alias($node, 'bulkupdate');
    $count++;
  }
  drupal_set_message($count . ' article subpages were updated.');
}

This is Drupal 7 code,

This is Drupal 7 code, correct?

IT Sherpa, Drupal Mason

You don't really need to

You don't really need to write custom codes to handle this. You can easily get this running using Display Suite http://drupal.org/project/ds. Any reason you're custom coding this?

Arshad Chummun
blog | twitter | app.net

Hi, I didn't know about

Hi, I didn't know about Display Suite, so I thought that simply coding it would be easier and faster than searching for a module that may or may not do it. Plus I have learned a bit more about drupal modules.