Index: relativity.module
===================================================================
--- relativity.module	(revision 373)
+++ relativity.module	(working copy)
@@ -7,6 +7,7 @@
  * To store this extra information, we need an auxiliary database table.
  */
 
+
  /**
  * Implementation of hook_perm().
  */
@@ -48,81 +49,103 @@
  *   with various filters for restricting what is seen.  Someday, maybe :)
  *   javanaut
  */
-function relativity_list_possible_children($type, $parent) {
-  $links = array();
-  $relativity_query = variable_get('relativity_child_query_'. $parent->type .'_'. $type, NULL);
-  $common_children_reqd = variable_get('relativity_common_child_'. $parent->type .'_'. $type, array());
-  if ($relativity_query && $query = node_load($relativity_query)) {
-    //drupal_set_message("executing query ". print_r($query, 1));
-    foreach (relativity_execute_query($query, NULL, $parent->nid) as $chnid => $child) {
-      if ($child->type == $type) {
-        $links[] = theme('relativity_link', check_plain($child->title), "addparent/$child->nid/parent/$parent->nid", $parent->nid, ' '. theme_relativity_trace($child->relativity_trace));
+function relativity_list_possible_attachments($type='', $attach_type='parent', $attach_node) {
+  global $user;
+  //check url for correct form
+  if ((($attach_type == 'parent') || ($attach_type == 'child')) && (is_numeric($attach_node->nid)) && (!($type == ''))) {
+    $links = array();
+    $attachee = $attach_node;
+    $relativity_query = variable_get('relativity_child_query_'. $attachee->type .'_'. $type, NULL);
+    $common_children_reqd = variable_get('relativity_common_child_'. $attachee->type .'_'. $type, array());
+    if ($relativity_query && $query = node_load($relativity_query)) {
+      //drupal_set_message("executing query ". print_r($query, 1));
+      foreach (relativity_execute_query($query, NULL, $attach_nid) as $chnid => $child) {
+        if ($child->type == $type) {
+          $links[] = theme('relativity_link', $child->title, "addparent/$child->nid/parent/$attach_nid", $attach_nid, ' '. theme_relativity_trace($child->relativity_trace));
+        }
       }
     }
-  }
-  elseif (count($common_children_reqd)) {
-    $otherparents = relativity_list_grand_relatives($parent, 'child', 'parent', $common_children_reqd, array($type));
-
-    foreach ($otherparents as $childparent) {
-      $links[] = theme('relativity_link', check_plain($childparent->title), "addparent/$childparent->nid/parent/$parent->nid", $parent->nid, 'common child required');
+    elseif (count($common_children_reqd)) {
+      $otherparents = relativity_list_grand_relatives($attachee, 'child', 'parent', $common_children_reqd, array($type));
+  
+      foreach ($otherparents as $childparent) {
+        if (node_access("view", $childparent)) {
+          $links[] = theme('relativity_link', $childparent->title, "addparent/$childparent->nid/parent/$attach_nid", $attach_nid, 'common child required');
+        }
+      }
     }
-  }
-  else {
-    // So, look up all valid nids attached to this parent_node already..
-    $result = db_query(db_rewrite_sql('SELECT n.nid FROM {node} n LEFT OUTER JOIN {relativity} r ON n.nid=r.nid WHERE n.type = \'%s\' AND r.parent_nid=%d'), array($type, $parent->nid));
-    $excluded_nids = array($parent->nid);
-    // The number of nids returned by this array should be reasonably small.
-    // It's the number of nodes attached to a given node already.
-    while ($existing_nid = db_fetch_object($result)) {
-      $excluded_nids[] = $existing_nid->nid;
-    }
-
-    $use_taxonomy = variable_get('relativity_use_taxonomy', 0);
-    if ($use_taxonomy) {
-      $result = db_query(db_rewrite_sql('SELECT DISTINCT n.nid, t.tid, v.vid FROM {node} n INNER JOIN {term_node} t ON n.nid = t.nid INNER JOIN {term_data} v ON t.tid = v.tid WHERE n.type = \'%s\' AND n.status = 1 ORDER BY v.vid, t.tid'), $type);
-    }
     else {
-      $result = db_query(db_rewrite_sql('SELECT n.nid FROM {node} n WHERE n.type = \'%s\' AND n.status = 1 ORDER BY n.title'), $type);
+      // So, look up all valid nids attached to this parent_node already..
+      $excluded_nids[] = $attachee->nid; 
+      if ($attach_type == 'parent') {
+        $result = db_query(db_rewrite_sql('SELECT n.nid FROM {node} n LEFT OUTER JOIN {relativity} r ON n.nid=r.nid WHERE n.type = \'%s\' AND r.parent_nid=%d'), array($type, $attachee->nid));
+      }
+      else { //attaching a parent
+        $result = db_query(db_rewrite_sql('SELECT n.nid FROM {node} n LEFT OUTER JOIN {relativity} r ON n.nid=r.parent_nid WHERE n.type = \'%s\' AND r.nid=%d'), array($type, $attachee->nid));
+      }
+      // The number of nids returned by this array should be reasonably small.
+      // It's the number of nodes attached to a given node already.
+      while ($existing_nid = db_fetch_object($result)) {
+        $excluded_nids[] = $existing_nid->nid;
+      }      
+      // The number of nids returned by this array should be reasonably small.
+      // It's the number of nodes directly attached to a given node already.
+      while ($existing_nid = db_result($result)) {
+        $excluded_nids[] = $existing_nid;
+      }
+      $use_taxonomy = variable_get('relativity_use_taxonomy', 0);
+      if ($use_taxonomy) {
+        $result = db_query(db_rewrite_sql('SELECT DISTINCT n.nid, t.tid, v.vid FROM {node} n INNER JOIN {term_node} t ON n.nid = t.nid INNER JOIN {term_data} v ON t.tid = v.tid WHERE n.type = \'%s\' AND n.status = 1 ORDER BY v.vid, t.tid'), $type);
+      }
+      else {
+        $result = db_query(db_rewrite_sql('SELECT n.nid FROM {node} n WHERE n.type = \'%s\' AND n.status = 1 ORDER BY n.title'), $type);
+      }
     }
-  }
-
-  while ($child = db_fetch_object($result)) {
-    if (in_array($child->nid, $excluded_nids)) {
-      continue;
+  
+    while ($attachment = db_fetch_object($result)) {
+      if (in_array($attachment->nid, $excluded_nids)) {
+        
+        continue;
+      }
+      $attachment_node = node_load($attachment->nid);
+        if (node_access('view', $attachment_node, $user)) {
+          if ($use_taxonomy) {
+            $parent_tree = array_reverse(taxonomy_get_parents_all($attachment->tid));
+            // Building the array key
+            for ($i=0; $i<count($parent_tree); $i++) {
+              if ($i==0) {
+                $key = $parent_tree[$i]->vid .';'. $parent_tree[$i]->tid .';';
+              }
+              else {
+                $term = taxonomy_get_term($parent_tree[$i]->tid);
+                $key .= $parent_tree[$i]->tid .';';
+              }
+            }
+            $key = rtrim($key, ';');
+            $links[$key][] = ($attach_type == 'parent') ? array('title' => $attachment_node->title, 'child_node' => $attachment_node->nid, 'parent_node' => $attach_nid) : array('title' => $attachment_node->title, 'child_node' => $attach_nid, 'parent_node' => $attachment_node->nid);
+          }
+          else {
+            $links[] = ($attach_type == 'parent') ? theme('relativity_link', $attachment_node->title, "addparent/$attachment_node->nid/parent/$attachee->nid", $attachee->nid) : theme('relativity_link', $attachment_node->title, "addparent/$attachee->nid/child/$attachment_node->nid", $attachee->nid);
+          }
+        }
     }
-    $child_node = node_load($child->nid);
-    if ($use_taxonomy) {
-      $parent_tree = array_reverse(taxonomy_get_parents_all($child->tid));
-      // Building the array key
-      for ($i=0; $i<count($parent_tree); $i++) {
-        if ($i==0) {
-          $key = $parent_tree[$i]->vid .';'. $parent_tree[$i]->tid .';';
-        }
-        else {
-          $term = taxonomy_get_term($parent_tree[$i]->tid);
-          $key .= $parent_tree[$i]->tid .';';
-        }
+    if (count($links)) {
+      if ($use_taxonomy) {
+        print(theme('page', drupal_get_form('relativity_taxonomy_form', $links, $attach_type) ));
       }
-      $key = rtrim($key, ';');
-      $links[$key][] = array('title' => check_plain($child_node->title), 'child_node' => $child_node->nid, 'parent_node' => $parent->nid);
+      else {
+        print(theme('page', theme('relativity_bullets', $links)));
+      }
     }
     else {
-        $links[] = theme('relativity_link', check_plain($child_node->title), "addparent/$child_node->nid/parent/$parent->nid", $parent->nid);
+      drupal_set_message(t('There are no available !s items to attach', array('!s' => node_get_types('name', $type))));
+      drupal_goto("node/$attachee->nid");
     }
   }
-
-  if (count($links)) {
-    if ($use_taxonomy) {
-      print(theme('page', drupal_get_form('relativity_taxonomy_form', $links)));
-    }
-    else {
-      print(theme('page', theme('relativity_bullets', $links)));
-    }
-  }
   else {
-    drupal_set_message(t('There are no available !s items to attach', array('!s' => node_get_types('name', $type))));
-    drupal_goto("node/$parent->nid");
-  }
+      drupal_set_message(t('Illegal url to make attachements'));
+      drupal_goto("node/$attachee->nid");    
+  }  
 }
 
 /**
@@ -229,16 +252,18 @@
 /**
  * Attach a node to its parent
  */
-function relativity_addparent($child_nid="", $parent_nid="") {
-  if (!$child_nid && !$parent_nid) {
-    $child_nid = arg(2);
-    $parent_nid = arg(4);
-  }
+function relativity_addparent($child_node, $parent_node, $attach_type='parent') {
   $output = "";
-
-  db_query('INSERT INTO {relativity} (nid, parent_nid) VALUES (%d, %d)', $child_nid, $parent_nid);
-  drupal_set_message(t('Node relationship created.'));
-  drupal_goto('node/'. $parent_nid);
+  //check that the nodes are loaded for attaching
+  if ((isset($child_node->nid)) && (isset($parent_node->nid))) {
+    db_query('INSERT INTO {relativity} (nid, parent_nid) VALUES (%d, %d)', $child_node->nid, $parent_node->nid);
+    drupal_set_message(t('Node relationship created.'));
+    ($attach_type == 'parent') ? drupal_goto('node/'. $parent_node->nid) : drupal_goto('node/'. $child_node->nid);
+   }
+   else {
+    drupal_set_message(t('Node relationship failed.'));
+    ($attach_type == 'parent') ? drupal_goto('node/'. $parent_node->nid) : drupal_goto('node/'. $child_node->nid);
+   }
 }
 
 /**
@@ -272,19 +297,20 @@
 function relativity_menu() {
   $items = array();
 
-    $items['relativity/listnodes/%relativity_node_list/parent/%node'] = array(
+    $items['relativity/listnodes/%relativity_node_list/%/%node'] = array(
       'title' => 'list of !type nodes to attach',
       'title arguments' => array('!type' => node_get_types('name', 2)),
       'load arguments' => array(4),
-      'page callback' => 'relativity_list_possible_children',
-      'page arguments' => array(2, 4),
+      'page callback' => 'relativity_list_possible_attachments',
+      'page arguments' => array(2, 3, 4),
       'access arguments' => array('add child relations'),
       'type' => MENU_CALLBACK,
     );
 
-    $items['relativity/addparent/%node/parent/%node'] = array(
+    $items['relativity/addparent/%node/%/%node'] = array(
       'title' => 'attach node to parent',
       'page callback' => 'relativity_addparent',
+      'page arguments' => array(2, 4, 3),
       'access callback' => 'node_access',
       'access arguments' => array('view', 2),
       'type' => MENU_CALLBACK,
@@ -768,6 +794,18 @@
   }
 }
 
+
+function relativity_load_parents($node, $type, $block = FALSE) {
+  $parent_nids = array();
+  $result = db_query(db_rewrite_sql('SELECT n.nid FROM {node} n LEFT OUTER JOIN {relativity} r ON n.nid=r.nid WHERE n.type = \'%s\' AND r.parent_nid=%d'), array($type, $node->nid));
+  // The number of nids returned by this array should be reasonably small.
+  // It's the number of child nodes of type=$type attached to the parent node = $node already.
+  while ($existing_nid = db_fetch_object($result)) {
+    $parent_nids[] = $existing_nid->nid;
+  }
+  return $parent_nids;
+}
+
 /**
  * Generate an array of ancestors for the given node.
  * This will keep looking for more ancestors until a circular path was found,
@@ -1004,6 +1042,7 @@
  * so we can manage our additional data appropriately.
  */
 function relativity_nodeapi(&$node, $op, $teaser, $page) {
+  //check to see if we're adding a new node to a relative
   if (is_numeric(arg(4))) {
     //check if parent node actually exists
     if (db_result(db_query("SELECT COUNT(nid) FROM {node} WHERE nid=%d", arg(4)))) {
@@ -1278,6 +1317,32 @@
 }
 
 /**
+ * recursively lists all types that could be parents of each allowed type
+ * returns an array of ancestor types, keyed by child type
+ * @param unknown_type $nid
+ */
+function relativity_list_parent_types() {
+  $result = array();
+  /**
+   * go through each type allowed to have relationships
+   * and find what it can be the child of
+   */
+  foreach (relativity_node_list() as $child_type => $child_type_name) {
+    $result[$child_type] = array();
+    foreach (relativity_node_list() as $parent_type => $parent_type_name) {          
+      $child_types = variable_get('relativity_type_' . $parent_type, FALSE);
+      if (is_array($child_types)) {        
+        if (in_array($child_type, $child_types)) {
+            $result[$child_type][] = $parent_type;
+        }
+      }
+    }
+  }
+  return $result;
+}
+
+
+/**
  * Implementing hook_token_values to present basic tokens
  * for relativity module
  */
@@ -1650,34 +1715,59 @@
  */
 function relativity_get_operation_links($parent) {
   $parent_nid = $parent->nid;
-
-  $childrentypes = relativity_childrentypes($parent);
-  if (count($childrentypes) == 0) {
-    return '';
-  }
-
-  foreach ($childrentypes as $type) {
-    if (relativity_may_add_child($parent, $type)) {
-      $type_name = node_get_types('name', $type);
-      $may_create = relativity_may_attach_new_child_type($parent->type, $type);
-
-      // only offer to let user create new child if user has 'create' access
-      // and common child relationship isn't required
-      if ($may_create) {
-        $type_for_url = str_replace('_', '-', $type);
-        $items[] = l(t('Create new !type', array('!type' => $type_name)), "node/add/$type_for_url/parent/$parent_nid", array('class' => 'relativity_create_'. $type));
+  $content = '';
+  /**
+   * add parent attachment links
+   */
+  $parenttypes = relativity_list_parent_types();
+  if (!(count($parenttypes[$parent->type]) == 0)) {
+    $content .= '<div class="relativity-parent-link-operations">';
+    foreach ($parenttypes[$parent->type] as $parent_type) {
+      $items = array();
+      $content .= '<div class="relativity-parent-operations-' . $type . '">';
+      $type_name = node_get_types('name', $parent_type);    
+      $content .= '</div> <!-- relativity-parent-operations -->';
+      if (user_access('add child relations')) {
+        $type_for_url = str_replace('_', '-', $parent_type);
+        $items[] = l(t('Attach this ' . node_get_types('name', $parent->type) . ' to a document of type: !type', array('!type' => $type_name)), "relativity/listnodes/$parent_type/child/$parent_nid", array('class' => 'relativity_attach_' . $type));
       }
-
-      // only show link to attach existing node when the potential child doesn't require a parent.
-      if ((!relativity_requires_parent($type) || relativity_multi_parent($type)) && user_access('add child relations')) {
-        $items[] = l(t('Attach existing !type', array('!type' => $type_name)), "relativity/listnodes/$type/parent/$parent_nid", array('class' => 'relativity_attach_'. $type));
+      if ($items) {
+        $content .= theme('item_list', $items);
       }
     }
+    $content .= '</div> <!-- relativity-parent-link-operations -->';
   }
-
-  if ($items) {
-    return '<div class="relativity_add_child">'. theme('item_list', $items) .'</div>';
+  /**
+   * add child addition links
+   */
+  $childrentypes = relativity_childrentypes($parent);
+  if (!(count($childrentypes) == 0)) {
+    $content .= '<div class="relativity-child-link-operations">';
+    foreach ($childrentypes as $type) {
+      if (relativity_may_add_child($parent, $type)) {
+        $items = array();
+        $content .= '<div class="relativity-child-operations-' . $type . '">';
+        $type_name = node_get_types('name', $type);
+        $may_create = relativity_may_attach_new_child_type($parent->type, $type);
+        // only offer to let user create new child if user has 'create' access
+        // and common child relationship isn't required
+        if ($may_create && node_access('update', $parent)) {
+          $type_for_url = str_replace('_', '-', $type);
+          $items[] = l(t('Create new !type', array('!type' => $type_name)), "node/add/$type_for_url/parent/$parent_nid", array('class' => 'relativity_create_' . $type));
+        }
+        // only show link to attach existing node when the potential child doesn't require a parent.
+        if ((!relativity_requires_parent($type) || relativity_multi_parent($type)) && user_access('add child relations')) {
+          $items[] = l(t('Attach existing !type', array('!type' => $type_name)), "relativity/listnodes/$type/parent/$parent_nid", array('class' => 'relativity_attach_' . $type));
+        }
+        if ($items) {
+          $content .= theme('item_list', $items);
+        }
+        $content .= '</div> <!-- relativity-child-operations' . $type . ' -->';
+      }
+    }
+    $content .= '</div> <!-- relativity-child-link-operations -->';
   }
+  return $content;
 }
 
 /************************ Block themes ***********************/
