### Eclipse Workspace Patch 1.0
#P Drupal
Index: Drupal6/Modules/node_embed/node_embed.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/node_embed/node_embed.module,v
retrieving revision 1.5
diff -u -r1.5 node_embed.module
--- Drupal6/Modules/node_embed/node_embed.module	8 Sep 2010 02:11:40 -0000	1.5
+++ Drupal6/Modules/node_embed/node_embed.module	4 Nov 2010 23:36:50 -0000
@@ -10,16 +10,22 @@
  * @file module code to define the input filter for node embedding.
  */
 
+global $NODE_EMBED_REGEX,$NODE_EMBED_REGEX_TRIMMED;
+$NODE_EMBED_REGEX = "/\[{2}\s*(nid:\d+.*)\]{2}/";
+$NODE_EMBED_REGEX_TRIMMED = "/^nid:(\d+)((\s[\d\w]+:[\d\w]+)*)$/";
+
 /**
  * Implementation of hook_filter()
  */
 function node_embed_filter($op, $delta = 0, $format = -1, $text = '') {
+  global $NODE_EMBED_REGEX;
+  
   switch ($op) {
   case 'list':
     return array(0 => t('Insert node'));
 
   case 'description':
-    return t('By including the syntax [[nid:(node_id)]], this filter will embed the node with given NID');
+    return t('By including the syntax <code>[[nid:node_id]]</code> (eg <code>[[nid:345]]</code>), this filter will embed the node with given NID');
 
   case 'prepare':
     return $text;
@@ -28,8 +34,9 @@
     return TRUE;
 
   case "process":
-    // replace on [[nid: ###]]
-    return preg_replace_callback('/\[\[nid:(\d+)\]\]/', '_node_make_replacements', $text);
+    // replace on [[nid:###]]
+    // replace on [[nid:### key1:value1 key2:value2 key3:value3 .... ]]
+    return preg_replace_callback($NODE_EMBED_REGEX, '_node_make_replacements',$text);
   }
 }
 
