Index: schema.xml
===================================================================
RCS file: /cvs/drupal/contributions/modules/apachesolr/schema.xml,v
retrieving revision 1.1.2.8
diff -u -r1.1.2.8 schema.xml
--- schema.xml	4 Nov 2008 14:29:55 -0000	1.1.2.8
+++ schema.xml	24 Feb 2009 07:28:08 -0000
@@ -292,8 +292,9 @@
    <dynamicField name="fmfield*"  type="sfloat"  indexed="true"  stored="true" multiValued="true"/>
    <dynamicField name="psfield*"  type="sdouble" indexed="true"  stored="true" multiValued="false"/>
    <dynamicField name="pmfield*"  type="sdouble" indexed="true"  stored="true" multiValued="true"/>
-
-
+ 
+   <!-- This field is used to store node access records, as opposed to CCK field data -->
+   <dynamicField name="nodeaccess*" type="sint"  indexed="true"  stored="true" multiValued="true"/>
 
    <!-- uncomment the following to ignore any fields that don't already match an existing
         field name or dynamic field, rather than reporting them as an error.
Index: modules/apachesolr/contrib/apachesolr_nodeaccess/apachesolr_nodeaccess.info
===================================================================
RCS file: modules/apachesolr/contrib/apachesolr_nodeaccess/apachesolr_nodeaccess.info
diff -N modules/apachesolr/contrib/apachesolr_nodeaccess/apachesolr_nodeaccess.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/apachesolr/contrib/apachesolr_nodeaccess/apachesolr_nodeaccess.info	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,5 @@
+name = Apache Solr node access
+description =  Integrates the node access system with Apache Solr search
+dependencies = apachesolr 
+package = ApacheSolr
+
Index: modules/apachesolr/contrib/apachesolr_nodeaccess/tests/apachesolr_nodeaccess.test
===================================================================
RCS file: modules/apachesolr/contrib/apachesolr_nodeaccess/tests/apachesolr_nodeaccess.test
diff -N modules/apachesolr/contrib/apachesolr_nodeaccess/tests/apachesolr_nodeaccess.test
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/apachesolr/contrib/apachesolr_nodeaccess/tests/apachesolr_nodeaccess.test	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,144 @@
+<?php
+// $Id$
+
+class DrupalApacheSolrNodeAccess extends DrupalTestCase {
+  function get_info() {
+    return array(
+      'name' => 'Node Access',
+      'description' => 'Test Access Control',
+      'group' => 'Apache Solr tests'
+    );
+  }
+
+  function setUp() {
+    parent::setUp("nodeaccess", "apachesolr", "apachesolr_search", "apachesolr_nodeaccess");
+
+	print_r($this);
+
+     // Create a basic user, which is subject to moderation.
+    $permissions = array(
+      'access content',
+      'create page content',
+      'edit own page content',
+      'create story content',
+      'edit own story content',
+    );
+    $this->basic_user = $this->drupalCreateUserRolePerm($permissions);
+  }
+
+  function testIndexing() {
+    $basic_user = $this->basic_user;
+    // Login as basic user to perform initial content creation.
+    $this->drupalLoginUser($basic_user);
+
+    //Create 2 nodes
+    $role_restricted_node = new StdClass();
+    
+    $role_restricted_node->title = $this->randomName(32);
+    $role_restricted_node->body  = $this->randomName(32);
+    $role_restricted_node->comment = 2;
+    $role_restricted_node->changed   = time();
+    $role_restricted_node->format    = FILTER_FORMAT_DEFAULT;
+    $role_restricted_node->moderate  = 0;
+    $role_restricted_node->promote   = 0;
+    $role_restricted_node->revision  = 1;
+    $role_restricted_node->log       = '';
+    $role_restricted_node->status    = 1;
+    $role_restricted_node->sticky    = 0;
+    $role_restricted_node->type      = 'page';
+    $role_restricted_node->revisions = NULL;
+    $role_restricted_node->taxonomy  = NULL;    
+    node_save($node);
+
+    $author_restricted_node   = new StdClass();
+    $author_restricted_node->title = $this->randomName(32);
+    $author_restricted_node->body  = $this->randomName(32);
+    $role_restricted_node->comment = 2;
+    $role_restricted_node->changed   = time();
+    $role_restricted_node->format    = FILTER_FORMAT_DEFAULT;
+    $role_restricted_node->moderate  = 0;
+    $role_restricted_node->promote   = 0;
+    $role_restricted_node->revision  = 1;
+    $role_restricted_node->log       = '';
+    $role_restricted_node->status    = 1;
+    $role_restricted_node->sticky    = 0;
+    $role_restricted_node->type      = 'page';
+    $role_restricted_node->revisions = NULL;
+    $role_restricted_node->taxonomy  = NULL;    
+    node_save($node);
+
+    // No Drupal Logout in SimpleTest 1    $this->drupalLogout();
+
+    $roles = array_keys($basic_user->roles);
+    // The assigned role will be the last in the array.
+    $assigned_role = end($roles);
+    $role_grant = array (
+        'gid' => $assigned_role,
+        'realm' => 'nodeaccess_rid',
+        'grant_view' => '1',
+        'grant_update' => '0',
+        'grant_delete' => '0',
+    );
+    node_access_write_grants($role_restricted_node, array($role_grant), "nodeaccess_rid");
+
+    $author_grant = array (
+        'gid' => $basic_user->uid,
+        'realm' => 'nodeaccess_author',
+        'grant_view' => '1',
+        'grant_update' => '0',
+        'grant_delete' => '0',
+    );
+
+    node_access_write_grants($author_restricted_node, array($author_grant), "nodeaccess_author");
+
+    $include_path = get_include_path();
+    set_include_path('./'. drupal_get_path('module', 'apachesolr') .'/SolrPhpClient/');
+    include_once('Apache/Solr/Service.php');
+    set_include_path($include_path);
+
+    $document = new Apache_Solr_Document();
+    apachesolr_nodeaccess_apachesolr_update_index($document, $role_restricted_node);
+    $this->assertEqual($document->nodeaccess_nodeaccess_rid[0], $assigned_role, "Solr Document being indexed is restricted by the proper role");
+
+    $document = new Apache_Solr_Document();
+    apachesolr_nodeaccess_apachesolr_update_index($document, $author_restricted_node);
+    $this->assertEqual($document->nodeaccess_nodeaccess_author[0], $basic_user->uid, "Solr Document being indexed is restricted by the proper author");
+  }
+
+  function testQuery() {
+    $basic_user = $this->basic_user;
+    // Login as basic user
+    $this->drupalLoginUser($basic_user);
+
+    include_once drupal_get_path('module', 'apachesolr') .'/Solr_Base_Query.php';
+    $query = apachesolr_drupal_query();
+    $params = array();
+
+    $subquery = _apachesolr_nodeaccess_build_subquery($basic_user);
+
+    $roles = array_keys($basic_user->roles);
+    $assigned_role = end($roles);
+
+    $expected_criterion = array(
+      "nodeaccess_all" => 0,
+      "nodeaccess_nodeaccess_rid" => array(2, $assigned_role),
+      "nodeaccess_nodeaccess_uid" => $basic_user->uid,
+      "nodeaccess_nodeaccess_author" => $basic_user->uid,
+    );
+
+    $fields = $subquery->get_fields();
+
+    foreach ($fields as $field) {
+      if (is_array($expected_criterion[$field['#name']])) {
+        $this->assertTrue(in_array($field['#value'], $expected_criterion[$field['#name']]), t("Expected node access grant @name == @value found", array('@name' => $field['#name'], '@value' => $field['#value'])));
+        //This is sorta a bug
+        $found_criterion[$field['#name']] = $expected_criterion[$field['#name']];
+      } else {
+        $this->assertEqual($expected_criterion[$field['#name']], $field['#value'], t("Expected node access grant @name == @value found", array('@name' => $field['#name'], '@value' => $field['#value'])));
+        $found_criterion[$field['#name']] = $expected_criterion[$field['#name']];
+      }
+    }
+
+    $this->assertEqual($expected_criterion, $found_criterion, "All Criteria was accounted for in fields. If not accounted for, Unaccounted Criteria [" . var_export(array_diff($expected_criterion, $found_criterion), 1) . "]");
+  }
+}
Index: modules/apachesolr/contrib/apachesolr_nodeaccess/apachesolr_nodeaccess.module
===================================================================
RCS file: modules/apachesolr/contrib/apachesolr_nodeaccess/apachesolr_nodeaccess.module
diff -N modules/apachesolr/contrib/apachesolr_nodeaccess/apachesolr_nodeaccess.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/apachesolr/contrib/apachesolr_nodeaccess/apachesolr_nodeaccess.module	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,111 @@
+<?php
+// $Id$
+
+/**
+ * Implementation of apachesolr_update_index
+ */
+function apachesolr_nodeaccess_apachesolr_update_index(&$document, $node) {
+  if (count(module_implements('node_grants'))) {
+    // Get node access grants
+    $result = db_query('SELECT * from {node_access} WHERE nid = %d AND grant_view = 1', $node->nid);
+    while ($grant = db_fetch_object($result)) {
+      $key = 'nodeaccess_'. $grant->realm;
+      $document->setMultiValue($key, $grant->gid);
+    }
+  }
+}
+
+/**
+ * Creates a Solr query for a given user
+ *
+ * @param $account an account to get grants for and build a solr query
+ */
+function _apachesolr_nodeaccess_build_subquery($account) {
+  if (!user_access('administer nodes', $account) && count(module_implements('node_grants'))) {
+    // Get node access perms
+    $node_access_query = "";
+    $node_access_query = new Solr_Base_Query('', 'OR');
+    $grants = node_access_grants('view', $account->uid);
+    if (empty($grants)) {
+      // If they can't see any content, we might as well not bother searching.
+      // Catch the exception to null out the query.
+      throw new Exception("This user cannot access any content!");
+    }
+
+    foreach ($grants as $realm => $gids) {
+      foreach ($gids as $gid) {
+        $node_access_query->add_field('nodeaccess_' . $realm, $gid);
+      }
+    }
+    return $node_access_query;
+  }
+  return NULL;
+}
+
+/**
+ * Implementation of hook_apachesolr_modify_query().
+ */
+function apachesolr_nodeaccess_apachesolr_modify_query(&$query, &$params) {
+   global $user;
+   
+   try {
+    $subquery = _apachesolr_nodeaccess_build_subquery($user);
+  } catch (Exception $e) {
+    $query = NULL;
+    watchdog("apachesolr_nodeaccess", 'User %name (UID:!uid) is not allowed to access any content', array('%name' => $user->name, '!uid' => $user->uid));
+    return;
+  }
+  if (!empty($subquery)) {
+    $query->add_subquery($subquery, 'AND');
+  }
+}
+
+/**
+ * Implementation of hook_nodeapi().
+ *
+ * Listen to this hook to find out when a node is being saved.
+ */
+function apachesolr_nodeaccess_nodeapi(&$node, $op) {
+  switch ($op) {
+    case 'insert':
+    case 'update':
+      // hook_nodeapi() is called before hook_node_access_records() in node_save().
+      $node->apachesolr_nodeaccess_ignore = 1;
+      break;
+  }
+}
+
+/**
+ * Implementation of hook_node_access_records().
+ *
+ * Listen to this hook to find out when a node needs to be re-indexed
+ * for its node access grants.
+ */
+function apachesolr_nodeaccess_node_access_records($node) {
+  // node_access_needs_rebuild() will usually be TRUE during a
+  // full rebuild.
+  // In Drupal 5 there is no checking for this, so removing it for now.
+  if (empty($node->apachesolr_nodeaccess_ignore)) { // Removed, From Drupal 6 version && !node_access_needs_rebuild()) {
+    db_query('UPDATE {node} SET changed = %d WHERE nid = %d', time(), $node->nid);
+  }
+}
+
+/**
+ * Implementation of hook_form_alter().
+ */
+function apachesolr_nodeaccess_form_alter($form_id, &$form) {
+  if ($form_id == 'node_configure_rebuild_confirm') {
+    $form['#submit'][] = 'apachesolr_nodeaccess_rebuild_nodeaccess';
+  }
+}
+
+/**
+ * Forces Solr to do a total re-index.
+ * This is unfortunate because not every node is going to be affected, but there is little we can do.
+ */
+function apachesolr_nodeaccess_rebuild_nodeaccess(&$form, $form_state) {
+  drupal_set_message(t('Solr search index will be rebuilt.'));
+  node_access_rebuild();  
+  ApacheSolrUpdate::reset('apachesolr');
+}
+
