Using hook_apachesolr_modify_query()

SomebodySysop - November 14, 2009 - 22:01
Project:Apache Solr Search Integration
Version:6.x-1.0-rc3
Component:Code
Category:support request
Priority:normal
Assigned:Unassigned
Status:closed
Description

I need a little help in figuring out how to use hook_apachesolr_modify_query(). I have the annotations.module installed. When I execute a search, apachesolr searches annotations as well. Problem is that it returns nodes which have private annotations to anonymous users.

I need to figure out a way to use hook_apachesolr_modify_query() to reject such nodes that anonymous users should not see.

I've looked at apachesolr_nodeaccess_apachesolr_modify_query(). It appears to use the following format:

<?php
    $query
->add_subquery($subquery, 'OR');
?>

The $subquery seems to be built like this:
<?php
         
// From _apachesolr_nodeaccess_build_subquery()
         
$node_access_query->add_filter('nodeaccess_' . apachesolr_site_hash() . '_' . $realm, $gid);
?>

But, I don't see a way to say:

If the user does NOT have "view" access to the annotations in this node, then don't display it (even if he has the node access "view" grant).

Could someone please point me to where I can get more info on using this function to filter query results?

Thanks!

#1

pwolanin - November 15, 2009 - 16:22

You can only filter by some property that is in the document int he Solr index.

So - for node access we are indexing the node grants into Solr - you would have to do something similar (using a dynamic field) for your nodes so that for each oneSolr can determine if it has private annotations.

If annontations are simply just public or private, the added property could just be a boolean (or int) field.

#2

SomebodySysop - November 16, 2009 - 21:21

OK, thanks for the response!

I figure the easiest way would be to create node grants for the annotations so that they would be processed by the apachesolr_nodeaccess.module.

However, when I try and test this using an existing node grant, I'm not getting the anticipated results.

For example, in apachesolr_nodeaccess_apachesolr_update_index, the following dynamic field is added to the index (from node grants):

nodeaccess_a3eb1dd69364_og_public

According to the node_access table, the nodes that are public will have a gid value of "0":
nid: 2968 
gid: 0
realm: og_public
grant_view: 1
grant_update: 0
grant_delete: 0

So, theoretically, if the node is OG public, I should be able to filter on this dynamic apache solr index field.

Now, in my hook_apachesolr_modify_query() code, I enter the following:

<?php
 
// If the user is not logged in, then only list "public" group nodes
 
if ($user->uid == 0) {
   
$key = 'nodeaccess_' . apachesolr_site_hash() . '_og_public';
   
$query->add_filter($key, 0);        
  }
?>

The result no nodes appear at all, even though most of my nodes are OG public. I've checked and the $key generated above is the same as that listed in the apache solr query object.

Can anyone tell what I am dong wrong here in my attempt to filter on this dynamic field?

#3

pwolanin - November 17, 2009 - 00:16

did you reindex all content?

#4

SomebodySysop - November 17, 2009 - 00:28
Status:active» fixed

OK, I have discovered two thing:

a. The node access realm og_public is NOT indexed in apachesolr. That's why the filter returned no nodes. I tried re-indexing several times, but to no avail. I do not know if this is the result of my specific configuration or is a problem with the indexer. I'll open a new issue for this if I can't resolve it.

b. I could achieve more or less the same thing by using hook_apachesolr_update_index() to add a field, then hook_apachesolr_modify_query() to filter on it:

<?php
/**
* Implementation of apachesolr_update_index
*/
function mymodule_apachesolr_update_index(&$document, $node) {
  static
$account;

 
// Give the node a value.
 
$key = 'nodeaccess_mymodule_public';
  if (
$node->og_public == 1) {
   
$document->setMultiValue($key, 1);
  } else {
   
$document->setMultiValue($key, 0);
  }

}

/**
* Implementation of hook_apachesolr_modify_query().
*/
function mymodule_apachesolr_modify_query(&$query, &$params) {
  global
$user;

 
// If the user is not logged in, then only list "public" group nodes
 
if ($user->uid == 0) {
   
$key = 'nodeaccess_mymodule_public';
   
$query->add_filter($key, 1);        
  }
}
?>

So, my larger issue of how to use hook_apachesolr_modify_query() is solved. However, the more specific case is that of limiting access to annotations.

I think I need to close this issue and create another because it's not that I don't want the nodes to be seen in the search (if they contain the search keywords), it's that I don't want the annotations searched and/or displayed if the user doesn't have access to them.

Thanks for the assistance.

#5

Scott Reynolds - November 17, 2009 - 00:37

The node access realm og_public is NOT indexed in apachesolr.

So this is true because apachesolr_nodeaccess does a check like this.

<?php
if (!isset($account)) {
   
// Load the anonymous user.
   
$account = drupal_anonymous_user();
  }

  if (!
node_access('view', $node, $account)) {
    
// Get the realms here.
 
}
  else {
    
// Add the generic view grant if we are not using
    // node access or the node is viewable by anonymous users.
 
}
?>

Because its viewable by all users it gets the generic nodeaccess_all => 0.

#6

pwolanin - November 17, 2009 - 02:05

Right - that's an optimization to avoid needing complex queries for nodes that will end up being shown to the anonymous users.

#7

SomebodySysop - November 17, 2009 - 07:54

Thanks for the clarification.

#8

System Message - December 1, 2009 - 08:00
Status:fixed» closed

Automatically closed -- issue fixed for 2 weeks with no activity.

 
 

Drupal is a registered trademark of Dries Buytaert.