@@ -44,7 +51,7 @@
  * Implementation of hook_preprocess_node()
  */
 function node_embed_preprocess_node(&$vars) {
-  if ($vars['node_embedded']) { 
+  if (!empty($vars['node_embedded'])) { 
     $vars['template_files'][] = "node-embed--default";
     $vars['template_files'][] = 'node-embed--' . $vars['type'];
   }
@@ -60,13 +67,41 @@
  *    The rendered HTML replacing the embed code
  */ 
 function _node_make_replacements($matches) {
-  if (is_numeric($matches[1])) {
-    $node = node_load($matches[1]);
-    $node->node_embedded = TRUE;
+  $params_array = array();
+
+  $embedded_node_params = node_embed_get_embedded_node($matches[1]);
+  
+  if (isset($embedded_node_params)) {
+    $nid = key($embedded_node_params);
     
+    // Load the node.
+    $node = node_load($nid);
+    
+    if (module_exists('translation')) {
+      global $language;
+      $current_lang = $language->language; // Get the current language.
+      
+      if ($node->language != $current_lang) {
+        $trans_set = translation_node_get_translations($node->tnid); // Get the transl set for that node if one exists.
+
+        // Load the translation object for the current language(if one exists).
+        $trans_object = $trans_set[$current_lang];
+        
+        // If a translation object exists for the current language then work some magic.
+        // If it doesn't then return the text untouched.
+        if ($trans_object) {
+          $trans_nid = $trans_object->nid;
+          $node = node_load($trans_nid);
+        }
+      }
+    }
+
     if (!$node->status || !node_access('view', $node)) {
       return '';
     }
+    else {
+      $node->node_embedded=current($embedded_node_params);
+    }
   }
   else {
     return '';
@@ -143,19 +178,211 @@
  * validation for the node_embed filter.
  * we do not allow nodes to embed in themselves.
  * results in segment fault.
+ * 
+ * This checks whether there is an attempt to self embed a node or
+ * if there is an to embed a node when it is all ready embedded in a
+ * chain of nodes.
+ * 
+ * The appropriate error messages are displayed
  */
 function node_embed_validate($form, &$form_state) {
-  $nid = $form['nid']['#value'];  
-  if ($nid) {
-    $needle = "[[nid:$nid]]";
-    $found = strpos($form['#post']['body'], $needle);
-    if ($found === FALSE) {
-      // nothing found
+  // Body is not the only entry of content and of embedding node
+  // Fields of Content Type
+  $nid = $form['nid']['#value'];
+  if ($nid){
+    // Perform recursive check on embedded node
+    $node_content_fields= node_embed_get_node_field_values($form['#post']);
+    $conflict_fields = _valid_embed_reference($nid, $nid, $form['#post'],true);
+
+     
+    if (count($conflict_fields) > 0) {
+      $msg = t('<strong>Node Embed Module Error</strong><br/>');
+      $msg .= t('<ul>');
+      foreach($conflict_fields as $field_name => $conflict_nodes) {
+        foreach($conflict_nodes as $attempted_embed_node_id=>$embedded_node) {
+          $msg .= t('<li>');
+          $msg .= t('Cannot use node ID "' . $attempted_embed_node_id . '" in Field "' . _get_content_field_label($field_name) . '"<br/>');
+          if ($nid == $attempted_embed_node_id) {
+            $msg .= t('Cannot embed a node into itself!');
+          }
+          else if (is_null($embedded_node)) {
+            $msg .= t('Node ID "<strong>'. $attempted_embed_node_id . '</strong>" DOES NOT EXIST!');
+          }
+          else {
+            // TODO: Is it possible to add an achor reference ?
+            $msg .= t('Node ID "<strong>'. $nid . '</strong>" is all ready embedded in node ID "' . key(current($embedded_node)). '" in Field "' . _get_content_field_label(current(current($embedded_node))) . '"<br/>');
+            if (key(current($embedded_node)) != $attempted_embed_node_id) {
+              $msg .= t('Node ID "'.  key(current($embedded_node)) . '" is embedded in node ID "<strong>' . $attempted_embed_node_id . '</strong>" in Field "' . _get_content_field_label(key($embedded_node)) . '"<br/>');
+            }
+          }
+          $msg .= t('</li>');
+        }
+      }
+      $msg .= t('</ul>');
+      form_set_error('edit-body', $msg);
     }
-    else {
-      form_set_error('edit-body', t('A node is not allowed to embed in itself.'));
+  }
+}
+
+/**
+ * This recursive function performs a check on each node that is to be embedded
+ * that the node is not trying to embed with itself or create a circular reference.
+ *
+ * @param int $nid	- Current Node ID being evaluated
+ * @param int $reference_node - Node ID to compare to
+ * @param array $form	- The node editing form
+ *
+ * @return array
+ * 					returns an array list of fields that have conflicting embedded nodes with references to associated fields
+ *   'field_name' =>
+ *  		array (
+ *   			attempted_embedded_node_id =>
+ *   				array (
+ *     					'attempted_embedded_node_field_name' => array (conflict_node_id => 'conflict_node_field_name',),
+ *   				),
+ * 			),
+ *
+ */
+function _valid_embed_reference($nid, $reference_node,$node_properties, $start_recurse=false) {
+  global $NODE_EMBED_REGEX;
+  global $_node_embed_result_array;
+  global $_node_embed_orig_field;
+  global $_node_embed_attempted_node_embed;
+  global $_node_embed_parent_field;
+   
+  if ($start_recurse) {
+    $_node_embed_parent_field = 'self';
+  }
+
+  $node_embed_field_list = node_embed_get_node_field_values($node_properties);
+
+  $found = FALSE;
+  foreach($node_embed_field_list as $field_name => $node_embed_body) {
+    if ($start_recurse) {
+      $_node_embed_orig_field=$field_name;
+    }
+
+    $match_count = preg_match_all($NODE_EMBED_REGEX,$node_embed_body, $matches);
+    if ($match_count !==FALSE && $match_count != 0) {
+      for ($i=0; $i < $match_count; $i++) {
+        $attempted_embed_node_params = node_embed_get_embedded_node($matches[1][$i]);
+        if (!empty($attempted_embed_node_params)) {
+          if($embedded_node_id = key($attempted_embed_node_params)) {
+            if ($start_recurse) {$_node_embed_attempted_node_embed=$embedded_node_id;}
+            if (node_load($embedded_node_id )) {
+              if($found = (is_numeric($embedded_node_id ) && $embedded_node_id == $reference_node)) {
+                $_node_embed_result_array[$_node_embed_orig_field][$_node_embed_attempted_node_embed]=array($_node_embed_parent_field => array($nid => $field_name));
+              }    // Check for Circular Reference
+              elseif (is_numeric($embedded_node_id)) {
+                $_node_embed_parent_field = $field_name;
+                _valid_embed_reference($embedded_node_id ,$reference_node, get_object_vars(node_load($embedded_node_id)));
+              }
+            }
+            else {
+              $_node_embed_result_array[$_node_embed_orig_field][$_node_embed_attempted_node_embed]=NULL;
+            }
+          }
+        }
+      }
     }
   }
+
+  return $_node_embed_result_array;
+}
+
+/**
+ * This function returns an array of content fields that
+ * use the node embedded input filter and their corresponding
+ * values in those fields
+ *
+ * @param array $node_properties
+ * @return array $node_embed_field_list
+ */
+function node_embed_get_node_field_values($node_properties) {
+  $node_embed_field_list = array();
+
+  if (array_key_exists('body', $node_properties) && array_key_exists('format', $node_properties)) {
+    if (is_numeric($node_properties['format'])) {
+      $num_rows = db_result(db_query("SELECT count(*) FROM {filters} WHERE format='%d' AND module = 'node_embed'", $node_properties['format']));
+      if ($num_rows >= 1) {
+        $node_embed_field_list['body'] =  $node_properties['body'];
+      }
+    }
+  }
+
+  if (module_exists('content')) {
+    // Loop thru POST fields to see if there are any matches
+    // Look for 'field_XXXXX" and check on filter format
+    foreach($node_properties as $field_name => $value) {
+      if (strpos($field_name, 'field_') !== FALSE) {
+        foreach($value as $key => $field_value) {
+          if (array_key_exists('format', $field_value)) {
+            if (is_numeric($field_value['format'])) {
+              $num_rows = db_result(db_query("SELECT count(*) FROM {filters} WHERE format='%d' AND module = 'node_embed'", $field_value['format']));
+              if ($num_rows >= 1) {
+                $node_embed_field_list[$field_name] =  $field_value['value'];
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  return  $node_embed_field_list;
+}
+
+/**
+ * Get the label name of the CCK Field
+ * @param string $field_name
+ * 
+ * @return string
+ */
+function _get_content_field_label($field_name) {
+  if (empty($field_name)) return '';
+  if (strcmp($field_name, 'body')==0) return 'Body';
+
+  if (module_exists('content')) {
+    $info = content_fields($field_name);
+    return $info['widget']['label'];
+  }
+}
+
+/**
+ * The function will parse an attempted embed node token
+ * 		"[[ nid:xxx ..... ]]"
+ * and return an array with node as the key and any associated key:value pairs
+ * 
+ * @param $attempted_embed_token
+ * 
+ * @return an array with the embedded node as key
+ */
+function node_embed_get_embedded_node($attempted_embed_token) {
+  global $NODE_EMBED_REGEX_TRIMMED;
+  
+  $embedded_node_params = NULL;
+  $attempted_token = preg_replace('/\s\s+/', ' ', trim($attempted_embed_token));
+  $match_count = preg_match($NODE_EMBED_REGEX_TRIMMED,$attempted_token, $matches);
+    
+  if ($match_count) {
+    if (is_numeric($matches[1])) {
+      // $matches is of the form "key:value key:value key:value ..."
+      // Use tab and newline as tokenizing characters as well
+      $key_value_array=NULL;
+      $tok = strtok($matches[2], " ");
+
+      //TODO:This assumes that the key valus are unique
+      while ($tok !== false) {
+        list($key, $value) =explode(":", $tok);
+        $key_value_array[$key] =$value;
+        $tok = strtok(" ");
+      }
+
+      $embedded_node_params[$matches[1]]=$key_value_array;
+    }
+  }
+  
+  return $embedded_node_params;
 }
 
 /**
