--- /Users/dblake/tmp/nodeaccess_autoreference/nodeaccess_autoreference.module	2009-10-07 12:27:19.000000000 -0500
+++ /Users/dblake/Sites/winstage/sites/all/modules/nodeaccess_autoreference/nodeaccess_autoreference.module	2010-03-26 11:54:43.000000000 -0500
@@ -15,7 +15,7 @@
 /**
  * Implementation of hook_menu().
  */
-function nodeaccess_autoreference_menu() { 
+function nodeaccess_autoreference_menu() {
   $items['admin/settings/nodeaccess_autoreference'] = array(
     'title' => t('Node Access Auto Reference Settings'),
     'description' => t('Settings page for Auto References.'),
@@ -31,7 +31,7 @@ function nodeaccess_autoreference_menu()
     'file' => 'nodeaccess_autoreference.admin.inc',
     'access arguments' => array('administer autoreference settings'),
     'type' => MENU_CALLBACK,
-  ); 
+  );
 
   return $items;
 }
@@ -66,51 +66,87 @@ function nodeaccess_autoreference_perm()
  */
 function nodeaccess_autoreference_form_alter(&$form, $form_state, $form_id) {
   if (!variable_get('nodeaccess_autoreference_disable', FALSE)
-    && variable_get('nodeaccess_autoreference_form_alter_check', FALSE) 
-    && !$form_state['submitted'] && strpos($form_id, '_node_form') !== FALSE ) {
+  && variable_get('nodeaccess_autoreference_form_alter_check', FALSE)
+  && !$form_state['submitted'] && strpos($form_id, '_node_form') !== FALSE ) {
     $ctype = current(explode('_', $form_id)); /* get content type name */
     module_load_include('inc', 'nodeaccess_autoreference'); // load additional function from included file
     foreach( content_fields() as $field_name => $field_data ) {
       if ($field_data['type_name'] == $ctype && $field_data['type'] == 'nodereference') {
-          // get the node types which could be referenced to current node
-          $referenced_types = $field_data['referenceable_types'] ? drupal_map_assoc($field_data['referenceable_types']) : array(); // select types which can be referenced
-          unset($referenced_types[0]);
-          foreach ($referenced_types as $key => $name) {
-            $rows = db_query("SELECT nid FROM {node} WHERE type = '%s'", $name);
-            while ($row = db_fetch_object($rows)) {
-              $node = node_load($row->nid);
-              if (!variable_get('nodeaccess_autoreference_disable', FALSE) && $grants = nodeaccess_autoreference_node_get_grants($node)) {
-                nodeaccess_autoreference_node_write_grants($node, $grants);
-              } else if (!variable_get('nodeaccess_autoreference_disable', FALSE)) {
-                  $args = array('%nid' => $node->nid, '%permission' => print_r($grants, TRUE), '%option' => 'nodeaccess_autoreference_disable');
-                  $msg = 'Option: %option disabled! Not added permissions to node %nid. (permission: %permission)';
-              }
-              if (variable_get('nodeaccess_autoreference_debug', FALSE) && user_access('administer autoreference settings')) {
-                drupal_set_message(t($msg, $args), 'status');
-              }
+        // get the node types which could be referenced to current node
+        $referenced_types = $field_data['referenceable_types'] ? drupal_map_assoc($field_data['referenceable_types']) : array(); // select types which can be referenced
+        unset($referenced_types[0]);
+        foreach ($referenced_types as $key => $name) {
+          $rows = db_query("SELECT nid FROM {node} WHERE type = '%s'", $name);
+          while ($row = db_fetch_object($rows)) {
+            $node = node_load($row->nid);
+            if (!variable_get('nodeaccess_autoreference_disable', FALSE) && $grants = nodeaccess_autoreference_node_get_grants($node)) {
+              nodeaccess_autoreference_node_write_grants($node, $grants);
+            } else if (!variable_get('nodeaccess_autoreference_disable', FALSE)) {
+              $args = array('%nid' => $node->nid, '%permission' => print_r($grants, TRUE), '%option' => 'nodeaccess_autoreference_disable');
+              $msg = 'Option: %option disabled! Not added permissions to node %nid. (permission: %permission)';
+            }
+            if (variable_get('nodeaccess_autoreference_debug', FALSE) && user_access('administer autoreference settings')) {
+              drupal_set_message(t($msg, $args), 'status');
             }
           }
+        }
       }
     } // end: foreach
   } // end: if
+
+  //lets add some permission checking checkboxes to associate to a user-reference field.
+  //@todo Maybe we should turn on (enable) userreference for specific fields?
+  if($form_id == 'content_field_edit_form') {
+    if($form['#field']['type'] == 'userreference') {
+      $field = $form['#field']['field_name'];
+      $ctype = $form['#field']['type_name'];
+      //lets add in our permissions for this node to give to our grants
+      $form['field'][$ctype.'_'.$field.'_permissions'] = array(
+        '#type' => 'checkboxes',
+        '#title' => 'User access permissions for node',
+        '#options' => array('update' => 'Update', 'delete' => 'Delete'), //@todo Maybe add array('view' => 'View') 
+        '#default_value' => variable_get($ctype.'_'.$field.'_permissions', array())
+      );
+      //add our submit handler
+      $form['#submit'][] = 'nodeaccess_autoreference_access_submit';
+    }
+  }
+}
+
+function nodeaccess_autoreference_access_submit($form, $form_state) {
+  $field = $form_state['values']['field_name'];
+  $ctype = $form_state['values']['type_name'];
+  //setup permissions
+  $perms = $form_state['values'][$ctype.'_'.$field.'_permissions'];
+  if(is_array($perms)) {
+    $var = array();
+    foreach($perms as $key => $value) {
+      if($value != "0") {
+        $var[$value] = $value;
+      }
+    }
+    //set the variable for the field and content type
+    variable_set($ctype.'_'.$field.'_permissions', $var);
+  }
 }
 
 /**
  * Implementation of hook_views_pre_execute()
+ * @todo: Find out whats wrong with this function and how it filters out our results in this view
  */
 function nodeaccess_autoreference_views_pre_execute(&$view) {
   if (variable_get('nodeaccess_autoreference_views_check', FALSE)) {
     module_load_include('inc', 'nodeaccess_autoreference'); // load additional function from included file
     $replacements = module_invoke_all('views_query_substitutions', $this);
-    $query = str_replace(array_keys($replacements), $replacements, $view->build_info['query']); 
+    $query = str_replace(array_keys($replacements), $replacements, $view->build_info['query']);
     $result = db_query($query, $view->build_info['query_args']);
     while ($row = db_fetch_object($result)) {
       $node = node_load($row->nid);
-      if (!variable_get('nodeaccess_autoreference_disable', FALSE) && $grants = nodeaccess_autoreference_node_get_grants($node)) {
+      if (!variable_get('nodeaccess_autoreference_disable', FALSE) && !node_access('view', $node) && $grants = nodeaccess_autoreference_node_get_grants($node)) {
         nodeaccess_autoreference_node_write_grants($node, $grants);
       } else if (!variable_get('nodeaccess_autoreference_disable', FALSE)) {
-          $args = array('%nid' => $node->nid, '%permission' => print_r($grants, TRUE), '%option' => 'nodeaccess_autoreference_disable');
-          $msg = 'Option: %option disabled! Not added permissions to node %nid. (permission: %permission)';
+        $args = array('%nid' => $node->nid, '%permission' => print_r($grants, TRUE), '%option' => 'nodeaccess_autoreference_disable');
+        $msg = 'Option: %option disabled! Not added permissions to node %nid. (permission: %permission)';
       }
       if (variable_get('nodeaccess_autoreference_debug', FALSE) && user_access('administer autoreference settings')) {
         drupal_set_message(t($msg, $args), 'status');
@@ -131,28 +167,63 @@ function nodeaccess_autoreference_nodeap
       unset($na_skip_next_load);
       return;
     }
-
     if (!node_access('view', $node)
-      || (!node_access('update', $node) && user_access("edit referenced $node->type content"))
-      || (!node_access('delete', $node) && user_access("delete referenced $node->type content")))
+    || (!node_access('update', $node) && user_access("edit referenced $node->type content"))
+    || (!node_access('delete', $node) && user_access("delete referenced $node->type content")))
     {
       module_load_include('inc', 'nodeaccess_autoreference'); // load additional function from included file
       if (!variable_get('nodeaccess_autoreference_disable', FALSE) && $grants = nodeaccess_autoreference_node_get_grants($node)) {
         nodeaccess_autoreference_node_write_grants($node, $grants);
       } else if (!variable_get('nodeaccess_autoreference_disable', FALSE)) {
-          $args = array('%nid' => $node->nid, '%permission' => print_r($grants, TRUE), '%option' => 'nodeaccess_autoreference_disable');
-          $msg = 'Option: %option disabled! Not added permissions to node %nid. (permission: %permission)';
+        $args = array('%nid' => $node->nid, '%permission' => print_r($grants, TRUE), '%option' => 'nodeaccess_autoreference_disable');
+        $msg = 'Option: %option disabled! Not added permissions to node %nid. (permission: %permission)';
       }
       watchdog('permission', $msg, $args, WATCHDOG_INFO);
       if (variable_get('nodeaccess_autoreference_debug', FALSE) && user_access('administer autoreference settings')) {
         drupal_set_message(t($msg, $args), 'status');
       }
-    } if (variable_get('nodeaccess_autoreference_debug', FALSE)) {
+    }
+    if (variable_get('nodeaccess_autoreference_debug', FALSE)) {
       module_load_include('inc', 'nodeaccess_autoreference'); // load additional function from included file
       nodeaccess_autoreference_find_connection($node);
     }
   }
-} 
+  //we need to clear cache on update if user access has changed
+  switch($op) {
+    case 'update':
+      //dynamic on user reference fields.
+      //we need to compare our old node with our new node and see what users (if any) have been removed and then clear that users cache.
+      $userref_fields = _nodeaccess_autoreference_get_userref_fields($node->type);
+      //if we have user fields lets loop through and compare removed users and clear cache accordingly.
+      if(is_array($userref_fields) && !empty($userref_fields)) {
+        $old_node = node_load($node->nid);
+        foreach($userref_fields as $field) {
+          $old_users = array();
+          foreach($old_node->$field as $value) {
+            $old_users[] = $value['uid'];
+          }
+          $new_users = array();
+          foreach($node->$field as $value) {
+            $new_users[] = $value['uid'];
+          }
+          //this will get us our users that were removed from the old array
+          $clear_cache = array_diff($old_users, $new_users);
+          if(is_array($clear_cache) && !empty($clear_cache)) {
+            //lets itereate through all our users that were removed from this node and clear their cache.
+            foreach($clear_cache as $uid) {
+              //clear our cache
+              cache_clear_all('nodeaccess_autoreference_uid:'.$uid, 'cache', TRUE);
+              //clear our node access for the user, it will then be rebuilt when they try to access each node.
+              db_query("DELETE FROM {node_access} WHERE gid=%d AND realm='%s'", $uid, 'nodeaccess_autoreference_owner');
+            }
+          }
+        }
+      }
+      break;
+    case 'validate':
+      //we need to verify that users can only be assigned to one user reference field?
+  }
+}
 
 /**
  * Implementation of hook_node_access_records().
@@ -165,3 +236,38 @@ function nodeaccess_autoreference_node_a
   return nodeaccess_autoreference_node_get_grants($node);
 }
 
+/**
+ * Return array of content userreference fields for clearing cache correctly.
+ */
+function _nodeaccess_autoreference_get_userref_fields($content_type) {
+  $fields = array();
+  $userref_fields = _nodeaccess_autoreference_content_fields($content_type);
+  if (is_array($userref_fields)) {
+    foreach ($userref_fields as $field) {
+      // Only kickout user reference fields
+      if ($field['type'] == 'userreference') {
+        $fields[] = $field['field_name'];
+      }
+    }
+  }
+  return $fields;
+}
+
+/**
+ * Return a list of all fields applicable to a specific content type.
+ *
+ * @param $content_type_name
+ *   If not empty, return information of the field within the context of this content
+ *   type.
+ */
+function _nodeaccess_autoreference_content_fields($content_type_name = NULL) {
+  $info = _content_type_info(); // CCK function. All information on content types, fields, and related structures.
+  if (isset($info['fields'])) {
+    if (empty($content_type_name)) {
+      return $info['fields'];
+    }
+    else {
+      return $info['content types'][$content_type_name]['fields'];
+    }
+  }
+}
\ No newline at end of file
