/[drupal]/contributions/modules/forum_access/forum_access.module
ViewVC logotype

Contents of /contributions/modules/forum_access/forum_access.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.50 - (show annotations) (download) (as text)
Sun Oct 4 22:43:46 2009 UTC (7 weeks, 4 days ago) by salvis
Branch: MAIN
Changes since 1.49: +13 -6 lines
File MIME type: text/x-php
Distinguish between grants as moderator or as normal user.
1 <?php
2 // $Id: forum_access.module,v 1.49 2009/09/20 01:09:20 salvis Exp $
3
4 /**
5 * @file forum_access.module
6 *
7 * This module uses form_alter to add permissions and moderator settings to
8 * forums.
9 *
10 */
11
12 /**
13 * Implementation of hook_node_grants().
14 *
15 * This function supplies the forum access grants. forum_access simply uses
16 * roles as ACLs, so rids translate directly to gids.
17 */
18 function forum_access_node_grants($user, $op) {
19 $grants['forum_access'] = array_keys($user->roles);
20 return $grants;
21 }
22
23 /**
24 * Implementation of hook_node_access_records().
25 *
26 * Returns a list of grant records for the passed in node object.
27 * Checks to see if maybe we're being disabled.
28 */
29 function forum_access_node_access_records($node) {
30 if (!forum_access_enabled()) {
31 return;
32 }
33
34 static $grants = array();
35 if ($tid = _forum_access_get_tid($node)) {
36 if (!isset($grants[$tid])) {
37 $result = db_query('SELECT * FROM {forum_access} WHERE tid = %d', $tid);
38 while ($grant = db_fetch_object($result)) {
39 $grants[$tid][] = array(
40 'realm' => 'forum_access',
41 'gid' => $grant->rid,
42 'grant_view' => $grant->grant_view,
43 'grant_update' => $grant->grant_update,
44 'grant_delete' => $grant->grant_delete,
45 'priority' => $grant->priority,
46 );
47 }
48 //drupal_set_message("forum_access_node_access_records($node->nid) (tid=$tid) returns ". var_export($grants[$tid], TRUE), 'status');
49 }
50 if (isset($grants[$tid])) {
51 return $grants[$tid];
52 }
53 }
54 }
55
56 /**
57 * Implementation of hook_init().
58 *
59 * Deny access to forum if the user does not have access to it.
60 * Enable moderator access on node/%, node/%/edit, comment/edit/%,
61 * and comment/delete/% where needed.
62 */
63 function forum_access_init() {
64 global $user;
65 if ($user->uid == 1) {
66 return;
67 }
68
69 switch (arg(0)) {
70 case 'forum':
71 if (is_numeric($tid = arg(1))) {
72 if (!forum_access_access($tid, 'view')) {
73 drupal_access_denied();
74 module_invoke_all('exit');
75 exit;
76 }
77 }
78 break;
79
80 case 'comment':
81 if (variable_get('forum_access_D5_legacy_mode', FALSE)) {
82 return; // disable comment access control
83 }
84 if ((arg(1) == 'edit' || arg(1) == 'delete') && !user_access('administer comments')) {
85 if (is_numeric($cid = arg(2))) { // comment/edit/%, comment/delete/%
86 $access[] = (arg(1) == 'edit' ? 'update' : 'delete');
87 $comment = _comment_load($cid);
88 $nid = $comment->nid;
89 // If the node turns out to be in a forum where we have update/delete
90 // access, then we need Moderator permissions now, so we can moderate
91 // this comment.
92 // We won't provide full Administrator access, though: we'll remove
93 // author and timestamp, for example.
94 }
95 }
96 break;
97
98 case 'node':
99 if (is_numeric(arg(1))) {
100 $access[] = 'update';
101 if (arg(2) == 'edit' && !user_access('administer nodes')) { // node/%/edit
102 $nid = arg(1);
103 // If the node turns out to be in a forum where we have update/delete
104 // access, then we already get limited edit capabilities from NA, but
105 // we need some more, e.g. publish/unpublish and comment status.
106 // In order to get these controls on the form, we need Moderator
107 // permissions now.
108 // We won't provide full Administrator access, though: we'll remove
109 // author and timestamp, for example.
110 }
111 if (arg(2) == NULL && !user_access('administer comments')) { // node/%
112 $nid = arg(1);
113 // If the node turns out to be in a forum where we have update/delete
114 // access, then we'll get the 'Edit' link automatically from NA, but
115 // we'll need Moderator permissions, so that we can add the edit/delete
116 // comment links (*after* we've identified the other comment links).
117 }
118 }
119 break;
120 }
121 if (isset($nid)) {
122 $node = node_load($nid);
123 if ($tid = _forum_access_get_tid($node)) {
124 foreach ($access as $a) {
125 if ($level = forum_access_access($tid, $a)) {
126 module_load_include('node.inc', 'forum_access');
127 $user->_forum_access_moderator = $level;
128 if (arg(0) == 'comment' || arg(0) == 'node' && arg(2) == 'edit') {
129 _forum_access_enable_moderator();
130 }
131 }
132 }
133 }
134 }
135 }
136
137 /**
138 * Implementation of hook_form_alter().
139 *
140 * Alter the node/comment create/edit forms and various admin forms.
141 */
142 function forum_access_form_alter(&$form, &$form_state, $form_id) {
143 if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
144 module_load_include('node.inc', 'forum_access');
145 _forum_access_node_form($form, $form_state);
146 }
147 else if ($form_id == 'comment_form' && !variable_get('forum_access_D5_legacy_mode', FALSE)) {
148 module_load_include('node.inc', 'forum_access');
149 _forum_access_comment_form($form, $form_state);
150 }
151 else if ($form_id == 'forum_overview') {
152 module_load_include('admin.inc', 'forum_access');
153 _forum_access_forum_overview($form, $form_state);
154 }
155 else if ($form_id == 'forum_form_container') {
156 module_load_include('admin.inc', 'forum_access');
157 _forum_access_forum_form($form, $form_state, TRUE);
158 }
159 else if ($form_id == 'forum_form_forum') {
160 module_load_include('admin.inc', 'forum_access');
161 _forum_access_forum_form($form, $form_state, FALSE);
162 }
163 else if ($form_id == 'forum_admin_settings') {
164 module_load_include('admin.inc', 'forum_access');
165 _forum_access_forum_admin_settings_form($form, $form_state);
166 }
167 else if ($form_id == 'user_admin_role') {
168 module_load_include('admin.inc', 'forum_access');
169 _forum_access_user_admin_role_form($form, $form_state);
170 }
171 else if ($form_id == 'content_access_admin_settings' && empty($_POST)) {
172 module_load_include('admin.inc', 'forum_access');
173 _forum_access_content_access_admin_form();
174 }
175 }
176
177 /**
178 * Implementation of hook_db_rewrite_sql().
179 *
180 * Because in order to restrict the visible forums, we have to rewrite
181 * the sql. This is because there isn't a node_access equivalent for
182 * taxonomy. There should be.
183 */
184 function forum_access_db_rewrite_sql($query, $primary_table, $primary_field, $args) {
185 global $user;
186 if ($primary_field == 'tid' && $user->uid != 1 && !(strstr($_GET['q'], 'admin/content/forum') !== FALSE && user_access('administer forums'))) {
187 $roles = _forum_access_get_roles($user);
188 $sql['join'] = "LEFT JOIN {forum_access} fa ON $primary_table.tid = fa.tid
189 LEFT JOIN {acl} acl_fa ON acl_fa.name = ". ($GLOBALS['db_type'] == 'pgsql' ? 'CAST(' : '')
190 ."$primary_table.tid". ($GLOBALS['db_type'] == 'pgsql' ? ' AS VARCHAR)' : '')
191 ." AND acl_fa.module = 'forum_access'
192 LEFT JOIN {acl_user} aclu_fa ON aclu_fa.acl_id = acl_fa.acl_id AND aclu_fa.uid = $user->uid";
193 $sql['where'] = "(fa.grant_view >= 1 AND fa.rid IN ($roles)) OR fa.tid IS NULL OR aclu_fa.uid = $user->uid";
194 $sql['distinct'] = 1;
195 return $sql;
196 }
197 }
198
199 /**
200 * Implementation of hook_nodeapi().
201 *
202 * Add ACL data to fresh forum posts.
203 */
204 function forum_access_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
205 static $old_tid = NULL;
206 // This is modeled after forum_nodeapi():
207 $vid = variable_get('forum_nav_vocabulary', '');
208 $vocabulary = taxonomy_vocabulary_load($vid);
209 if (empty($vocabulary) || !in_array($node->type, $vocabulary->nodes)) {
210 return;
211 }
212
213 switch ($op) {
214 case 'presave':
215 $old_tid = db_result(db_query('SELECT tid FROM {forum} WHERE nid = %d', $node->nid));
216 break;
217
218 case 'update':
219 if (!empty($old_tid)) {
220 if (!empty($node->tid) && $node->tid == $old_tid) {
221 return;
222 }
223 $acl_id = db_result(db_query("SELECT acl_id from {acl} WHERE module = 'forum_access' AND name = '%d'", $old_tid));
224 acl_node_remove_acl($node->nid, $acl_id);
225 }
226 // Deliberate no break -- for changed and for previously unassigned terms we need an insert.
227
228 case 'insert':
229 if (!empty($node->tid)) {
230 $acl_id = db_result(db_query("SELECT acl_id from {acl} WHERE module = 'forum_access' AND name = '%d'", $node->tid));
231 acl_node_add_acl($node->nid, $acl_id, 1, 1, 1);
232 }
233 $old_tid = NULL;
234 break;
235 }
236 }
237
238 /**
239 * Get an array of moderator UIDs or NULL.
240 */
241 function forum_access_get_moderator_uids($tid) {
242 if ($acl_id = acl_get_id_by_name('forum_access', $tid)) {
243 if ($uids = acl_get_uids($acl_id)) {
244 return $uids;
245 }
246 }
247 }
248
249 /**
250 * Implementation of $modulename_preprocess_$hook() for forum_list.
251 *
252 * Add forum_access_moderators to each forum,
253 * containing a list of user objects.
254 *
255 * Note: On a site with many moderators, this function is expensive,
256 * and thus it is disabled by default. Set the variable to TRUE to enable.
257 */
258 function forum_access_preprocess_forum_list(&$variables) {
259 if (variable_get('forum_access_provide_moderators_template_variable', FALSE)) {
260 static $users;
261 foreach ($variables['forums'] as $tid => $forum)
262 {
263 $moderators = array();
264 if ($uids = forum_access_get_moderator_uids($tid)) {
265 foreach ($uids as $uid) {
266 if (!isset($users[$uid])) {
267 $users[$uid] = user_load(array('uid' => $uid));
268 }
269 $moderators[$uid] = $users[$uid];
270 }
271 }
272 $forum->forum_access_moderators = (empty($moderators) ? NULL : $moderators);
273 }
274 }
275 }
276
277 /**
278 * Implementation of $modulename_preprocess_$hook() for forums.
279 *
280 * Remove 'post' links from forum page, if the user does not have the
281 * 'create' permission.
282 */
283 function forum_access_preprocess_forums(&$variables) {
284 if (!forum_access_access($variables['tid'], 'create') && !empty($variables['links'])) {
285 foreach ($variables['links'] as $key => $link) {
286 if (substr($link['href'], 0, 9) == 'node/add/') {
287 unset($variables['links'][$key]);
288 }
289 }
290 }
291 }
292
293 if (!variable_get('forum_access_D5_legacy_mode', FALSE))
294 { // LEGACY-MODE disables these methods
295
296 /**
297 * Implementation of hook_link_alter().
298 *
299 * Remove the 'Add new comment' link from nodes, if the user does not have the
300 * 'create' permission.
301 */
302 function forum_access_link_alter(&$links, $node)
303 {
304 global $user;
305 if ($user->uid != 1 && ($tid = _forum_access_get_tid($node)) && isset($links['comment_add']) && !forum_access_access($tid, 'create')) {
306 unset($links['comment_add']);
307 }
308 }
309
310 /**
311 * Implementation of $modulename_preprocess_$hook() for box.
312 *
313 * Remove the in-line 'Post new comment' box, if it's empty
314 * (after _forum_access_comment_form()).
315 */
316 function forum_access_preprocess_box(&$variables) {
317 $tr = 't';
318 if (empty($variables['content']) && ($variables['title'] == $tr('Post new comment') || $variables['title'] == $tr('Reply'))) {
319 $variables['title'] = '';
320 }
321 }
322
323 /**
324 * Implementation of $modulename_preprocess_$hook() for comment.
325 *
326 * Recreate comment links (they've already been themed), and
327 * remove those that aren't accessible to the user.
328 */
329 function forum_access_preprocess_comment(&$variables) {
330 if (isset($variables['node']->tid)) {
331 module_load_include('node.inc', 'forum_access');
332 _forum_access_preprocess_comment($variables);
333 }
334 }
335
336 } // End of !LEGACY-MODE
337
338 /**
339 * This is also required by ACL module.
340 */
341 function forum_access_enabled($set = NULL) {
342 static $enabled = true;
343 if ($set !== NULL) {
344 $enabled = $set;
345 }
346 return $enabled;
347 }
348
349 /**
350 * Implementation of hook_enable().
351 */
352 function forum_access_enable() {
353 node_access_needs_rebuild();
354 }
355
356 /**
357 * Implementation of hook_disable().
358 */
359 function forum_access_disable() {
360 forum_access_enabled(FALSE);
361 node_access_needs_rebuild();
362 }
363
364 /**
365 * See if a given user has access to a forum.
366 *
367 * $tid -- the tid of the forum
368 * $type -- view, update, delete or create
369 * $account -- the account to test for. If NULL use current user.
370 *
371 * Return:
372 * FALSE - access not granted
373 * 1 - access granted
374 * 2 - access granted for forum moderator
375 * 3 - user has 'administer nodes' (this occurs also when in
376 * forum moderator mode!)
377 */
378 function forum_access_access($tid, $type, $account = NULL) {
379 static $cache = array();
380 if (!$account) {
381 global $user;
382 $account = $user;
383 }
384
385 if ($account->uid == 1 ||
386 user_access('administer nodes') && array_search($type, array('view', 'update', 'delete')) !== FALSE) {
387 return 3;
388 }
389
390 if (!isset($cache[$account->uid][$tid][$type])) {
391 $roles = _forum_access_get_roles($account);
392 $result = db_result(db_query("SELECT tid FROM {forum_access} WHERE rid IN (%s) AND grant_%s = 1 AND tid = %d", $roles, $type, $tid));
393
394 if ($result) {
395 $cache[$account->uid][$tid][$type] = 1;
396 }
397 else {
398 // check our moderators too
399 $acl_id = db_result(db_query("SELECT acl_id from {acl} WHERE module = 'forum_access' AND name = '%d'", $tid));
400 $result = db_result(db_query("SELECT uid FROM {acl_user} WHERE acl_id = %d AND uid = %d", $acl_id, $account->uid));
401 if ($result) {
402 $cache[$account->uid][$tid][$type] = 2;
403 }
404 else {
405 $cache[$account->uid][$tid][$type] = FALSE;
406 }
407 }
408 }
409 return $cache[$account->uid][$tid][$type];
410 }
411
412 /**
413 * Implementation of hook_user().
414 */
415 function forum_access_user($op, &$edit, &$account, $category = NULL) {
416 switch ($op) {
417 case 'validate':
418 $rid = variable_get('forum_access_moderator_rid', NULL);
419 if (!empty($rid)) {
420 if (isset($edit['roles'][$rid]) && $edit['roles'][$rid]) {
421 $roles = user_roles();
422 $variables = array(
423 '!Forum_Access' => 'Forum Access',
424 '%Role' => $roles[$rid],
425 );
426 drupal_set_message(t('The %Role role is reserved for !Forum_Access! It has been removed.', $variables), 'warning');
427 unset($edit['roles'][$rid]);
428 }
429 }
430 break;
431 }
432 }
433
434 /**
435 * Get the roles of a user.
436 */
437 function _forum_access_get_roles($user) {
438 return implode(', ', array_keys($user->roles));
439 }
440
441 /**
442 * Return the forum tid or FALSE.
443 */
444 function _forum_access_get_tid($node) {
445 return (isset($node->forum_tid) ? $node->forum_tid : (isset($node->tid) ? $node->tid : FALSE));
446 }
447
448 /**
449 * Implementation of hook_node_access_explain().
450 */
451 function forum_access_node_access_explain($row) {
452 static $roles = NULL;
453 if ($row->realm == 'forum_access') {
454 if (!isset($roles)) {
455 module_load_include('node.inc', 'forum_access');
456 $roles = _forum_access_get_all_roles();
457 }
458 if (isset($roles[$row->gid])) {
459 return array($roles[$row->gid]);
460 }
461 return array('(unknown gid)');
462 }
463 }

  ViewVC Help
Powered by ViewVC 1.1.2