You are here

subform.module in Subform 5

Same filename and directory in other branches
  1. 7 subform.module

File

subform.module
View source
<?php

/**
 * @file
 */
function subform_field_info() {
  return array(
    'subform' => array(
      'label' => 'Subform',
    ),
  );
}
function subform_field_formatter_info() {
  return array(
    'default' => array(
      'label' => 'Default',
      'field types' => array(
        'subform',
      ),
    ),
  );
}
function subform_widget_info() {
  return array(
    'subform' => array(
      'label' => 'Subform',
      'field types' => array(
        'subform',
      ),
    ),
  );
}
function subform_widget($op, &$node, &$field, &$items) {
  switch ($op) {
    case 'form':
      $node_property = $field['field_name'] . '_parent_node';
      if (isset($node->nid)) {
        $parent_node = $node->nid;
      }
      else {
        if (isset($node->{$node_property})) {
          $parent_node = $node->{$node_property};
        }
        else {
          $parent_node = 0 - floor(rand());
        }
      }
      $form = array(
        $field['field_name'] => array(
          $field['field_name'] . '_parent_node' => array(
            '#type' => 'hidden',
            '#default_value' => $parent_node,
          ),
          'widget' => array(
            '#type' => 'subform',
            '#title' => $field['widget']['label'],
            '#mode' => $field['widget']['children_display_mode'],
            '#child_side' => $field['widget']['child_side'],
            '#relation_class' => $field['widget']['relation_class'],
            '#parent_node' => $parent_node,
            '#allow_selection' => $field['widget']['allow_selection'],
            '#allow_hoisting' => $field['widget']['allow_hoisting'],
            '#selection_query' => $field['widget']['selection_query'],
            '#type_name' => $node->type,
            '#field_name' => $field['field_name'],
          ),
        ),
      );
      return $form;
    case 'submit':
      $node_property = $field['field_name'] . '_parent_node';
      $node->subforms[$field['field_name']] = $node->{$node_property};
  }
}
function subform_form_alter($form_id, &$form) {
  if ($form_id == '_content_admin_field') {
    if ($form['field_type']['#value'] == 'subform') {
      unset($form['field']['required']);
      unset($form['field']['multiple']);
      $form['field']['required'] = array(
        '#type' => 'markup',
        '#value' => '<div class="form-item"><b>Required?:</b> Not applicable for subform.</div>',
      );
      $form['field']['multiple'] = array(
        '#type' => 'markup',
        '#value' => '<div class="form-item"><b>Multiple?:</b> Not applicable for subform.</div>',
      );
    }
  }
}
function subform_widget_settings($op, $widget) {
  switch ($op) {
    case 'callbacks':
      return array(
        'default value' => '_none_',
      );

    // settings form to be displayed during field creation.
    case 'form':
      $form = array(
        'relation_class' => array(
          '#type' => 'select',
          '#title' => t('Relation Class'),
          '#required' => TRUE,
          '#default_value' => isset($widget['relation_class']) ? $widget['relation_class'] : null,
          '#options' => relation_class_extended_list(),
          '#suffix' => l("Manage Relation Classes", "node/manage/relation_class"),
        ),
        'child_side' => array(
          '#type' => 'select',
          '#title' => t('Child Node Side'),
          '#required' => TRUE,
          '#default_value' => isset($widget['child_side']) ? $widget['child_side'] : null,
          '#suffix' => "Whatever relation class you have selected, determines what node types can be at the left and right ends of a relation instance based off of that relation class. Subform allows on-the-fly creation and referencing of child nodes, but it must know what *type* of child nodes to create.",
          '#options' => array(
            "left" => "Left",
            "right" => "Right",
          ),
        ),
        'children_display_mode' => array(
          '#type' => 'select',
          '#title' => t('Children Display Mode'),
          '#required' => TRUE,
          '#default_value' => isset($widget['children_display_mode']) ? $widget['children_display_mode'] : "edit",
          '#options' => array(
            "edit" => "Edit",
            "view" => "View",
            "hide" => "Hide",
          ),
        ),
        'allow_hoisting' => array(
          '#type' => 'select',
          '#title' => t('Allow Hoisting'),
          '#required' => TRUE,
          '#default_value' => isset($widget['allow_hoisting']) ? $widget['allow_hoisting'] : "no",
          '#options' => array(
            "yes" => "Yes",
            "no" => "No",
          ),
        ),
        'allow_selection' => array(
          '#type' => 'select',
          '#title' => t('Allow Selection of Existing Records'),
          '#required' => TRUE,
          '#default_value' => isset($widget['allow_selection']) ? $widget['allow_selection'] : "yes",
          '#options' => array(
            "yes" => "Yes",
            "no" => "No",
          ),
        ),
        'selection_query' => array(
          '#type' => 'textarea',
          '#title' => t('Selection Query'),
          '#required' => FALSE,
          '#default_value' => isset($widget['selection_query']) ? $widget['selection_query'] : "\n    SELECT\n      nid, title\n    FROM\n      {node}\n    WHERE\n      type = 'SOME CONTENT TYPE'\n    ",
          '#suffix' => "The results of this query will be displayed as a table except that previously-referenced entries will not be displayed. Be aware that an nid field is required.",
        ),
      );
      return $form;

    // form keys to save for settings form.
    case 'save':
      return array(
        'relation_class',
        'child_side',
        'children_display_mode',
        'allow_selection',
        'allow_hoisting',
        'selection_query',
      );
  }
}
function subform_field_settings($op, &$field) {
  switch ($op) {
    case 'callbacks':
      return array(
        'view' => CONTENT_CALLBACK_CUSTOM,
      );
    case 'database columns':
      return array(
        'subform' => array(
          'type' => 'int',
          'not null' => FALSE,
          'default' => 0,
        ),
      );
  }
}
function subform_field($op, &$node, $field, &$items, $teaser, $page) {
  switch ($op) {
    case 'view':
      $element = array(
        '#type' => 'subform',
        '#title' => $field['widget']['label'],
        '#mode' => 'view',
        '#child_side' => $field['widget']['child_side'],
        '#relation_class' => $field['widget']['relation_class'],
        '#parent_node' => $node->nid,
        '#allow_selection' => $field['widget']['allow_selection'],
        '#allow_hoisting' => $field['widget']['allow_hoisting'],
        '#selection_query' => $field['widget']['selection_query'],
        '#type_name' => $node->type,
        '#field_name' => $field['field_name'],
      );
      return theme_subform($element);
  }
}
function subform_menu($may_cache) {
  $items = array();
  content_clear_type_cache();
  $operations = array(
    "view" => true,
    "edit" => true,
    "delete" => true,
    "hoist" => true,
  );
  $node_access = array(
    "view" => 'view',
    "edit" => 'update',
    "delete" => 'delete',
  );
  if ($may_cache) {
    foreach (node_get_types() as $type => $name) {
      $items[] = array(
        'path' => 'subform/add/' . $type,
        'title' => t($name),
        'access' => node_access('create', $type),
        'callback' => '_subform_add',
        'callback arguments' => array(
          $type,
        ),
        'type' => MENU_CALLBACK,
      );
    }
  }
  else {
    if (arg(0) == 'subform' && is_numeric(arg(1)) && $operations[arg(2)] && arg(3) == null) {
      $node = node_load(arg(1));
      if ($node->nid) {
        $items[] = array(
          'path' => 'subform/' . arg(1) . '/' . arg(2),
          'title' => t(arg(2)),
          'callback' => '_subform_page',
          'access' => node_access($node_access[arg(2)], $node),
          'type' => MENU_CALLBACK,
        );
      }
    }
  }
  if (!$may_cache) {
    $directions = array(
      "left" => true,
      "right" => true,
    );
    if (arg(0) == 'subform_related' && is_numeric(arg(1)) && $directions[arg(2)]) {
      $child_side = arg(2);
      $child_node = $child_side . "_node";
      $child_node_type = $child_side . "_node_type";
      $parent_side = $child_side == "left" ? "right" : "left";
      $parent_node = $parent_side . "_node";
      $parent_node_type = $parent_side . "_node_type";

      // it looks like a request to create a new child of a certain node on a certain relation class
      if (is_numeric(arg(3)) && arg(4) == 'add' && arg(5) == null) {
        $relation_class_node = node_load(arg(1));
        $parent_node = arg(3) > 0 ? node_load(arg(3)) : arg(3);
        if ($relation_class_node->type == "relation_class" && (is_numeric($parent_node) && $parent_node < 0 || $parent_node->type == $relation_class_node->{$parent_node_type})) {
          $items[] = array(
            // subform_related / relation class id / side / parent node / add
            'path' => 'subform_related/' . arg(1) . '/' . arg(2) . '/' . arg(3) . '/add',
            'title' => t($name),
            'access' => node_access('create', $relation_class_node->{$child_node_type}),
            'callback' => '_subform_related_add',
            'callback arguments' => array(
              $relation_class_node,
              $parent_node,
              $child_side,
            ),
            'type' => MENU_CALLBACK,
          );
        }
      }
      else {
        if ($operations[arg(3)]) {
          $relation_instance_node = relation_instance_load(arg(1));
          if (isset($relation_instance_node->id)) {
            $node = node_load($relation_instance_node->{$child_node});
            if ($node) {
              $items[] = array(
                // subform_related / 1                    / right/ hoist
                // subform_related / relation instance id / side / operation
                'path' => 'subform_related/' . arg(1) . '/' . arg(2) . '/' . arg(3),
                'title' => t(arg(3)),
                'callback' => '_subform_related_page',
                'callback arguments' => array(
                  $relation_instance_node,
                  $node->nid,
                ),
                'access' => arg(3) == "hoist" ? true : node_access($node_access[arg(3)], $node),
                'type' => MENU_CALLBACK,
              );
            }
          }
        }
      }
    }
    if (arg(0) == 'subform_select' && is_string(arg(1)) && is_string(arg(2)) && is_numeric(arg(3)) && $directions[arg(4)]) {
      if ($result = db_fetch_object(db_query("SELECT * FROM {node_field_instance} WHERE type_name = '" . arg(1) . "' AND field_name = '" . arg(2) . "'"))) {
        $items[] = array(
          // type_name / field_name / relation class / direction
          'path' => 'subform_select/' . arg(1) . '/' . arg(2) . '/' . arg(3) . '/' . arg(4),
          'title' => t("Select"),
          'callback' => '_subform_select',
          'callback arguments' => array(
            $result,
            arg(3),
            arg(4),
          ),
          'access' => TRUE,
          'type' => MENU_CALLBACK,
        );
      }
    }
  }
  return $items;
}
function _subform($relation_class_id, $child_side, $parent_node_id, $selection_query = null, $allow_selection, $allow_hoisting, $mode = 'hide', $type_name, $field_name) {
  $subform_id = $parent_node_id;
  $relation_class = node_load($relation_class_id);
  $parent_side = $child_side == "left" ? "right" : "left";
  $child_side_cardinality = $child_side . "_node_cardinality";
  if (is_object($relation_class_id)) {
    $relation_class_node = $relation_class_id;
    $relation_class_id = $relation_class_node->nid;
  }
  else {
    $relation_class_node = node_load($relation_class_id);
  }
  drupal_add_css(drupal_get_path('module', 'subform') . '/subform.css');

  // drupal_add_js(drupal_get_path('module', 'subform') .'/subform.js');
  $relation_instance_results = db_query_range("SELECT id, " . $child_side . "_node as child_node FROM {relation_instance} WHERE relation_class = {$relation_class_node->nid} AND " . $parent_side . "_node = %d", $parent_node_id, 0, $relation_class->{$child_side_cardinality});
  $image_path = drupal_get_path('module', 'subform');
  $subform_name = "subform{$relation_class_id}";
  $subform_name = str_replace("-", "_", $subform_name);
  $table_name = "table{$subform_id}";
  $table_name = str_replace("-", "_", $table_name);
  $content = "\n<table id=\"{$tableName}\" class=\"table\" cellmargin=\"2\"></table>\n\n<script>\n  var {$subform_name} = new Subform( {$subform_id}, '" . substr(url("/", null, null, TRUE), 0, -1) . "', '{$child_side}', '{$mode}', {$relation_class_id}, {$parent_node_id}, " . ($allow_selection == "yes" ? "true" : "false") . ", " . $relation_class->{$child_side_cardinality} . ", '{$type_name}', '{$field_name}', '{$image_path}', " . ($allow_hoisting == 'yes' ? 'true' : 'false') . ");\n  {$subform_name}.renderLinks();\n  {$subform_name}.refresh();\n\n";
  while ($relation_instance_result = db_fetch_object($relation_instance_results)) {
    $content .= "  {$subform_name}.addChild( " . $relation_instance_result->id . " );\n";
  }
  $content .= "\n</script>";
  return $content;
}

