Customizing Drupal Content Type Input Forms

23 July 2010
I've recently been struggling to alter a form in Drupal associated with the creation of a new node for a specific content type. I wanted something that wasn't as heavy as a module, and I couldn't seem to find a solution using views. So, some background - I'm developing a project management site in Drupal, and I want there to be tasks that you can associate with users. Instead of using comments for task updates I created a new content type 'tasklog' so that users could create new logs and do stuff like attach files. So when you view a Task I want there to be a custom button that says 'New task log' and a view that shows the logs already attached to the task. So I created two custom content types - task and takslog. Tasklog has a node reference field 'task' that pulls from a list of tasks. This allows each tasklog to be linked with a specific task. So the issue is that when you create a new task log there's a drop down of all the tasks. This could get quite long and I didn't want people to pick the wrong task by accident. So normally when you create a new tasklog you would use the url ?q=node/add/tasklog but I wanted to provide the option to use the url ?q=node/add/tasklog/12 where '12' would be the nid of the task for which the tasklog was associated and thus set the default task drop down to task #12. I tried all sorts of things, but eventually what I did was settle on altering the form using the template. I copied the garland template into my local templates/ folder and renamed it garland2. Then I added the following function:
function garland2_node_form($form) {
  if ($form['#token'] == 'tasklog_node_form') {
    if (isset($form['#action'])) {
      $action = $form['#action'];
      $action_id = intval(substr(strrchr($action, '/'),1)); 
      $form['field_task']['#default_value'] = array(array('nid'=>$action_id));	
      $form['field_task']['#value'] = array(array('nid'=>$action_id));
      $form['field_task']['nid']['#default_value'] = array(array('nid'=>$action_id));
      $form['field_task']['nid']['#value'] = array('nid'=>$action_id);	
      $form['field_task']['nid']['nid']['#default_value'] = $action_id;	
      $form['field_task']['nid']['nid']['#value'] = $action_id;	
  $output .= drupal_render($form);
  return $output;
This checks the URL, strips off the last integer, and uses it to set defaults on the form field. Notice how many times you have to reset it! This is cumbersome but it's much easier than doing a custom module. Anyways, just wanted to share in case someone else runs into this issue.