Posted by tecjam on February 8, 2012 at 9:41am
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_CALLBACKI 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.