/**
 * hook_nodeapi().
 */
function subform_nodeapi(&$node, $op, $a3 = null, $a4 = null) {

  // drupal_set_message( '<pre>' . print_r( $node, true ) . '</pre>' );
  if ($op == 'insert' && isset($node->subform_new)) {
    drupal_goto("subform/{$node->nid}/edit");
  }
  if ($op == 'insert' && isset($node->subform_related_new)) {

    // drupal_set_message( '<pre>' . print_r( $node, true ) . '</pre>' );
    $child_side = $node->child_side;
    $parent_side = $child_side == 'left' ? 'right' : 'left';
    $child_side_node = $child_side . '_node';
    $parent_side_node = $parent_side . '_node';
    $relation_instance = (object) array(
      'relation_class' => $node->relation_class,
      $parent_side_node => $node->parent_node,
      $child_side_node => $node->nid,
    );
    $relation_instance_id = relation_instance_insert($relation_instance);
    drupal_goto("subform_related/{$relation_instance_id}/{$child_side}/edit");
  }
  if ($op == 'insert' && isset($node->subforms)) {
    foreach ($node->subforms as $field => $parent_node) {
      if ($parent_node < 0) {
        relation_instance_update($parent_node, $node->nid);
      }
    }
  }
}

/**
 * Menu add callback
 */
