comparison sites/all/modules/custom/solrconnect/apachesolr_access/apachesolr_access.module @ 0:015d06b10d37 default tip

initial
author dwinter
date Wed, 31 Jul 2013 13:49:13 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:015d06b10d37
1 <?php
2
3 /**
4 * Implements hook_apachesolr_index_document_build_node()
5 *
6 * Add node access grants of generic view grants if node access is not used.
7 *
8 * @param $document
9 * The document to add our node access information to
10 * @param $node
11 * The node which is used to built the document from
12 * @param $env_id
13 * The environment for which we are building the document. This parameter does not have any effect in
14 * this code so it can be ignored
15 */
16 function apachesolr_access_apachesolr_index_document_build_node(ApacheSolrDocument $document, $node, $env_id) {
17 $account = &drupal_static(__FUNCTION__);
18
19 if (!isset($account)) {
20 // Load the anonymous user.
21 $account = drupal_anonymous_user();
22 }
23
24 // When using a node access module like Domain Access which has
25 // access grants that vary for anonymous users for the same content,
26 // this variable should be set to 1. Note that doing so will prevent
27 // any results from being returned if using apachesolr_multisitesearch
28 // from a different site.
29 $always_add = apachesolr_environment_variable_get($env_id, 'apachesolr_access_always_add_grants', 0);
30 if ($always_add || !node_access('view', $node, $account)) {
31 // Get node access grants.
32 $result = db_query('SELECT * FROM {node_access} WHERE (nid = 0 OR nid = :nid) AND grant_view = 1', array(':nid' => $node->nid));
33 foreach ($result as $grant) {
34 $grant_realm = apachesolr_access_clean_realm_name($grant->realm);
35 $key = 'access_node_' . apachesolr_site_hash() . '_' . $grant_realm;
36 $document->addField($key, $grant->gid);
37 }
38 }
39 else {
40 // Add the generic view grant if we are not using
41 // node access or the node is viewable by anonymous users.
42 // We assume we'll never have an entity with the name '__all'.
43 $document->addField('access__all', 0);
44 }
45 }
46
47 /**
48 * Creates a Solr query for a given user
49 *
50 * @param $account
51 * an account to get grants for and build a solr query
52 *
53 * @throws Exception
54 *
55 * @return SolrFilterSubQuery
56 * Instance of SolrFilterSubQuery
57 */
58 function apachesolr_access_build_subquery($account) {
59 if (!user_access('access content', $account)) {
60 throw new Exception('No access');
61 }
62 $node_access_query = apachesolr_drupal_subquery();
63 if (user_access('bypass node access', $account)) {
64 // Access all content from the current site.
65 $node_access_query->addFilter('hash', apachesolr_site_hash());
66 }
67 else {
68 // Get node access grants.
69 $grants = node_access_grants('view', $account);
70 foreach ($grants as $realm => $gids) {
71 $realm = apachesolr_access_clean_realm_name($realm);
72 foreach ($gids as $gid) {
73 $node_access_query->addFilter('access_node_' . apachesolr_site_hash() . '_' . $realm, $gid);
74 }
75 }
76 }
77 // Everyone can access public content. Note that if the variable
78 // 'apachesolr_access_always_add_grants' is TRUE, no content from this site
79 // is considered "public". However, this condition may match documents in
80 // the Solr index supplied by other sites when multiple sites are indexing
81 // into the same index , i.e. multisite search.
82 $node_access_query->addFilter('access__all', 0);
83 return $node_access_query;
84 }
85
86 /**
87 * Implements hook_apachesolr_query_alter().
88 *
89 * Alter the query to include the access subquery
90 *
91 * @param DrupalSolrQueryInterface $query
92 *
93 */
94 function apachesolr_access_apachesolr_query_alter(DrupalSolrQueryInterface $query) {
95 global $user;
96 try {
97 $subquery = apachesolr_access_build_subquery($user);
98 $query->addFilterSubQuery($subquery);
99 }
100 catch (Exception $e) {
101 watchdog("apachesolr_access", 'User %name (UID:!uid) cannot search: @message', array('%name' => $user->name, '!uid' => $user->uid, '@message' => $e->getMessage()));
102 $query->abort_search = TRUE;
103 }
104 }
105
106 /**
107 * Implements hook_node_insert().
108 *
109 * hook_node_ACTION() is called before hook_node_access_records() in node_save().
110 *
111 * @param object $node
112 */
113 function apachesolr_access_node_insert($node) {
114 $node->apachesolr_access_node_ignore = 1;
115 }
116
117 /**
118 * Implements hook_node_update().
119 *
120 * hook_node_ACTION() is called before hook_node_access_records() in node_save().
121 *
122 * @param object $node
123 */
124 function apachesolr_access_node_update($node) {
125 $node->apachesolr_access_node_ignore = 1;
126 }
127
128 /**
129 * Implements hook_node_access_records().
130 *
131 * Listen to this hook to find out when a node needs to be re-indexed
132 * for its node access grants.
133 *
134 * @param object $node
135 */
136 function apachesolr_access_node_access_records($node) {
137 // node_access_needs_rebuild() will usually be TRUE during a
138 // full rebuild.
139 if (empty($node->apachesolr_access_node_ignore) && !node_access_needs_rebuild()) {
140 // Only one node is being changed - mark for re-indexing.
141 apachesolr_mark_entity('node', $node->nid);
142 }
143 }
144
145 /**
146 * Implements hook_form_alter().
147 *
148 * @param array $form
149 * @param array $form_state
150 * @param string $form_id
151 *
152 */
153 function apachesolr_access_form_alter(&$form, $form_state, $form_id) {
154 $form['#submit'][] = 'apachesolr_access_rebuild_nodeaccess';
155 }
156
157 /**
158 * Implements hook_form_FORM_ID_alter().
159 */
160 function apachesolr_access_form_apachesolr_environment_edit_form_alter(&$form, $form_state) {
161 $form['conf']['apachesolr_access_always_add_grants'] = array(
162 '#type' => 'checkbox',
163 '#title' => t('Add access grants even for public content'),
164 '#default_value' => empty($form['#environment']['conf']['apachesolr_access_always_add_grants']) ? 0 : 1,
165 '#description' => t('Normally should be disabled. Changing this value requires all content to be re-indexed. Useful for sites using Domamin Access or simliar node acess modules with grants that vary for anonymous users.'),
166 );
167 $form['actions']['save']['#submit'][] = 'apachesolr_access_environment_edit_form_submit';
168 $form['actions']['save_edit']['#submit'][] = 'apachesolr_access_environment_edit_form_submit';
169 }
170
171 /**
172 * Added button-level form submit function for apachesolr_environment_edit_form.
173 */
174 function apachesolr_access_environment_edit_form_submit($form, &$form_state) {
175 $prior = empty($form['#environment']['conf']['apachesolr_access_always_add_grants']) ? 0 : 1;
176 if ($form_state['values']['conf']['apachesolr_access_always_add_grants'] != $prior) {
177 apachesolr_access_enable();
178 }
179 }
180
181 /**
182 * Force Solr to do a total re-index when node access rules change.
183 *
184 * This is unfortunate because not every node is going to be affected, but
185 * there is little we can do.
186 *
187 * @param $form
188 * @param $form_state
189 *
190 */
191 function apachesolr_access_rebuild_nodeaccess($form, $form_state) {
192 drupal_set_message(t('Solr search index will be rebuilt.'));
193 // Clear last updated
194 apachesolr_clear_last_index_position();
195 }
196
197 /**
198 * Implements hook_enable().
199 *
200 * On enabling the module, tell the user to reindex
201 */
202 function apachesolr_access_enable() {
203 drupal_set_message(t('Your content <a href="@url">must be re-indexed</a> before Apache Solr Access will be functional on searches.', array('@url' => url('admin/config/search/apachesolr/index'))), 'warning');
204 }
205
206 /**
207 * Helper function - return a safe (PHP identifier) realm name.
208 *
209 * @todo See if we can replace this with a native php function
210 *
211 * @param string $realm
212 *
213 * @return string
214 * Clean string without bad characters
215 */
216 function apachesolr_access_clean_realm_name($realm) {
217 return preg_replace('/[^a-zA-Z0-9_\x7f-\xff]/', '_', $realm);
218 }