1
|
<?php
|
2
|
|
3
|
/**
|
4
|
* @file Content access module file.
|
5
|
*/
|
6
|
|
7
|
/**
|
8
|
* Implements hook_help().
|
9
|
*/
|
10
|
function content_access_help($path, $arg) {
|
11
|
switch ($path) {
|
12
|
case 'admin/help#content_access':
|
13
|
$output = '<h3>' . t('About') . '</h3>';
|
14
|
$output .= '<p>' . t('The <strong>Content Access</strong> module let you content manage access permission in a flexible and transparant way.') . '</p>';
|
15
|
$output .= '<h3>' . t('Use') . '</h3>';
|
16
|
$output .= '<p>' . t('It provides two new permissions: <em>view all</em> (allows anyone to view the content) and <em>view own</em> (allows only the content creator to see his/her own content). It also gives access to the existing core permissions <em>edit</em> and <em>delete</em> on the same settings page.') . '</p>';
|
17
|
$output .= '<p>' . t('It provides the following modalities:') . '</p><ul>';
|
18
|
$output .= '<li>' . t('Each <em>!content-type</em> can have its own default content access settings by role.', array('!content-type' => l('content type', 'admin/structure/types'))) . '</li>';
|
19
|
$output .= '<li>' . t('Optionally you can enable role based access control settings per <em>content node</em>.') . '</li>';
|
20
|
$output .= '<li>' . t('Access control can be further customized per <em>user</em> if you have the <strong>!acl</strong> module enabled.',
|
21
|
array('!acl' => l('ACL', 'https://www.drupal.org/project/acl/'))) . '</li></ul>';
|
22
|
if (function_exists('advanced_help_hint_docs')) {
|
23
|
$output .= '<p>' . advanced_help_hint_docs('content_access', 'https://drupal.org/node/1194974', TRUE) . '</p>';
|
24
|
}
|
25
|
else {
|
26
|
$output .= '<p>' .t('If you install and enable the module <strong>!url</strong>, you will get more help for <strong>Content Access</strong>.',
|
27
|
array('!url' => l('Advanced Help Hint', 'https://www.drupal.org/project/advanced_help_hint'))) . '</p>';
|
28
|
}
|
29
|
return $output;
|
30
|
}
|
31
|
}
|
32
|
|
33
|
/**
|
34
|
* Implements hook_admin_paths().
|
35
|
*/
|
36
|
function content_access_admin_paths() {
|
37
|
$paths = array(
|
38
|
'node/*/access' => TRUE,
|
39
|
);
|
40
|
return $paths;
|
41
|
}
|
42
|
|
43
|
/**
|
44
|
* Implements hook_menu().
|
45
|
*/
|
46
|
function content_access_menu() {
|
47
|
$items = array();
|
48
|
|
49
|
$items['node/%node/access'] = array(
|
50
|
'title' => 'Access control',
|
51
|
'page callback' => 'drupal_get_form',
|
52
|
'page arguments' => array('content_access_page', 1),
|
53
|
'access callback' => 'content_access_node_page_access',
|
54
|
'access arguments' => array(1),
|
55
|
'file' => 'content_access.admin.inc',
|
56
|
'theme callback' => '_node_custom_theme',
|
57
|
'type' => MENU_LOCAL_TASK,
|
58
|
'weight' => 3,
|
59
|
'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
|
60
|
);
|
61
|
|
62
|
$items['admin/structure/types/manage/%node_type/access'] = array(
|
63
|
'title' => 'Access control',
|
64
|
'description' => 'Configure content access control.',
|
65
|
'page callback' => 'drupal_get_form',
|
66
|
'page arguments' => array('content_access_admin_settings', 4),
|
67
|
'access callback' => 'content_access_admin_settings_access',
|
68
|
'access arguments' => array(),
|
69
|
'type' => MENU_LOCAL_TASK,
|
70
|
'file' => 'content_access.admin.inc',
|
71
|
'theme callback' => '_node_custom_theme',
|
72
|
'weight' => 1,
|
73
|
);
|
74
|
|
75
|
return $items;
|
76
|
}
|
77
|
|
78
|
/**
|
79
|
* Implements hook_perm().
|
80
|
*/
|
81
|
function content_access_permission() {
|
82
|
return array(
|
83
|
'grant content access' => array(
|
84
|
'title' => t('Grant content access'),
|
85
|
'description' => t('View and modify content access for any nodes'),
|
86
|
),
|
87
|
'grant own content access' => array(
|
88
|
'title' => t('Grant own content access'),
|
89
|
'description' => t('View and modify content access for own nodes'),
|
90
|
),
|
91
|
);
|
92
|
}
|
93
|
|
94
|
/**
|
95
|
* Get access tab page for the viewed node.
|
96
|
*/
|
97
|
function content_access_node_page_access($node) {
|
98
|
global $user;
|
99
|
return content_access_get_settings('per_node', $node->type) && user_access('grant content access') ||
|
100
|
content_access_get_settings('per_node', $node->type) && (user_access('grant own content access') && ($user->uid == $node->uid));
|
101
|
}
|
102
|
|
103
|
/**
|
104
|
* Content access settings for content type.
|
105
|
*/
|
106
|
function content_access_admin_settings_access() {
|
107
|
return user_access('administer nodes') && user_access('administer content types');
|
108
|
}
|
109
|
|
110
|
/**
|
111
|
* Implements hook_node_grants().
|
112
|
*/
|
113
|
function content_access_node_grants($account, $op) {
|
114
|
return array(
|
115
|
'content_access_author' => array($account->uid),
|
116
|
'content_access_rid' => array_keys($account->roles),
|
117
|
);
|
118
|
}
|
119
|
|
120
|
/**
|
121
|
* Implements hook_node_access_records().
|
122
|
*/
|
123
|
function content_access_node_access_records($node) {
|
124
|
if (content_access_disabling() || !$node->status) {
|
125
|
return;
|
126
|
}
|
127
|
|
128
|
// Apply per node settings if necessary.
|
129
|
if (content_access_get_settings('per_node', $node->type)) {
|
130
|
$grants = array();
|
131
|
foreach (array('view', 'update', 'delete') as $op) {
|
132
|
foreach (content_access_get_rids_per_node_op($op, $node) as $rid) {
|
133
|
$grants[$rid]['grant_' . $op] = 1;
|
134
|
}
|
135
|
}
|
136
|
foreach ($grants as $rid => $grant) {
|
137
|
$grants[$rid] = content_access_proccess_grant($grant, $rid, $node);
|
138
|
}
|
139
|
|
140
|
// Care for the author grant.
|
141
|
$grant = array();
|
142
|
foreach (array('view', 'update', 'delete') as $op) {
|
143
|
// Get all roles that have access to use $op on this node.
|
144
|
$any_roles = drupal_map_assoc(content_access_per_node_setting($op, $node));
|
145
|
$any_roles = $any_roles ? $any_roles : array();
|
146
|
$any_roles += ($op != 'view') ? content_access_get_settings($op, $node->type) : array();
|
147
|
$grant['grant_' . $op] = content_access_own_op($node, $any_roles, content_access_get_rids_per_node_op($op . '_own', $node));
|
148
|
}
|
149
|
|
150
|
if (array_filter($grant)) {
|
151
|
$grant['realm'] = 'content_access_author';
|
152
|
$grants[] = content_access_proccess_grant($grant, $node->uid, $node);
|
153
|
}
|
154
|
}
|
155
|
else {
|
156
|
// Apply the content type defaults.
|
157
|
$grants = content_access_get_type_grant($node);
|
158
|
}
|
159
|
|
160
|
if (empty($grants)) {
|
161
|
// This means we grant no access.
|
162
|
$grants[] = content_access_proccess_grant(array(), 0, $node);
|
163
|
}
|
164
|
else {
|
165
|
content_access_optimize_grants($grants, $node);
|
166
|
}
|
167
|
|
168
|
return $grants;
|
169
|
}
|
170
|
|
171
|
/**
|
172
|
* Implements hook_node_delete().
|
173
|
*/
|
174
|
function content_access_node_delete($node) {
|
175
|
db_delete('content_access')
|
176
|
->condition('nid', $node->nid)
|
177
|
->execute();
|
178
|
}
|
179
|
|
180
|
/**
|
181
|
* Used by the ACL module.
|
182
|
*/
|
183
|
function content_access_enabled() {
|
184
|
return !content_access_disabling();
|
185
|
}
|
186
|
|
187
|
/**
|
188
|
* Implements hook_disable().
|
189
|
*/
|
190
|
function content_access_disable() {
|
191
|
content_access_disabling(TRUE);
|
192
|
}
|
193
|
|
194
|
/**
|
195
|
* Remembers if we have disabled access.
|
196
|
*/
|
197
|
function content_access_disabling($set = NULL) {
|
198
|
static $disabling = FALSE;
|
199
|
|
200
|
if (isset($set)) {
|
201
|
$disabling = $set;
|
202
|
}
|
203
|
return $disabling;
|
204
|
}
|
205
|
|
206
|
/**
|
207
|
* Return content_access' settings.
|
208
|
*
|
209
|
* @param $setting
|
210
|
* One of the content_access_available_settings(), e.g. 'view' or 'per_node'.
|
211
|
* If 'all' is passed, all available settings are returned.
|
212
|
* @param $type_name
|
213
|
* The name of the content type to return settings for.
|
214
|
*
|
215
|
* @return
|
216
|
* The value of the given setting or an array of all settings.
|
217
|
*/
|
218
|
function content_access_get_settings($setting, $type_name) {
|
219
|
$settings = variable_get('content_access_' . $type_name, array());
|
220
|
$settings += content_access_get_setting_defaults($type_name);
|
221
|
if ($setting == 'all') {
|
222
|
return $settings;
|
223
|
}
|
224
|
return isset($settings[$setting]) ? $settings[$setting] : NULL;
|
225
|
}
|
226
|
|
227
|
/**
|
228
|
* Save content_access settings of a content type.
|
229
|
*/
|
230
|
function content_access_set_settings($settings, $type_name) {
|
231
|
// Do not store default values so we do not have to care about syncing our
|
232
|
// settings with the permissions.
|
233
|
foreach (content_access_get_setting_defaults($type_name) as $setting => $default_value) {
|
234
|
if (isset($settings[$setting]) && $settings[$setting] == $default_value) {
|
235
|
unset($settings[$setting]);
|
236
|
}
|
237
|
}
|
238
|
variable_set('content_access_' . $type_name, $settings);
|
239
|
}
|
240
|
|
241
|
/**
|
242
|
* Return an array containing all available content_access settings.
|
243
|
*/
|
244
|
function content_access_available_settings() {
|
245
|
return array('view', 'update', 'delete', 'view_own', 'update_own', 'delete_own', 'per_node', 'priority');
|
246
|
}
|
247
|
|
248
|
/**
|
249
|
* Defines default values for settings.
|
250
|
*/
|
251
|
function content_access_get_setting_defaults($type) {
|
252
|
$defaults = array();
|
253
|
$defaults['view'] = $defaults['view_own'] = array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID);
|
254
|
foreach (array('update', 'delete') as $op) {
|
255
|
$defaults[$op] = content_access_get_permission_access(content_access_get_permission_by_op($op, $type));
|
256
|
$defaults[$op . '_own'] = content_access_get_permission_access(content_access_get_permission_by_op($op . '_own', $type));
|
257
|
}
|
258
|
$defaults['priority'] = 0;
|
259
|
$defaults['per_node'] = FALSE;
|
260
|
return $defaults;
|
261
|
}
|
262
|
|
263
|
/**
|
264
|
* Returns an array of role ids that contain the given permission.
|
265
|
*/
|
266
|
function content_access_get_permission_access($perm, $reset = FALSE) {
|
267
|
$roles = &drupal_static(__FUNCTION__, array());
|
268
|
|
269
|
if ($reset) {
|
270
|
$roles = array();
|
271
|
}
|
272
|
if (!isset($roles[$perm]) && $perm) {
|
273
|
$roles[$perm] = array_keys(user_roles(0, $perm));
|
274
|
}
|
275
|
return isset($roles[$perm]) ? $roles[$perm] : array();
|
276
|
}
|
277
|
|
278
|
/**
|
279
|
* Gets the name of a permission for the given operation, if there is a suiting one.
|
280
|
*/
|
281
|
function content_access_get_permission_by_op($op, $type) {
|
282
|
switch ($op) {
|
283
|
default:
|
284
|
return FALSE;
|
285
|
case 'update':
|
286
|
return 'edit any ' . $type . ' content';
|
287
|
case 'update_own':
|
288
|
return 'edit own ' . $type . ' content';
|
289
|
case 'delete':
|
290
|
return 'delete any ' . $type . ' content';
|
291
|
case 'delete_own':
|
292
|
return 'delete own ' . $type . ' content';
|
293
|
}
|
294
|
}
|
295
|
|
296
|
/**
|
297
|
* Returns the default grants for a given node type.
|
298
|
*/
|
299
|
function content_access_get_type_grant($node) {
|
300
|
// Cache per type default grants in a static array
|
301
|
static $defaults = array();
|
302
|
|
303
|
if (!isset($defaults[$node->type])) {
|
304
|
$grants = array();
|
305
|
|
306
|
// Only process the 'view' op as node_access() will take care of edit and delete
|
307
|
foreach (content_access_get_settings('view', $node->type) as $rid) {
|
308
|
$grants[$rid]['grant_view'] = 1;
|
309
|
$grants[$rid] = content_access_proccess_grant($grants[$rid], $rid, $node);
|
310
|
}
|
311
|
$defaults[$node->type] = $grants;
|
312
|
}
|
313
|
|
314
|
// Care for the author grant.
|
315
|
$grant = $grants = array();
|
316
|
$grant['grant_view'] = content_access_own_op($node, content_access_get_settings('view', $node->type), content_access_get_settings('view_own', $node->type));
|
317
|
if ($grant['grant_view']) {
|
318
|
$grant['realm'] = 'content_access_author';
|
319
|
$grants = array('author' => content_access_proccess_grant($grant, $node->uid, $node));
|
320
|
}
|
321
|
|
322
|
return $defaults[$node->type] + $grants;
|
323
|
}
|
324
|
|
325
|
/**
|
326
|
* Process a grant, which means add priority, realm and other properties.
|
327
|
*/
|
328
|
function content_access_proccess_grant($grant, $gid, $node) {
|
329
|
$grant += array('grant_view' => 0, 'grant_update' => 0, 'grant_delete' => 0, 'realm' => 'content_access_rid');
|
330
|
$grant['gid'] = $gid;
|
331
|
$grant['priority'] = content_access_get_settings('priority', $node->type);
|
332
|
return $grant;
|
333
|
}
|
334
|
|
335
|
/**
|
336
|
* Determines the grant for the node author and the given allowed roles of a operation.
|
337
|
*
|
338
|
* @param $any_roles
|
339
|
* The roles with which anybody has access (not optimized!)
|
340
|
* @param $own_roles
|
341
|
* The roles with which only the author has access (optimized!)
|
342
|
*/
|
343
|
function content_access_own_op($node, $any_roles, $own_roles) {
|
344
|
static $roles = array();
|
345
|
|
346
|
if (!isset($roles[$node->uid])) {
|
347
|
$roles[$node->uid] = $node->uid ? array(DRUPAL_AUTHENTICATED_RID) : array(DRUPAL_ANONYMOUS_RID);
|
348
|
$result = db_query('SELECT rid FROM {users_roles} WHERE uid = :uid', array(':uid' => $node->uid));
|
349
|
|
350
|
foreach ($result as $role) {
|
351
|
$roles[$node->uid][] = $role->rid;
|
352
|
}
|
353
|
}
|
354
|
if (array_intersect($roles[$node->uid], $any_roles)) {
|
355
|
// If there is access due to "any permissions" there is no need to at an author grant.
|
356
|
return 0;
|
357
|
}
|
358
|
return array_intersect($roles[$node->uid], $own_roles) ? 1 : 0;
|
359
|
}
|
360
|
|
361
|
/**
|
362
|
* Returns optimized role ids for the given operation and node to
|
363
|
* grant access for.
|
364
|
*
|
365
|
* If to a role access is granted by permissions, it's not necessary
|
366
|
* to write a grant for it. So it won't be returned.
|
367
|
*
|
368
|
* @param $op
|
369
|
* One of the supported operations.
|
370
|
* @param $node
|
371
|
* The node object.
|
372
|
*/
|
373
|
function content_access_get_rids_per_node_op($op, $node) {
|
374
|
$rids = content_access_per_node_setting($op, $node);
|
375
|
|
376
|
if ($permission = content_access_get_permission_by_op($op, $node->type)) {
|
377
|
$perm_roles = content_access_get_permission_access($permission);
|
378
|
$rids = array_diff($rids, $perm_roles);
|
379
|
|
380
|
if (in_array(DRUPAL_AUTHENTICATED_RID, $perm_roles)) {
|
381
|
return in_array(DRUPAL_ANONYMOUS_RID, $rids) ? array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID) : array(DRUPAL_AUTHENTICATED_RID);
|
382
|
}
|
383
|
}
|
384
|
return $rids;
|
385
|
}
|
386
|
|
387
|
|
388
|
/**
|
389
|
* Returns the per node role settings. If no per node settings are available,
|
390
|
* it will return the content type settings.
|
391
|
*
|
392
|
* @param $op
|
393
|
* One of the supported operations.
|
394
|
* @param $node
|
395
|
* The node object.
|
396
|
* @param $settings
|
397
|
* Optional array used to update the settings cache with the given settings.
|
398
|
* @return
|
399
|
* An array of role ids which have access.
|
400
|
*/
|
401
|
function content_access_per_node_setting($op, $node, $settings = NULL) {
|
402
|
static $grants = array();
|
403
|
|
404
|
if (isset($settings)) {
|
405
|
// Update settings cache
|
406
|
$grants[$node->nid] = $settings;
|
407
|
return;
|
408
|
}
|
409
|
|
410
|
if (!isset($grants[$node->nid]) || $grants[$node->nid] === FALSE) {
|
411
|
$grants[$node->nid] = content_access_get_per_node_settings($node);
|
412
|
}
|
413
|
|
414
|
// Return the content type defaults if no per node settings are available
|
415
|
return isset($grants[$node->nid][$op]) ? $grants[$node->nid][$op] : content_access_get_settings($op, $node->type);
|
416
|
}
|
417
|
|
418
|
/**
|
419
|
* Gets the per node settings of a node.
|
420
|
*
|
421
|
* @note
|
422
|
* This function won't apply defaults, so if there are no other settings
|
423
|
* it will return an empty array.
|
424
|
*/
|
425
|
function content_access_get_per_node_settings($node) {
|
426
|
foreach (db_query("SELECT settings FROM {content_access} WHERE nid = :nid", array(':nid' => $node->nid)) as $record) {
|
427
|
$settings = $record->settings;
|
428
|
if (!$settings) {
|
429
|
return array();
|
430
|
}
|
431
|
return unserialize($settings);
|
432
|
}
|
433
|
}
|
434
|
|
435
|
/**
|
436
|
* Saves custom per node settings in the own content_access table.
|
437
|
*/
|
438
|
function content_access_save_per_node_settings($node, $settings) {
|
439
|
$count = db_select('content_access')
|
440
|
->condition('nid', $node->nid)
|
441
|
->countQuery()->execute()->fetchField();
|
442
|
|
443
|
if ($count > 0) {
|
444
|
db_update('content_access')
|
445
|
->condition('nid', $node->nid)
|
446
|
->fields(array('settings' => serialize($settings)))
|
447
|
->execute();
|
448
|
}
|
449
|
else {
|
450
|
db_insert('content_access')
|
451
|
->fields(array('nid' => $node->nid, 'settings' => serialize($settings)))
|
452
|
->execute();
|
453
|
}
|
454
|
|
455
|
// Make content_access_per_node_setting() use the new settings
|
456
|
content_access_per_node_setting(NULL, $node, $settings);
|
457
|
}
|
458
|
|
459
|
/**
|
460
|
* Deletes all custom per node settings, so that content type defaults are used again.
|
461
|
*/
|
462
|
function content_access_delete_per_node_settings($node) {
|
463
|
db_delete('content_access')
|
464
|
->condition('nid', $node->nid)
|
465
|
->execute();
|
466
|
|
467
|
// Clear the cache.
|
468
|
content_access_per_node_setting(NULL, $node, FALSE);
|
469
|
|
470
|
// Delete possible acl settings
|
471
|
if (module_exists('acl')) {
|
472
|
// @todo why content_access.admin.inc is not loaded before?
|
473
|
module_load_include('inc', 'content_access', 'content_access.admin');
|
474
|
foreach (array('view', 'update', 'delete') as $op) {
|
475
|
$acl_id = content_access_get_acl_id($node, $op);
|
476
|
acl_delete_acl($acl_id);
|
477
|
}
|
478
|
}
|
479
|
}
|
480
|
|
481
|
/**
|
482
|
* Removes grants that doesn't change anything.
|
483
|
*
|
484
|
* @note
|
485
|
* The grants are compared with the normal access control settings.
|
486
|
*/
|
487
|
function content_access_optimize_grants(&$grants, $node) {
|
488
|
$rids = array('view' => array(), 'update' => array(), 'delete' => array());
|
489
|
|
490
|
foreach ($grants as $key => $grant) {
|
491
|
foreach (array('view', 'update', 'delete') as $op) {
|
492
|
if (is_numeric($key) && !empty($grant['grant_' . $op])) {
|
493
|
$rids[$op][] = $key;
|
494
|
}
|
495
|
}
|
496
|
}
|
497
|
|
498
|
// Detect if all are allowed to view
|
499
|
$all = array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID);
|
500
|
if (count(array_diff($all, $rids['view'])) == 0) {
|
501
|
//grant view access to all instead of single roles
|
502
|
$rids['view'] = array('all');
|
503
|
$grants['all'] = array('realm' => 'all', 'gid' => 0, 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0, 'priority' => content_access_get_settings('priority', $node->type));
|
504
|
}
|
505
|
|
506
|
// If authenticated users are involved, remove unnecessary other roles.
|
507
|
foreach (array('view', 'update', 'delete') as $op) {
|
508
|
if (in_array(DRUPAL_AUTHENTICATED_RID, $rids[$op])) {
|
509
|
$rids[$op] = in_array(DRUPAL_ANONYMOUS_RID, $rids[$op]) ? array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID) : array(DRUPAL_AUTHENTICATED_RID);
|
510
|
}
|
511
|
}
|
512
|
|
513
|
// Now let's remove unnecessary grants, if any.
|
514
|
foreach ($grants as $key => $grant) {
|
515
|
if (!is_numeric($key)) {
|
516
|
continue;
|
517
|
}
|
518
|
foreach (array('view', 'update', 'delete') as $op) {
|
519
|
if ($grant['grant_' . $op] && in_array($key, $rids[$op])) {
|
520
|
//it's still here, so we can't remove this grant
|
521
|
continue 2;
|
522
|
}
|
523
|
}
|
524
|
//ok, remove it
|
525
|
unset($grants[$key]);
|
526
|
}
|
527
|
}
|
528
|
|
529
|
/**
|
530
|
* Implements hook_node_type_delete().
|
531
|
*/
|
532
|
function content_access_node_type_delete($info) {
|
533
|
variable_del('content_access_' . $info->type);
|
534
|
}
|
535
|
|
536
|
/**
|
537
|
* Implements hook_node_type_update().
|
538
|
*
|
539
|
* Updates settings on node type name change.
|
540
|
*/
|
541
|
function content_access_node_type_update($info) {
|
542
|
if (!empty($info->old_type) && $info->old_type != $info->type) {
|
543
|
$settings = content_access_get_settings('all', $info->old_type);
|
544
|
content_access_set_settings($settings, $info->type);
|
545
|
variable_del('content_access_' . $info->old_type);
|
546
|
}
|
547
|
}
|
548
|
|
549
|
/**
|
550
|
* Implements hook_node_access_explain().
|
551
|
*/
|
552
|
function content_access_node_access_explain($row) {
|
553
|
static $roles;
|
554
|
|
555
|
if (!isset($roles)) {
|
556
|
$roles = user_roles();
|
557
|
}
|
558
|
if (!$row->gid && $row->realm == 'content_access_rid') {
|
559
|
return t('Content access: No access is granted.');
|
560
|
}
|
561
|
switch ($row->realm) {
|
562
|
case 'content_access_author':
|
563
|
return t('Content access: author of the content can access');
|
564
|
case 'content_access_rid':
|
565
|
return t('Content access: %role can access', array('%role' => $roles[$row->gid]));
|
566
|
}
|
567
|
}
|
568
|
|
569
|
/**
|
570
|
* Implements hook_form_alter().
|
571
|
*/
|
572
|
function content_access_form_alter(&$form, $form_state, $form_id) {
|
573
|
if ($form_id == 'user_admin_perm') {
|
574
|
module_load_include('inc', 'content_access', 'content_access.admin');
|
575
|
$form['#submit'][] = 'content_access_user_admin_perm_submit';
|
576
|
}
|
577
|
}
|
578
|
|
579
|
/**
|
580
|
* Returns an array of possible operations on content and their labels.
|
581
|
*/
|
582
|
function _content_access_get_operations($type = NULL) {
|
583
|
$operations = array(
|
584
|
'view' => t('View any @type content', array('@type' => $type)),
|
585
|
'view_own' => t('View own @type content', array('@type' => $type)),
|
586
|
'update' => t('Edit any @type content', array('@type' => $type)),
|
587
|
'update_own' => t('Edit own @type content', array('@type' => $type)),
|
588
|
'delete' => t('Delete any @type content', array('@type' => $type)),
|
589
|
'delete_own' => t('Delete own @type content', array('@type' => $type)),
|
590
|
);
|
591
|
return $operations;
|
592
|
}
|
593
|
|
594
|
/**
|
595
|
* Formapi #process callback, that disables checkboxes for roles without access to content
|
596
|
*/
|
597
|
function content_access_disable_checkboxes($element) {
|
598
|
$access_roles = content_access_get_permission_access('access content');
|
599
|
$admin_roles = content_access_get_permission_access('bypass node access');
|
600
|
|
601
|
foreach (element_children($element) as $key) {
|
602
|
if (!in_array($key, $access_roles) &&
|
603
|
$key == DRUPAL_ANONYMOUS_RID &&
|
604
|
!in_array(DRUPAL_AUTHENTICATED_RID, $access_roles)) {
|
605
|
$element[$key]['#disabled'] = TRUE;
|
606
|
$element[$key]['#default_value'] = FALSE;
|
607
|
$element[$key]['#prefix'] = '<span' . drupal_attributes(array('title' => t("This role is lacking the permission '@perm', so it has no access.", array('@perm' => t('access content'))))) . '>';
|
608
|
$element[$key]['#suffix'] = "</span>";
|
609
|
}
|
610
|
elseif (in_array($key, $admin_roles) ||
|
611
|
($key != DRUPAL_ANONYMOUS_RID && in_array(DRUPAL_AUTHENTICATED_RID, $admin_roles))) {
|
612
|
// Fix the checkbox to be enabled for users with bypass node access privileges
|
613
|
$element[$key]['#disabled'] = TRUE;
|
614
|
$element[$key]['#default_value'] = TRUE;
|
615
|
$element[$key]['#prefix'] = '<span' . drupal_attributes(array('title' => t("This role has '@perm' permission, so access is granted.", array('@perm' => t('bypass node access'))))) . '>';
|
616
|
$element[$key]['#suffix'] = "</span>";
|
617
|
}
|
618
|
}
|
619
|
|
620
|
return $element;
|
621
|
}
|
622
|
|
623
|
/**
|
624
|
* Gets node's access permissions.
|
625
|
*/
|
626
|
function _content_access_get_node_permissions($type) {
|
627
|
return array_filter(array_map('content_access_get_permission_by_op', array_flip(_content_access_get_operations()), array_fill(0, 6, $type)));
|
628
|
}
|
629
|
|
630
|
/**
|
631
|
* Gets the content access acl id of the node.
|
632
|
*/
|
633
|
function content_access_get_acl_id($node, $op) {
|
634
|
$acl_id = acl_get_id_by_name('content_access', $op . '_' . $node->nid);
|
635
|
if (!$acl_id) {
|
636
|
$acl_id = acl_create_new_acl('content_access', $op . '_' . $node->nid);
|
637
|
}
|
638
|
return $acl_id;
|
639
|
}
|
640
|
|
641
|
/**
|
642
|
* Detaches all our ACLs for the nodes of the given type.
|
643
|
*/
|
644
|
function _content_access_remove_acls($type) {
|
645
|
$result = db_query("SELECT n.nid FROM {node} n WHERE type = :type", array('type' => $type));
|
646
|
foreach ($result as $node) {
|
647
|
acl_node_clear_acls($node->nid, 'content_access');
|
648
|
}
|
649
|
}
|
650
|
|
651
|
/**
|
652
|
* Implements hook_node_export_alter().
|
653
|
*/
|
654
|
function content_access_node_export_alter(array $nodes) {
|
655
|
foreach ($nodes as $node) {
|
656
|
$node->content_access = content_access_get_per_node_settings($node);
|
657
|
}
|
658
|
}
|
659
|
|
660
|
/**
|
661
|
* Implements hook_node_export_after_import_alter().
|
662
|
*/
|
663
|
function content_access_node_export_after_import_alter(array $nodes) {
|
664
|
foreach ($nodes as $node) {
|
665
|
if(empty($node->nid))
|
666
|
continue;
|
667
|
content_access_save_per_node_settings($node, $node->content_access);
|
668
|
}
|
669
|
// Rebuild content access permissions
|
670
|
node_access_rebuild();
|
671
|
}
|