function _subform_related_add($relation_class_node, $parent_node, $child_side) {
  global $user;
  $child_side = arg(2);
  $child_node_type = $child_side . "_node_type";
  $child_node_type = $relation_class_node->{$child_node_type};
  $child_node_cardinality = $child_side . "_node_cardinality";
  $child_node_cardinality = $relation_class_node->{$child_node_cardinality};
  $parent_side = $child_side == "left" ? "right" : "left";
  $parent_node_type = $parent_side . "_node_type";
  $parent_node_type = $relation_class_node->{$parent_node_type};
  $parent_node_cardinality = $parent_side . "_node_cardinality";
  $parent_node_cardinality = $relation_class_node->{$parent_node_cardinality};
  $content_type = $child_node_type;
  drupal_add_js('misc/autocomplete.js');
  drupal_add_js('misc/collapse.js');
  drupal_add_css(drupal_get_path('module', 'subform') . '/subform.css');
  drupal_add_css(drupal_get_path('module', 'content') . '/content.css');
  $node = (object) array(
    'uid' => $user->uid,
    'name' => $user->name,
    'type' => $content_type,
  );
  $form = node_form_array($node);
  $form['relation_class'] = array(
    '#type' => 'hidden',
    '#value' => $relation_class_node->nid,
  );
  $form['parent_node'] = array(
    '#type' => 'hidden',
    '#value' => isset($parent_node->nid) ? $parent_node->nid : $parent_node,
  );
  $form['child_side'] = array(
    '#type' => 'hidden',
    '#value' => $child_side,
  );
  $form['#submit']['_subform_related_redirect'] = array();
  $form['#submit']['node_form_submit'] = array();
  unset($form['preview']);

  // hook_form_alter triggers during drupal_get_form
  $content = drupal_get_form($node->type . '_node_form', $form, 'node_form');
  $messages = theme_status_messages();
  $content = str_replace('<input type="submit" name="op" value="Submit"  class="form-submit" />', '<input type="hidden" name="op" id="op" value="Submit">', $content);
  $head = drupal_get_html_head();
  $styles = theme_get_styles();
  include_once 'subform_related.tpl.php';
}

