1
|
<?php
|
2
|
|
3
|
/**
|
4
|
* @file
|
5
|
* forum_access.module
|
6
|
*
|
7
|
* This module uses form_alter to add permissions and moderator settings to
|
8
|
* forums.
|
9
|
*
|
10
|
*/
|
11
|
|
12
|
/**
|
13
|
* Implements hook_requirements().
|
14
|
*
|
15
|
* Remind the user to upgrade to Chain Menu Access API 2.x.
|
16
|
*/
|
17
|
function forum_access_requirements($phase) {
|
18
|
$result = array();
|
19
|
switch ( $phase ) {
|
20
|
case 'update':
|
21
|
case 'runtime':
|
22
|
$t = get_t();
|
23
|
$path = drupal_get_filename('module', 'chain_menu_access');
|
24
|
$path = substr($path, 0, strlen($path) - 7) . '.info';
|
25
|
$info = drupal_parse_info_file($path);
|
26
|
$version = (isset($info['version']) ? $info['version'] : $t('Unknown'));
|
27
|
$found = preg_match('/7\.x-([0-9]*)\./', $version, $matches);
|
28
|
if ($found && $matches[1] == 1 || !$found) {
|
29
|
$cma = 'Chain Menu Access API';
|
30
|
$variables = array('@Chain_Menu_Access_API' => $cma, '@module' => url('admin/modules'));
|
31
|
$result[] = array(
|
32
|
'title' => $t('@Chain_Menu_Access_API module', $variables),
|
33
|
'value' => $version,
|
34
|
'description' => $t('Version 1.x is obsolete. Upgrade to version 2.x as soon as <em>all</em> installed client modules support that version.') . '<br />' .
|
35
|
$t('Check the <a href="@module">module administration page</a> to find out which of your modules depend on @Chain_Menu_Access_API.', $variables),
|
36
|
'severity' => REQUIREMENT_WARNING,
|
37
|
);
|
38
|
}
|
39
|
}
|
40
|
return $result;
|
41
|
}
|
42
|
|
43
|
/**
|
44
|
* Implements hook_menu_alter().
|
45
|
*
|
46
|
* Remove the 'Forum' menu item if no forums are visible.
|
47
|
*/
|
48
|
function forum_access_menu_alter(&$items) {
|
49
|
$requirements = forum_access_requirements('runtime');
|
50
|
if (!empty($requirements) && $requirements[0]['value'] != t('Unknown')) {
|
51
|
// Fall back to obsolete Chain Menu Access API version 7.x-1.x,
|
52
|
// because that's what's installed.
|
53
|
chain_menu_access_chain($items['forum'], 'forum_access_view_any_forum', array());
|
54
|
chain_menu_access_chain($items['node/%node'], '_forum_access_node_access_callback', array(1, 'view'));
|
55
|
chain_menu_access_chain($items['comment/%comment/edit'], '_forum_access_comment_edit_callback', array(1));
|
56
|
chain_menu_access_chain($items['comment/%comment/edit'], '_forum_access_comment_access_callback', array(1, 2), TRUE);
|
57
|
chain_menu_access_chain($items['comment/%/delete'], '_forum_access_comment_access_callback', array(1, 2), TRUE);
|
58
|
chain_menu_access_chain($items['comment/%/approve'], '_forum_access_comment_access_callback', array(1, 2), TRUE);
|
59
|
chain_menu_access_chain($items['comment/reply/%node'], '_forum_access_comment_access_callback', array(2, 1));
|
60
|
}
|
61
|
else {
|
62
|
chain_menu_access_chain($items, 'forum', 'forum_access_view_any_forum');
|
63
|
chain_menu_access_chain($items, 'node/%node', '_forum_access_node_access_callback', array(1, 'view'));
|
64
|
chain_menu_access_chain($items, 'comment/%comment/edit', '_forum_access_comment_edit_callback', array(1));
|
65
|
chain_menu_access_chain($items, 'comment/%comment/edit', '_forum_access_comment_access_callback', array(1, 2), TRUE);
|
66
|
chain_menu_access_chain($items, 'comment/%/delete', '_forum_access_comment_access_callback', array(1, 2), TRUE);
|
67
|
chain_menu_access_chain($items, 'comment/%/approve', '_forum_access_comment_access_callback', array(1, 2), TRUE);
|
68
|
chain_menu_access_chain($items, 'comment/reply/%node', '_forum_access_comment_access_callback', array(2, 1));
|
69
|
}
|
70
|
}
|
71
|
|
72
|
function _forum_access_node_access_callback($node, $op) {
|
73
|
global $user;
|
74
|
|
75
|
if ($op == 'view' && ($tid = _forum_access_get_tid($node))) {
|
76
|
if (forum_access_access('update', $tid) || forum_access_access('delete', $tid)) {
|
77
|
// Add the 'administer comments' permission to the user so that he can
|
78
|
// see unpublished comments.
|
79
|
forum_access_enable_moderator();
|
80
|
}
|
81
|
// The 'view' access check will be done by core.
|
82
|
}
|
83
|
return TRUE;
|
84
|
}
|
85
|
|
86
|
function _forum_access_comment_edit_callback($comment) {
|
87
|
global $user;
|
88
|
|
89
|
// This callback is governed by AND, return TRUE by default.
|
90
|
$node = node_load($comment->nid);
|
91
|
if ($tid = _forum_access_get_tid($node)) {
|
92
|
if (!forum_access_is_moderator($user, $tid) && !forum_access_access('update', $tid, $user) && !user_access('administer comments') && !($user->uid == $comment->uid && user_access('edit own forum content'))) {
|
93
|
return FALSE;
|
94
|
}
|
95
|
}
|
96
|
return TRUE;
|
97
|
}
|
98
|
|
99
|
function _forum_access_comment_access_callback($comment, $op) {
|
100
|
global $user;
|
101
|
|
102
|
if ($op == 'reply') {
|
103
|
// 'reply' is governed by AND, return TRUE by default.
|
104
|
$node = $comment;
|
105
|
if ($tid = _forum_access_get_tid($node)) {
|
106
|
return forum_access_access('create', $tid);
|
107
|
}
|
108
|
return TRUE;
|
109
|
}
|
110
|
|
111
|
if (is_numeric($comment)) {
|
112
|
$comment = comment_load($comment);
|
113
|
}
|
114
|
$node = node_load($comment->nid);
|
115
|
|
116
|
// The remaining $ops are governed by OR, return FALSE by default.
|
117
|
if ($tid = _forum_access_get_tid($node)) {
|
118
|
if ($op == 'approve') {
|
119
|
return $user->uid == 1 || forum_access_is_moderator($user, $tid);
|
120
|
}
|
121
|
if (!user_access('administer comments')) {
|
122
|
if ($op == 'edit' && (forum_access_access('update', $tid) || user_access('edit any forum content') || ($user->uid == $comment->uid && user_access('edit own forum content')))) {
|
123
|
forum_access_enable_moderator();
|
124
|
return TRUE;
|
125
|
}
|
126
|
if ($op == 'delete' && (forum_access_access('delete', $tid) || user_access('delete any forum content') || ($user->uid == $comment->uid && user_access('delete own forum content')))) {
|
127
|
return TRUE;
|
128
|
}
|
129
|
}
|
130
|
}
|
131
|
return FALSE;
|
132
|
}
|
133
|
|
134
|
/**
|
135
|
* Access callback for the 'forum' menu item.
|
136
|
*
|
137
|
* Returns 1 if the user has at least one role that can access
|
138
|
* at least one forum, 2 if the user is moderator in at least one forum,
|
139
|
* FALSE otherwise.
|
140
|
*/
|
141
|
function forum_access_view_any_forum($account = NULL) {
|
142
|
global $user;
|
143
|
$returns = &drupal_static(__FUNCTION__, array());
|
144
|
|
145
|
if (!isset($account)) {
|
146
|
$account = $user;
|
147
|
}
|
148
|
|
149
|
if (!isset($returns[$account->uid])) {
|
150
|
if (user_access('bypass node access', $account)) {
|
151
|
return $returns[$account->uid] = 1;
|
152
|
}
|
153
|
if (!user_access('access content')) {
|
154
|
return $returns[$account->uid] = FALSE;
|
155
|
}
|
156
|
$rids = variable_get('forum_access_rids', NULL);
|
157
|
if (!isset($rids)) {
|
158
|
$rids = db_query("SELECT fa.rid FROM {forum_access} fa WHERE fa.grant_view > 0 GROUP BY fa.rid")->fetchCol();
|
159
|
variable_set('forum_access_rids', $rids);
|
160
|
}
|
161
|
foreach ($rids as $rid) {
|
162
|
if (isset($account->roles[$rid])) {
|
163
|
return $returns[$account->uid] = 1;
|
164
|
}
|
165
|
}
|
166
|
// Check moderator, too.
|
167
|
$query = db_select('acl', 'acl');
|
168
|
$query->join('acl_user', 'aclu', "acl.acl_id = aclu.acl_id");
|
169
|
$count = $query
|
170
|
->fields('acl', array('number'))
|
171
|
->condition('acl.module', 'forum_access')
|
172
|
->condition('aclu.uid', $account->uid)
|
173
|
->countQuery()
|
174
|
->execute()
|
175
|
->fetchField();
|
176
|
$returns[$account->uid] = ($count > 0 ? 2 : FALSE);
|
177
|
}
|
178
|
return $returns[$account->uid];
|
179
|
}
|
180
|
|
181
|
/**
|
182
|
* Implements hook_node_grants().
|
183
|
*
|
184
|
* This function supplies the forum access grants. forum_access simply uses
|
185
|
* roles as ACLs, so rids translate directly to gids.
|
186
|
*/
|
187
|
function forum_access_node_grants($user, $op) {
|
188
|
$grants['forum_access'] = array_keys($user->roles);
|
189
|
return $grants;
|
190
|
}
|
191
|
|
192
|
/**
|
193
|
* Implements hook_node_access_records().
|
194
|
*
|
195
|
* Returns a list of grant records for the passed in node object.
|
196
|
* Checks to see if maybe we're being disabled.
|
197
|
*/
|
198
|
function forum_access_node_access_records($node) {
|
199
|
if (!forum_access_enabled()) {
|
200
|
return;
|
201
|
}
|
202
|
|
203
|
static $seers;
|
204
|
|
205
|
$grants = &drupal_static(__FUNCTION__, array());
|
206
|
$seers = &drupal_static(__FUNCTION__ . '__seers');
|
207
|
$tid = _forum_access_get_tid($node);
|
208
|
|
209
|
// Set proper grants for nodecomment comment nodes.
|
210
|
//if (isset($node->comment_target_nid)) {
|
211
|
// if ($changed_tid = _forum_access_changed_tid()) {
|
212
|
// $tid = $changed_tid; // the topic node hasn't been saved yet!
|
213
|
// }
|
214
|
// else {
|
215
|
// $node = node_load($node->comment_target_nid);
|
216
|
// $tid = _forum_access_get_tid($node);
|
217
|
// }
|
218
|
//}
|
219
|
|
220
|
if ($tid) {
|
221
|
if (!isset($grants[$tid])) {
|
222
|
if (!isset($seers)) {
|
223
|
$seers = user_roles(FALSE, 'bypass node access');
|
224
|
}
|
225
|
$result = db_query('SELECT * FROM {forum_access} WHERE tid = :tid', array(
|
226
|
':tid' => $tid
|
227
|
));
|
228
|
foreach ($result as $grant) {
|
229
|
if (isset($seers[$grant->rid])) {
|
230
|
continue; // Don't provide any useless grants!
|
231
|
}
|
232
|
$grants[$tid][] = array(
|
233
|
'realm' => 'forum_access',
|
234
|
'gid' => $grant->rid,
|
235
|
'grant_view' => $grant->grant_view,
|
236
|
'grant_update' => $grant->grant_update,
|
237
|
'grant_delete' => $grant->grant_delete,
|
238
|
'priority' => $grant->priority,
|
239
|
);
|
240
|
}
|
241
|
//dsm("forum_access_node_access_records($node->nid) (tid=$tid) returns ". var_export($grants[$tid], TRUE), 'status');
|
242
|
}
|
243
|
if (isset($grants[$tid])) {
|
244
|
return $grants[$tid];
|
245
|
}
|
246
|
}
|
247
|
}
|
248
|
|
249
|
/**
|
250
|
* Implements hook_form_alter().
|
251
|
*
|
252
|
* Alter the node/comment create/edit forms and various admin forms.
|
253
|
*/
|
254
|
function forum_access_form_alter(&$form, &$form_state, $form_id) {
|
255
|
//dpm($form, "form_id($form_id)");
|
256
|
if ($form_id == 'forum_node_form' && !empty($form['#node_edit_form'])) {
|
257
|
_forum_access_module_load_include('node.inc');
|
258
|
_forum_access_node_form($form, $form_state);
|
259
|
}
|
260
|
elseif ($form['#id'] == 'comment-form') {
|
261
|
_forum_access_module_load_include('node.inc');
|
262
|
_forum_access_comment_form($form, $form_state);
|
263
|
}
|
264
|
elseif ($form_id == 'forum_overview') {
|
265
|
_forum_access_module_load_include('admin.inc');
|
266
|
_forum_access_forum_overview($form, $form_state);
|
267
|
}
|
268
|
elseif ($form_id == 'forum_form_container') {
|
269
|
_forum_access_module_load_include('admin.inc');
|
270
|
_forum_access_forum_form($form, $form_state, TRUE);
|
271
|
}
|
272
|
elseif ($form_id == 'forum_form_forum') {
|
273
|
_forum_access_module_load_include('admin.inc');
|
274
|
_forum_access_forum_form($form, $form_state, FALSE);
|
275
|
}
|
276
|
elseif ($form_id == 'content_access_admin_settings' && empty($_POST)) {
|
277
|
_forum_access_module_load_include('admin.inc');
|
278
|
_forum_access_content_access_admin_form();
|
279
|
}
|
280
|
}
|
281
|
|
282
|
/**
|
283
|
* Implements hook_comment_load().
|
284
|
*/
|
285
|
function forum_access_comment_load($comments) {
|
286
|
//TODO: Investigate usefulness of this hook.
|
287
|
return;
|
288
|
}
|
289
|
|
290
|
/**
|
291
|
* Implements hook_query_alter().
|
292
|
*/
|
293
|
function forum_access_query_alter($p1, $p2, $p3) {
|
294
|
//TODO: Investigate usefulness of this hook.
|
295
|
return;
|
296
|
}
|
297
|
|
298
|
function forum_access_query_term_access_alter(QueryAlterableInterface $query) {
|
299
|
global $user;
|
300
|
|
301
|
// Read meta-data from query, if provided.
|
302
|
if (!$account = $query->getMetaData('account')) {
|
303
|
$account = $user;
|
304
|
}
|
305
|
if (!$op = $query->getMetaData('op')) {
|
306
|
$op = 'view';
|
307
|
}
|
308
|
|
309
|
// If $account can bypass node access, or there are no node access
|
310
|
// modules, we don't need to alter the query.
|
311
|
if (user_access('bypass node access', $account)) {
|
312
|
return;
|
313
|
}
|
314
|
|
315
|
// Prevent duplicate records.
|
316
|
$query->distinct();
|
317
|
|
318
|
// Find all instances of the {taxonomy_term_data} table being joined --
|
319
|
// could appear more than once in the query, and could be aliased.
|
320
|
// Join each one to the forum_access table.
|
321
|
|
322
|
$tables = $query->getTables();
|
323
|
$rids = array_keys($account->roles);
|
324
|
foreach ($tables as $talias => $tableinfo) {
|
325
|
$table = $tableinfo['table'];
|
326
|
if (!($table instanceof SelectQueryInterface) && $table == 'taxonomy_term_data') {
|
327
|
// The node_access table has the access grants for any given node.
|
328
|
$access_alias = $query->leftJoin('forum_access', 'fa', '%alias.tid = ' . $talias . '.tid');
|
329
|
$acl_alias = $query->leftJoin('acl', 'acl', "%alias.number = $talias.tid AND %alias.module = 'forum_access'");
|
330
|
$aclu_alias = $query->leftJoin('acl_user', 'aclu', "%alias.acl_id = $acl_alias.acl_id AND %alias.uid = $account->uid");
|
331
|
$query->condition(db_or()
|
332
|
->isNull("$access_alias.rid")
|
333
|
->condition(db_and()
|
334
|
->condition("$access_alias.rid", $rids, 'IN')
|
335
|
->condition("$access_alias.grant_$op", 1, '>='))
|
336
|
->condition("$aclu_alias.uid", $account->uid));
|
337
|
}
|
338
|
}
|
339
|
}
|
340
|
|
341
|
/**
|
342
|
* Implements hook_node_presave().
|
343
|
*/
|
344
|
function forum_access_node_presave($node, $return_old_tid = FALSE) {
|
345
|
$old_tid = &drupal_static('forum_access_node_presave');
|
346
|
if (_forum_node_check_node_type($node)) {
|
347
|
$old_tid = db_query('SELECT tid FROM {forum} WHERE nid = :nid', array(
|
348
|
':nid' => $node->nid,
|
349
|
))->fetchField();
|
350
|
}
|
351
|
}
|
352
|
|
353
|
/**
|
354
|
* Implements hook_node_update().
|
355
|
*/
|
356
|
function forum_access_node_update($node) {
|
357
|
$old_tid = &drupal_static('forum_access_node_presave');
|
358
|
if (_forum_node_check_node_type($node)) {
|
359
|
$tid = _forum_access_get_tid($node);
|
360
|
if (isset($old_tid)) {
|
361
|
if ($tid == $old_tid) {
|
362
|
return;
|
363
|
}
|
364
|
acl_node_clear_acls($node->nid, 'forum_access');
|
365
|
|
366
|
/*
|
367
|
if (module_exists('nodecomment')) {
|
368
|
_forum_access_changed_tid($tid);
|
369
|
$result = db_query('SELECT cid FROM {node_comments} WHERE nid = :nid', array(
|
370
|
':nid' => $node->nid,
|
371
|
));
|
372
|
foreach ($result as $row) {
|
373
|
acl_node_clear_acls($row->cid, 'forum_access');
|
374
|
}
|
375
|
}
|
376
|
*/
|
377
|
}
|
378
|
// For changed and for previously unassigned terms we need to fake an insert.
|
379
|
forum_access_node_insert($node);
|
380
|
}
|
381
|
}
|
382
|
|
383
|
/**
|
384
|
* Implements hook_node_insert().
|
385
|
*/
|
386
|
function forum_access_node_insert($node) {
|
387
|
$old_tid = &drupal_static('forum_access_node_presave');
|
388
|
if (_forum_node_check_node_type($node)) {
|
389
|
if ($tid = _forum_access_get_tid($node)) {
|
390
|
$acl_id = _forum_access_get_acl($tid);
|
391
|
acl_node_add_acl($node->nid, $acl_id, 1, 1, 1);
|
392
|
|
393
|
/*
|
394
|
if (isset($old_tid) && module_exists('nodecomment')) {
|
395
|
$result = db_query('SELECT cid FROM {node_comments} WHERE nid = :nid', array(
|
396
|
':nid' => $node->nid,
|
397
|
));
|
398
|
foreach ($result as $row) {
|
399
|
acl_node_add_acl($row->cid, $acl_id, 1, 1, 1);
|
400
|
node_access_acquire_grants(node_load($row->cid)); //TODO use node_load_multiple() here
|
401
|
}
|
402
|
}
|
403
|
*/
|
404
|
}
|
405
|
$old_tid = NULL;
|
406
|
}
|
407
|
/*
|
408
|
elseif (isset($node->comment_target_nid)) {
|
409
|
// Set moderator on nodecomment.
|
410
|
$topic_node = node_load($node->comment_target_nid);
|
411
|
if (_forum_node_check_node_type($topic_node) && $topic_tid = _forum_access_get_tid($topic_node)) {
|
412
|
$acl_id = _forum_access_get_acl($topic_tid);
|
413
|
acl_node_add_acl($node->nid, $acl_id, 1, 1, 1);
|
414
|
}
|
415
|
}
|
416
|
*/
|
417
|
}
|
418
|
|
419
|
function forum_access_enable_moderator($enable = TRUE) {
|
420
|
global $user;
|
421
|
|
422
|
if (!$enable || $enable && !user_access('administer comments')) {
|
423
|
$perm = &drupal_static('user_access');
|
424
|
if ($enable) {
|
425
|
$perm[$user->uid]['administer comments'] = $enable;
|
426
|
$user->_forum_access_moderator = $enable;
|
427
|
}
|
428
|
else {
|
429
|
unset($perm[$user->uid]['administer comments']);
|
430
|
unset($user->_forum_access_moderator);
|
431
|
}
|
432
|
}
|
433
|
}
|
434
|
|
435
|
/**
|
436
|
* Get an array of moderator UIDs or NULL.
|
437
|
*/
|
438
|
function forum_access_get_moderator_uids($tid) {
|
439
|
$acl_id = _forum_access_get_acl($tid);
|
440
|
if ($uids = acl_get_uids($acl_id)) {
|
441
|
return $uids;
|
442
|
}
|
443
|
}
|
444
|
|
445
|
/**
|
446
|
* Implements hook_custom_theme().
|
447
|
*/
|
448
|
function forum_access_custom_theme() {
|
449
|
}
|
450
|
|
451
|
/**
|
452
|
* Implements hook_menu_get_item_alter().
|
453
|
*
|
454
|
* Saves the tid on the forum-specific pages.
|
455
|
*/
|
456
|
function forum_access_menu_get_item_alter(&$router_item, $path, $original_map) {
|
457
|
switch ($original_map[0]) {
|
458
|
|
459
|
case 'forum':
|
460
|
if (empty($original_map[1])) {
|
461
|
forum_access_current_tid(0);
|
462
|
}
|
463
|
elseif (is_numeric($original_map[1])) {
|
464
|
forum_access_current_tid($original_map[1]);
|
465
|
}
|
466
|
break;
|
467
|
|
468
|
case 'node':
|
469
|
if (isset($original_map[1]) && is_numeric($nid = $original_map[1]) && ($node = node_load($nid)) && ($tid = _forum_access_get_tid($node))) {
|
470
|
forum_access_current_tid($tid);
|
471
|
}
|
472
|
break;
|
473
|
}
|
474
|
}
|
475
|
|
476
|
/**
|
477
|
* Saves and returns the forum TID, if we're on a forum-specific page.
|
478
|
*/
|
479
|
function forum_access_current_tid($tid = NULL) {
|
480
|
static $saved_tid = 0;
|
481
|
if (isset($tid)) {
|
482
|
$saved_tid = $tid;
|
483
|
}
|
484
|
return $saved_tid;
|
485
|
}
|
486
|
|
487
|
/**
|
488
|
* Implements $modulename_preprocess_$hook() for forum_list.
|
489
|
*
|
490
|
* Add forum_access_moderators to each forum,
|
491
|
* containing a list of user objects.
|
492
|
*
|
493
|
* Note: On a site with many moderators, this function is expensive,
|
494
|
* and thus it is disabled by default. Set the variable to TRUE to enable.
|
495
|
*/
|
496
|
function forum_access_preprocess_forum_list(&$variables) {
|
497
|
if (variable_get('forum_access_provide_moderators_template_variable', FALSE)) {
|
498
|
foreach ($variables['forums'] as $tid => $forum) {
|
499
|
$forum->forum_access_moderators = NULL;
|
500
|
if ($uids = forum_access_get_moderator_uids($tid)) {
|
501
|
$forum->forum_access_moderators = user_load_multiple(uids);
|
502
|
}
|
503
|
}
|
504
|
}
|
505
|
}
|
506
|
|
507
|
/**
|
508
|
* Implements hook_node_view_alter().
|
509
|
*
|
510
|
* Remove 'Add new comment' link if it shouldn't be there.
|
511
|
*/
|
512
|
function forum_access_node_view_alter(&$build) {
|
513
|
if ($tid = _forum_access_get_tid($build['#node'])) {
|
514
|
_forum_access_module_load_include('node.inc');
|
515
|
_forum_access_node_view_alter($build, $tid);
|
516
|
}
|
517
|
}
|
518
|
|
519
|
/**
|
520
|
* Implements hook_comment_view_alter().
|
521
|
*/
|
522
|
function forum_access_comment_view_alter(&$build) {
|
523
|
if ($tid = _forum_access_get_tid($build['#node'])) {
|
524
|
_forum_access_module_load_include('node.inc');
|
525
|
_forum_access_comment_view_alter($build, $tid);
|
526
|
}
|
527
|
}
|
528
|
|
529
|
/**
|
530
|
* Implements $modulename_preprocess_$hook() for comment.
|
531
|
*
|
532
|
* Recreate comment links (they've already been themed), and
|
533
|
* remove those that aren't accessible to the user.
|
534
|
*/
|
535
|
function forum_access_preprocess_comment(&$variables) {
|
536
|
if (isset($variables['node']->tid)) {
|
537
|
_forum_access_module_load_include('node.inc');
|
538
|
_forum_access_preprocess_comment($variables);
|
539
|
}
|
540
|
}
|
541
|
|
542
|
/**
|
543
|
* This is also required by ACL module.
|
544
|
*/
|
545
|
function forum_access_enabled($set = NULL) {
|
546
|
static $enabled = TRUE; // not drupal_static!
|
547
|
if ($set !== NULL) {
|
548
|
$enabled = $set;
|
549
|
}
|
550
|
return $enabled;
|
551
|
}
|
552
|
|
553
|
/**
|
554
|
* Implements hook_node_access().
|
555
|
*/
|
556
|
function forum_access_node_access($node, $op, $account) {
|
557
|
$cache = &drupal_static(__FUNCTION__, array());
|
558
|
|
559
|
$type = is_string($node) ? $node : $node->type;
|
560
|
if ($op == 'create') {
|
561
|
if ($type == 'forum') {
|
562
|
$tid = forum_access_current_tid();
|
563
|
if (isset($cache[$account->uid][$op][$tid])) {
|
564
|
return $cache[$account->uid][$op][$tid];
|
565
|
}
|
566
|
if (!forum_access_access('create', $tid, $account)) {
|
567
|
return $cache[$account->uid][$op][$tid] = NODE_ACCESS_DENY;
|
568
|
}
|
569
|
return $cache[$account->uid][$op][$tid] = NODE_ACCESS_IGNORE;
|
570
|
}
|
571
|
}
|
572
|
else {
|
573
|
$nid = $node->nid;
|
574
|
if (!isset($cache[$account->uid][$op][$nid])) {
|
575
|
if ($tid = _forum_access_get_tid($node)) {
|
576
|
if (!forum_access_access('view', $tid, $account)) {
|
577
|
return $cache[$account->uid][$op][$nid] = NODE_ACCESS_DENY;
|
578
|
}
|
579
|
if ($op == 'update' && (user_access('edit any forum content', $account) || ($node->uid == $account->uid && user_access('edit own forum content', $account)))
|
580
|
|| $op == 'delete' && (user_access('delete any forum content', $account) || ($node->uid == $account->uid && user_access('delete own forum content', $account)))) {
|
581
|
return $cache[$account->uid][$op][$nid] = forum_access_node_access($node, 'view', $account);
|
582
|
}
|
583
|
$access = forum_access_access($op, $tid, $account);
|
584
|
if ($op == 'view' && $access == 1 && !$node->status) {
|
585
|
if (user_access('view own unpublished content', $account) && $account->uid && $account->uid == $node->uid) {
|
586
|
// Allow access to own unpublished node.
|
587
|
}
|
588
|
elseif (forum_access_is_moderator($account, $tid)) {
|
589
|
// Allow access to moderator.
|
590
|
}
|
591
|
else {
|
592
|
$access = FALSE;
|
593
|
}
|
594
|
}
|
595
|
return $cache[$account->uid][$op][$nid] = ($access ? NODE_ACCESS_IGNORE : NODE_ACCESS_DENY);
|
596
|
}
|
597
|
else {
|
598
|
return $cache[$account->uid][$op][$nid] = NODE_ACCESS_IGNORE;
|
599
|
}
|
600
|
}
|
601
|
return $cache[$account->uid][$op][$nid];
|
602
|
}
|
603
|
return NODE_ACCESS_IGNORE;
|
604
|
}
|
605
|
|
606
|
/**
|
607
|
* Implements access checking.
|
608
|
*
|
609
|
* $op -- view, update, delete or create
|
610
|
* $tid -- the tid of the forum
|
611
|
* $account -- the account to test for; if NULL use current user
|
612
|
* $administer_nodes_sees_everything -- pass FALSE to ignore the 'administer nodes' permission
|
613
|
*
|
614
|
* Return:
|
615
|
* FALSE - access not granted
|
616
|
* 1 - access granted
|
617
|
* 2 - access granted for forum moderator
|
618
|
*/
|
619
|
function forum_access_access($op, $tid, $account = NULL, $administer_nodes_sees_everything = TRUE) {
|
620
|
$cache = &drupal_static(__FUNCTION__, array());
|
621
|
if (!$account) {
|
622
|
global $user;
|
623
|
$account = $user;
|
624
|
}
|
625
|
|
626
|
if (user_access('bypass node access', $account)) {
|
627
|
//TODO revise (including comment above)
|
628
|
// $administer_nodes_sees_everything && user_access('administer nodes', $account) && array_search($type, array('view', 'update', 'delete')) !== FALSE) {
|
629
|
return 1;
|
630
|
}
|
631
|
|
632
|
if ($op == 'delete' && user_access('delete any forum content', $account)) {
|
633
|
return 1;
|
634
|
}
|
635
|
|
636
|
if ($op == 'update' && user_access('edit any forum content', $account)) {
|
637
|
return 1;
|
638
|
}
|
639
|
|
640
|
if (!isset($cache[$account->uid][$tid][$op])) {
|
641
|
$query = db_select('forum_access', 'fa')
|
642
|
->fields('fa', array('tid'))
|
643
|
->condition("fa.grant_$op", 1, '>=')
|
644
|
->condition('fa.rid', array_keys($account->roles), 'IN');
|
645
|
if ($tid != 0) {
|
646
|
$query = $query
|
647
|
->condition('fa.tid', $tid, '=');
|
648
|
}
|
649
|
$result = $query
|
650
|
->execute()
|
651
|
->fetchField();
|
652
|
|
653
|
if ($result) {
|
654
|
$cache[$account->uid][$tid][$op] = 1;
|
655
|
}
|
656
|
else {
|
657
|
// check our moderators too
|
658
|
$result = forum_access_is_moderator($account, $tid);
|
659
|
$cache[$account->uid][$tid][$op] = ($result ? 2 : FALSE);
|
660
|
}
|
661
|
}
|
662
|
return $cache[$account->uid][$tid][$op];
|
663
|
}
|
664
|
|
665
|
/**
|
666
|
* Implements hook_taxonomy_term_delete().
|
667
|
*
|
668
|
* Delete {forum_access} records when forums are deleted.
|
669
|
*/
|
670
|
function forum_access_taxonomy_term_delete($term) {
|
671
|
//dpm($array, "hook_taxonomy_term_delete($term->tid)");
|
672
|
if ($term->vid == _forum_access_get_vid()) {
|
673
|
db_delete('forum_access')
|
674
|
->condition('tid', $term->tid)
|
675
|
->execute();
|
676
|
variable_del('forum_access_rids'); // clear cache
|
677
|
}
|
678
|
}
|
679
|
|
680
|
/**
|
681
|
* Implements hook_user_role_delete().
|
682
|
*/
|
683
|
function forum_access_user_role_delete($role) {
|
684
|
db_delete('forum_access')
|
685
|
->condition('rid', $role->rid)
|
686
|
->execute();
|
687
|
db_delete('node_access')
|
688
|
->condition('gid', $role->rid)
|
689
|
->condition('realm', 'forum_access')
|
690
|
->execute();
|
691
|
}
|
692
|
|
693
|
/**
|
694
|
* Check whether the given user is a moderator.
|
695
|
*
|
696
|
* @param $account
|
697
|
* The user or user ID to check.
|
698
|
* @param $tid
|
699
|
* ID of the forum to check or NULL to check whether the user is moderator
|
700
|
* in any forum at all.
|
701
|
*/
|
702
|
function forum_access_is_moderator($account, $tid = NULL) {
|
703
|
$uid = (is_object($account) ? $account->uid : $account);
|
704
|
return (bool) acl_get_ids_by_user('forum_access', $uid, NULL, ($tid ? $tid : NULL));
|
705
|
}
|
706
|
|
707
|
/**
|
708
|
* Return forum.module's forum vocabulary ID.
|
709
|
*/
|
710
|
function _forum_access_get_vid() {
|
711
|
return variable_get('forum_nav_vocabulary', '');
|
712
|
}
|
713
|
|
714
|
/**
|
715
|
* Returns the forum tid or FALSE.
|
716
|
*/
|
717
|
function _forum_access_get_tid($node) {
|
718
|
return (isset($node->forum_tid) ? $node->forum_tid : FALSE);
|
719
|
}
|
720
|
|
721
|
/**
|
722
|
* Saves and returns the $tid.
|
723
|
*/
|
724
|
function _forum_access_changed_tid($tid = NULL) {
|
725
|
$saved_tid = &drupal_static(__FUNCTION__);
|
726
|
if (!empty($tid)) {
|
727
|
$saved_tid = $tid;
|
728
|
}
|
729
|
return $saved_tid;
|
730
|
}
|
731
|
|
732
|
/**
|
733
|
* Returns the ACL ID of the forum.
|
734
|
*/
|
735
|
function _forum_access_get_acl($tid) {
|
736
|
$acl_id = acl_get_id_by_number('forum_access', $tid);
|
737
|
if (!$acl_id) { // create one
|
738
|
$acl_id = acl_create_new_acl('forum_access', NULL, $tid);
|
739
|
$subselect = db_select('taxonomy_index', 'n');
|
740
|
$subselect
|
741
|
->fields('n', array('nid'))
|
742
|
->condition('n.tid', $tid);
|
743
|
acl_add_nodes($subselect, $acl_id, 1, 1, 1);
|
744
|
}
|
745
|
return $acl_id;
|
746
|
}
|
747
|
|
748
|
function _forum_access_module_load_include($type) {
|
749
|
static $loaded = array();
|
750
|
|
751
|
if (!isset($loaded[$type])) {
|
752
|
$path = module_load_include($type, 'forum_access');
|
753
|
$loaded[$type] = drupal_get_path('module', 'forum_access') . "/forum_access.$type";
|
754
|
}
|
755
|
return $loaded[$type];
|
756
|
}
|
757
|
|
758
|
/**
|
759
|
* Implements hook_theme().
|
760
|
*/
|
761
|
function forum_access_theme() {
|
762
|
return array(
|
763
|
'forum_access_table' => array(
|
764
|
'render element' => 'form',
|
765
|
'file' => 'forum_access.admin.inc',
|
766
|
),
|
767
|
);
|
768
|
}
|
769
|
|
770
|
/**
|
771
|
* Implements hook_node_access_explain().
|
772
|
*/
|
773
|
function forum_access_node_access_explain($row) {
|
774
|
$roles = &drupal_static(__FUNCTION__);
|
775
|
if ($row->realm == 'forum_access') {
|
776
|
if (!isset($roles)) {
|
777
|
$roles = user_roles();
|
778
|
}
|
779
|
if (isset($roles[$row->gid])) {
|
780
|
return array($roles[$row->gid]);
|
781
|
}
|
782
|
return array('(unknown gid)');
|
783
|
}
|
784
|
}
|
785
|
|
786
|
/**
|
787
|
* Implements hook_acl_explain().
|
788
|
*/
|
789
|
function forum_access_acl_explain($acl_id, $name, $number, $users = NULL) {
|
790
|
if (empty($users)) {
|
791
|
return "ACL (id=$acl_id) would grant access to nodes in forum/$number.";
|
792
|
}
|
793
|
return "ACL (id=$acl_id) grants access to nodes in forum/$number to the listed user(s).";
|
794
|
}
|
795
|
|