6

I am using drupal 7 and am stuck at a very basic problem. I would like to simply show the edit page to a known node id. I know there are similar posts but they either didn't work or I didn't understand theme. My module looks like this:

<?php
/*
 * Show the edid page to a specific nid.
 */

function control_center_menu() {
  $items = array();
  module_load_include('inc', 'node', 'node.pages');
  $nid = '4';
  $node = node_load($nid);
  $items['test/test'] = array(
    'title' => 'Edit this node',
    'description' => 'Edit this node.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('page_node_form', $node),
    'access callback' => TRUE,
  );
  return $items;
}

However, at test/test I get a bunch of errors:

Warning: call_user_func_array() expects parameter 1 to be a valid callback, function 'node_form' not found or invalid function name in drupal_retrieve_form() (line 795 of /home/christian/workspace/gigs/includes/form.inc).
Notice: Undefined index: #node in menu_form_node_form_alter() (line 629 of /home/christian/workspace/gigs/modules/menu/menu.module).
Notice: Trying to get property of non-object in menu_form_node_form_alter() (line 629 of /home/christian/workspace/gigs/modules/menu/menu.module).
Notice: Undefined index: #node in menu_form_node_form_alter() (line 630 of /home/christian/workspace/gigs/modules/menu/menu.module).
Notice: Trying to get property of non-object in menu_form_node_form_alter() (line 630 of /home/christian/workspace/gigs/modules/menu/menu.module).

And instead of the hole form I only get the Menu setting check box and the URL path settings.

What am I doing wrong? I tried hard to find a noob friendly copy past example but didn't find any... Thanks a lot in advance!

3 Answers 3

7

hook_menu() is only evaluated when the caches are rebuilt, so the call to module_load_include() won't be called when the path is actually visited.

That hook is only meant for declaring menu items, if there's any logic that needs to be added for a path it should happen in the access callback/page callback like so:

function control_center_menu() {
  $items = array();

  $items['test/test'] = array(
    'title' => 'Edit this node',
    'description' => 'Edit this node.',
    'page callback' => 'control_center_test_callback',
    'page arguments' => array('page_node_form', $node),
    'access callback' => TRUE,
  );
  return $items;
}

function control_center_test_callback() {
  module_load_include('inc', 'node', 'node.pages');
  $nid = '4';
  $node = node_load($nid);

  return drupal_get_form('page_node_form', $node);
}

Since you're forwarding to a static node edit page though, it might be easier just to set the page callback to drupal_goto() and hardcode the URL:

function control_center_menu() {
  $items = array();

  $items['test/test'] = array(
    'title' => 'Edit this node',
    'description' => 'Edit this node.',
    'page callback' => 'drupal_goto',
    'page arguments' => array('node/4/edit'),
    'access callback' => TRUE,
  );
  return $items;
}
3
  • Thanks, now it seems so obvious! The node ID is not meant to be static in the end, that was just for testing purposes. The idea is to append the form to a view which has the nid as a field. So I suppose solution 2 is not the way to go since it redirects?
    – user8878
    Commented Jul 25, 2012 at 20:36
  • Yeah the redirect won't help if you're attaching the form to another page. You might also want to look at views_embed_view(), it might help if you're building up a page with a few different things in it
    – Clive
    Commented Jul 25, 2012 at 23:17
  • So what is the best practice to load the include files? your solution, kiamlaluno solution(at this question) , or this fragmentedthought.com/fragments/…? @Clive
    – Mouneer
    Commented Oct 5, 2015 at 12:09
3

You should define the menu callback as in the following code.

  $items['test/test'] = array(
    'title' => 'Edit this node',
    'description' => 'Edit this node.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('page_node_form', $node),
    'file path' => drupal_get_path('module', 'node'),
    'file' => 'node.pages.inc',
    'access callback' => TRUE,
  );

Remember that an implementation of hook_menu() is being invoked only when menus are rebuild, not each times a new page is requested to Drupal. As consequence of this, the form would get an updated node object only when your module is installed, or when the menus are being rebuilt; in other cases, the form will get a static copy of the node object, which doesn't reflect the actual node object.

It would be better to make test/test a path alias for node/4/edit. In that way, the form would get an updated node object every time.

1
  • Thanks as well for the prompt answer, you guys rock! As said above, I just set it to a static nid for testing purposes.
    – user8878
    Commented Jul 25, 2012 at 20:41
0

I've used code as follow:

function mymodule_menu() {

  $items = array();

  $items['user/%user/firm'] = array(
    'title' => 'Firm',
    'page callback' => 'firm_callback',
    'page arguments' => array(1),
    'access callback' => 'user_check',
    'access arguments'  => array(1),
    'type' => MENU_LOCAL_TASK,
  );

  return $items;
}

function firm_callback($userobj) {
    ....

    if ( isset($node) ) { // existed node

        $form_state['build_info']['args'] = array($node);
        form_load_include($form_state, 'inc', 'node', 'node.pages');
        $form = drupal_build_form('firm_node_form', $form_state);
        return $form;

    } else { // new node

        module_load_include('inc', 'node', 'node.pages');
        $form = node_add('firm');
        return drupal_render($form);

    }
}    

function mymodule_form_firm_node_form_alter(&$form, &$form_state, $form_id) {
  form_load_include($form_state, 'inc', 'node', 'node.pages');
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.