/**
 * Menu add callback
 */
function _subform_add($content_type) {
  global $user;
  drupal_add_js('misc/autocomplete.js');
  drupal_add_js('misc/collapse.js');
  drupal_add_css(drupal_get_path('module', 'content') . '/content.css');
  $node = (object) array(
    'uid' => $user->uid,
    'name' => $user->name,
    'type' => $content_type,
  );
  $form = node_form_array($node);
  $form['#submit']['_subform_redirect'] = array();
  $form['#submit']['node_form_submit'] = array();
  unset($form['preview']);

  // hook_form_alter triggers during drupal_get_form
  $messages = theme_status_messages();
  $content = drupal_get_form($node->type . '_node_form', $form, 'node_form');
  $head = drupal_get_html_head();
  $styles = theme_get_styles();
  include_once 'subform.tpl.php';
}

/**
 * Menu edit/view callback
 */
function _subform_page() {
  $node_id = arg(1);
  $operation = arg(2);

  // drupal_add_js('misc/autocomplete.js');
  drupal_add_js('misc/collapse.js');
  drupal_add_css(drupal_get_path('module', 'content') . '/content.css');
  $node = node_load($node_id);
  if ($operation == 'edit') {

    // since the result of ALL edit operations is redirection to edit, we need to check if the requested op was delete
    // this chunk of code ripped from node.module
    if ($_POST['op'] == 'Delete') {
      if ($_REQUEST['destination']) {
        $destination = drupal_get_destination();
        unset($_REQUEST['destination']);
      }
      drupal_goto('subform/' . arg(1) . '/delete', $destination);
      return;
    }
    $form = node_form_array($node);
    unset($form['preview']);
    $form['#redirect'] = "subform/{$node_id}/edit";
    $content = drupal_get_form($node->type . '_node_form', $form, 'node_form');
    $messages = theme_status_messages();
  }
  else {
    if ($operation == 'delete') {
      node_delete($node_id);
      $content = '';
    }
    else {
      $content = node_view($node);
    }
  }
  $head = drupal_get_html_head();
  $styles = theme_get_styles();
  include_once 'subform.tpl.php';
}
function subform_delete_relation_instance_submit($form_id, $form_values) {
  relation_instance_delete($form_values['relation_instance_id']);
  $output = "\n<html>\n<body>\n<script>\nparent.subform.removeChild( " . $form_values['relation_instance_id'] . " );\n</script>\n</body>\n</html>\n";
  print $output;
  die;
}
function _subform_select_submit($form_id, $form_values) {
  $child_side = $form_values['child_side'];
  $parent_side = $child_side == 'left' ? 'right' : 'left';
  $child_side_node = $child_side . '_node';
  $child_side_node_cardinality = $child_side . '_node_cardinality';
  $parent_side_node = $parent_side . '_node';
  $parent_node = $form_values['parent_node'];
  $relation_class = $form_values['relation_class'];
  $relation_class_node = node_load($relation_class);
  $allowed_slots = $relation_class_node->{$child_side_node_cardinality};
  $used_slots = relation_instance_used_slots($relation_class, $parent_side_node, $child_side_node, $parent_node);
  if ($form_values['select_list']['rows']) {
    foreach ($form_values['select_list']['rows'] as $row_key => $row_value) {
      foreach ($row_value as $cell_key => $cell_value) {
        if ($cell_value[0] == 1 && $used_slots < $allowed_slots) {
          $child_node = $cell_key;
          $relation_instance = (object) array(
            'relation_class' => $relation_class,
            $parent_side_node => $parent_node,
            $child_side_node => $child_node,
          );
          $relation_instance = relation_instance_insert($relation_instance);
          $used_slots++;
          $relation_instances[] = $relation_instance;
        }
      }
    }
  }
  $output = '';
  if (is_array($relation_instances)) {
    $output = implode(",", $relation_instances);
  }
  print $output;
  die;

  // print( "<pre>". print_r( $form_values, true ) ."</pre>" );
}
function _subform_select($result, $parent_node, $child_side) {

  // drupal_add_css(drupal_get_path('module', 'subform') .'/subform.css');
  // drupal_add_js(drupal_get_path('module', 'subform') .'/jquery.js');
  $result = unserialize($result->widget_settings);
  $relation_class = $result['relation_class'];
  $relation_class_node = node_load($relation_class);
  $limit_query = relation_instance_selectables_query($relation_class, $child_side, $parent_node);
  $selection_query = $result['selection_query'];
  $selectable_query = "SELECT * FROM ({$limit_query}) as limit_query INNER JOIN ({$selection_query}) AS selection_query ON limit_query.nid = selection_query.nid";

  // drupal_set_message( $selectable_query );
  $selectable_results = db_query($selectable_query);
  $form = array(
    'relation_class' => array(
      '#type' => 'hidden',
      '#value' => $relation_class,
    ),
    'child_side' => array(
      '#type' => 'hidden',
      '#value' => $child_side,
    ),
    'parent_node' => array(
      '#type' => 'hidden',
      '#value' => $parent_node,
    ),
    'select_list' => array(
      '#type' => 'fapi_table',
      '#tree' => true,
      '#width' => "100%",
      'rows' => array(),
      '#header' => true,
    ),
    'submit' => array(
      '#type' => 'submit',
    ),
    'javascript' => array(
      '#type' => 'markup',
      '#value' => "\n<script>\n\nfunction selectAll(form) {\n  for(var i = 0; i < form.elements.length; i++)\n  {\n    if( form.elements[i].type == 'checkbox' )\n    {\n      form.elements[i].checked = true;\n    }\n  }\n}\n\n</script>\n",
    ),
    'select_all' => array(
      '#type' => 'markup',
      '#value' => "<a href='#' onClick=\"selectAll(document.getElementById('_subform_select'));\" class='subform_button'><img src='/" . drupal_get_path('module', 'subform') . "/accept.png'>Select All</a>",
    ),
  );
  $result_found = 0;
  while ($selectable_result = db_fetch_array($selectable_results)) {
    if (!$form['select_list']['rows']) {
      $header_row["header_Select"] = array(
        array(
          '#type' => 'markup',
          '#value' => 'Select',
        ),
      );
      foreach ($selectable_result as $key => $value) {
        if ($key != 'nid' && $key != 'related_count') {
          $header_row["header_{$key}"] = array(
            array(
              '#type' => 'markup',
              '#value' => $key,
            ),
            '#table-sortable' => gettype($value),
            '#table-filterable' => true,
          );
        }
      }
      $form['select_list']['rows'][] = $header_row;
    }
    $new_record = array();
    $new_record[$selectable_result['nid']] = array(
      array(
        '#type' => 'checkbox',
        '#default_value' => false,
      ),
    );
    foreach ($selectable_result as $key => $value) {
      if ($key != 'nid' && $key != 'related_count') {
        $new_record[] = array(
          array(
            '#type' => 'markup',
            '#value' => $value,
          ),
        );
      }
    }
    $form['select_list']['rows'][] = $new_record;
    $result_found++;
  }
  if ($result_found == 0) {
    $new_record[] = array(
      array(
        '#type' => 'markup',
        '#value' => 'No results were found',
      ),
    );
    $form['select_list']['rows'][] = $new_record;
    unset($form['submit']);
  }
  drupal_add_css(drupal_get_path('module', 'subform') . '/subform_select.css');
  $content = drupal_get_form("_subform_select", $form);
  $content = str_replace("<input type=\"submit\" name=\"op\" value=\"\"  class=\"form-submit\" />", "<input type='hidden' name='op' id='op' value='Submit'>", $content);

  // its important that these occur after form generation, to allow fapi widgets to add js and css files
  $head = drupal_get_html_head();
  $styles = theme_get_styles();
  include_once 'subform_related.tpl.php';
  die;
}
function _subform_related_page($relation_instance_node, $node_id) {
  $relation_instance_id = arg(1);
  $operation = arg(3);
  $relation_class_node = node_load($relation_instance_node->relation_class);
  $child_side = arg(2);
  $child_node = $child_side . '_node';
  $child_node = $relation_instance_node->{$child_node};
  $parent_side = $child_side == 'left' ? 'right' : 'left';
  $parent_node = $parent_side . '_node';
  $parent_node = $relation_instance_node->{$parent_node};
  $form_delete_relation_instance = array(
    'relation_instance_id' => array(
      '#type' => 'hidden',
      '#value' => $relation_instance_id,
    ),
    'submit' => array(
      '#type' => 'submit',
    ),
  );
  $form_delete_relation_instance = str_replace("<input type=\"submit\" name=\"op\" value=\"\"  class=\"form-submit\" />", "<input type='hidden' name='op' id='op' value='Submit'>", drupal_get_form('subform_delete_relation_instance', $form_delete_relation_instance));
  $node = node_load($node_id);
  if ($operation == 'hoist') {
    drupal_goto("node/{$node_id}/edit");
  }
  else {
    if ($operation == 'edit') {

      // since the result of ALL edit operations is redirection to edit, we need to check if the requested op was delete
      // this chunk of code ripped from node.module
      if ($_POST['op'] == 'Delete') {
        if ($_REQUEST['destination']) {
          $destination = drupal_get_destination();
          unset($_REQUEST['destination']);
        }

        // 'subform_related/'. arg(1) .'/'. arg(2) .'/'. arg(3)
        drupal_goto("subform_related/{$relation_instance_id}/{$child_side}/delete", $destination);
        return;
      }
      $form = node_form_array($node);
      unset($form['preview']);
      unset($form['delete']);
      $form['#redirect'] = "subform_related/{$relation_instance_id}/{$child_side}/edit";
      $content = $form_delete_relation_instance . drupal_get_form($node->type . '_node_form', $form, 'node_form');
      $content = str_replace('<input type="submit" name="op" value="Submit"  class="form-submit" />', '<input type="hidden" name="op" id="op" value="Submit">', $content);
      $messages = theme_status_messages();
    }
    else {
      if ($operation == 'delete') {
        node_delete($node_id);
        $content = '';
      }
      else {
        $content = node_view($node);
      }
    }
  }
  $head = drupal_get_html_head();
  $styles = theme_get_styles();
  print $messages . $content;

  // include_once('subform.tpl.php');
}
function _subform_redirect($op, &$node) {
  drupal_set_message(t('Your %post was created.', array(
    '%post' => node_get_types('name', $node),
  )));
  $node['subform_new'] = TRUE;
}
function _subform_related_redirect($op, &$node) {
  drupal_set_message(t('Your %post was created.', array(
    '%post' => node_get_types('name', $node),
  )));
  $node['subform_related_new'] = TRUE;
}
function subform_elements() {
  $type['subform'] = array(
    '#child_side' => null,
    '#relation_class' => null,
    '#parent_node' => null,
    '#allow_selection' => null,
    '#allow_hoisting' => null,
    '#selection_query' => null,
  );
  return $type;
}
function theme_subform($subform_element) {

  // don't draw nested subforms
  if (arg(0) == 'subform_related' || arg(0) == 'subform_related') {
    return '';
  }
  if (isset($subform_element['#relation_class']) && isset($subform_element['#child_side']) && isset($subform_element['#parent_node'])) {
    drupal_set_html_head(theme('stylesheet_import', base_path() . drupal_get_path('module', 'subform') . '/subform.css'), "module");
    drupal_add_js(drupal_get_path('module', 'subform') . '/jquery.js');
    drupal_add_js(drupal_get_path('module', 'subform') . '/jquery.form.js');
    drupal_add_js(drupal_get_path('module', 'subform') . '/drupal_jquery_liaison.js');
    drupal_add_js(drupal_get_path('module', 'subform') . '/subform.js');
    drupal_add_js(drupal_get_path('module', 'subform') . '/table.js');
    $attributes = drupal_attributes($subform_element['#attributes']);
    $title = isset($subform_element['#title']) ? "<label for=\"edit-title\" class=\"subform_label\">" . $subform_element['#title'] . ':</label>' : '';
    $subform = _subform($subform_element['#relation_class'], $subform_element['#child_side'], $subform_element['#parent_node'], $subform_element['#selection_query'], $subform_element['#allow_selection'], $subform_element['#allow_hoisting'], $subform_element['#mode'], $subform_element['#type_name'], $subform_element['#field_name']);
    $subform = "<div class=\"form-item\">{$title}<div class=\"subform\">{$subform}</div></div>";
    return $subform . "\n";
  }
}