views:

321

answers:

2

I have a situation where I want a set of users (employees) to be able to create a node, but to replace the uid (user ID) with that of the users profile currently displayed.

In other words, I have a block that that calls a form for a content type. If an employee (uid = 20) goes to a clients page (uid =105), and fills out the form, I want the uid associated with the form to be the client's(105), not the employee's.

I'm using arg(1) to grab the Client's uid - here is what I have..

 <?php
function addSR_form_service_request_node_form_alter(&$form, $form_state) {
       if (arg(0) == 'user' && is_numeric(arg(1))) {
        $form['#submit'][] = 'addSR_submit_function';
    }
}

function addSR_submit_function($form, $form_state) {
    $account = user_load(arg(1));
    $form_state['values']['uid'] = $account->uid;
    $form_state['values']['name'] = $account->name;
}

?>

The form is loading in the block, but when submitted, is still showing the employee uid. I don't want to use hook_form_alter because I don't want to modify the actual form, because clients can fill out the form directly, in this case, I don't want to modify the form at all.

I'm also ashamed that I'm putting this in a block, but I couldn't think of a way to put this in a module, so any suggestions on that would also be appreciated...

+1  A: 

PHP blocks are bad. You can put them in a module.

function hook_block($op, $delta = 0) {
  // Fill in $op = 'list';
  if ($op == 'view' && $delta = 'whatever') {
    $account = user_load(arg(1));
    $node = array('uid' => $account->uid, 'name' => $account->name, 'type' => 'service_request', 'language' => '', '_service_request_client' => $account->uid);
    $output = drupal_get_form('service_request_node_form', $node);
    // Return properly formatted array.
  }
}

Additionally, you want a form_alter just to enforce the values. It's ugly but it works.

function hook_form_service_request_node_form_alter(&$form, $form_state) {
  if (isset($form_state['node']['_service_request_client'])) {
    $form['buttons']['submit']['#submit'] = array('yourmodule_node_form_submit', 'node_form_submit');
  }
}

function yourmodule_node_form_submit($form, &$form_state) {
  $account = user_load($form_state['node']['_service_request_cilent'])l
  $form_state['values']['uid'] = $account->uid;
  $form_state['values']['name'] = $account->name;
}
dmitrig01
I understand the bottom portion, I've added that to a module. However, I've never used the "hook_block" function. I thought it was supposed to go in the module, but I don't see where it is called. Also, do I still need to call drupal_get_form from the block?
cinqoTimo
Yes you do. Hook_block defines blocks from code. It goes in a module. See node_block, user_block, system_block.http://api.drupal.org/api/function/hook_block/6
dmitrig01
+1  A: 

To create your form in a block, you could use the formblock module. Especially if you are not used to use the Drupal API. Then all that's left if to add your own submit handler to the form. This is a piece of code that is run, when the form is submitted. You only want to do this on clients pages so you would do that using the hook_form_alter function.

/**
 * Hooks are placed in your module and are named modulename_hookname().
 * So if a made a module that I called pony (the folder would then be called
 * pony and it would need a pony.info and pony.module file I would create this function
 */
function pony_form_service_request_node_form_alter(&$form, $form_state) {
    // Only affect the form, if it is submitted on the client/id url
    if (arg(0) == 'client' && is_numeric(arg(1))) {
        $form['#submit'][] = 'pony_my_own_submit_function';
    }
}

function pony_my_own_submit_function($form, &$form_state) {
    $account = user_load(arg(1));
    $form_state['values']['uid'] = $account->uid;
    $form_state['values']['name'] = $account->name;
}

The idea behind this code, is to only alter the form when the condition is met - that it is submitted on a client page. I guessed that the arg(0) would be client so if it's something else you would need to change that of cause. We only need to add a submit function, since what we want is to change the values if the form has passed validation.

Then if that is the case our 2nd function is run, which does that actual alteration of the values.

googletorp
Thanks Googletorp, that was a very concise answer. I installed form block, and created a module named addSR (replaced pony). The formblock module displays the form, but it's still passing the original uid. Is there a way to test if the handler is even being called? ---I posted the updated snippet...
cinqoTimo
The quickest way is to call drupal_set_message('some text'); somewhere. if called it will print the text in the message area where validation erros etc are displayed. If you want to do some serious debugging, you should take a look at the devel module or take a look at drupal for Firebug. A firebug addon/drupal module combo which also has some nice debugging tools.
googletorp
cinqoTimo
The key points happen in `node_form_submit_build_node` and `node_submit`
googletorp
node_submit requires a node to be passed to it as a parameter, which won't work because the node hasn't been created yet. node_form_submit_build_node sounds like it will work, but I added it to the submit button handler after setting the the UID, and it still had no effect. I can't be the only one trying to do this!! I'm dying here :\
cinqoTimo
googletorp
It works! :) ...So wait, it seems like passing it by reference would make it not work? What was going on under the hood here?
cinqoTimo
When you pass by reference, whatever alterations you make on the reference is also effected on the original. So the function we make alters the value of $form_state that the function that saves the form uses. This is normal PHP stuff.
googletorp