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

Contents of /contributions/modules/node_privacy_byrole/node_privacy_byrole.module

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


Revision 1.34 - (show annotations) (download) (as text)
Fri Feb 13 22:33:27 2009 UTC (9 months, 1 week ago) by deekayen
Branch: MAIN
CVS Tags: HEAD
Changes since 1.33: +284 -41 lines
File MIME type: text/x-php
copy of 6.x
1 <?php
2 // $Id: node_privacy_byrole.module,v 1.32.2.8 2009/02/13 16:49:05 deekayen Exp $
3
4 /**
5 * @file
6 * Set node access permissions by role.
7 */
8
9 /**
10 * Implementation of hook_help().
11 */
12 function node_privacy_byrole_help($path, $arg) {
13 switch ($path) {
14 case 'admin/help#node_privacy_byrole':
15 $output = '<p>'. t('The node privacy by role module allows users, when creating or editing a post, to select which roles of users on a site will have <em>view</em> permissions for the node and which users on a site will have <em>edit</em> permissions. Community leaders frequently want to give permissions to roles to create and manage content for a site. The ability to publish information, that would traditionally be hoarded, allows communities to educate each other while still preserving the value of knowledge.') .'</p>';
16 $output .= '<p>'. t('The node privacy by-role permissions are set by users for their nodes. If the node privacy by role module is disabled, the default permissions scheme will be in effect again, in which all users have view permissions for all nodes. However, if the module is re-enabled, the node-by-node permissions that were in place during the previous period in which the module was enabled will take effect again. Roles given edit permissions are automatically given view permissions even if the user tries to give <em>edit</em> permissions to a particular role, but not view permissions.') .'</p>';
17 $output .= t('<p>You can:</p>
18 <ul>
19 <li>set default permissions for each content type in the default workflow settings at <a href="@admin-node-configure-types">Administer &gt;&gt; Content management &gt;&gt; Content types</a> for each content type.</li>
20 <li>decide who can ignore the default permissions for each content type in the default workflow settings at <a href="@admin-node-configure-types">Administer &gt;&gt; Content management &gt;&gt; Content types</a> for each content type.</li>
21 </ul>', array('@admin-node-configure-types' => url('admin/content/types')));
22 $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@node_privacy_byrole">Node privacy by role page</a>.', array('@node_privacy_byrole' => 'http://www.drupal.org/handbook/modules/node_privacy_byrole/')) .'</p>';
23 return $output;
24 }
25 }
26
27 /**
28 * Simple function to identify when module is being disabled
29 * so that as the node_access table is rebuilt, it doesn't set
30 * any permissions for this module
31 */
32 function node_privacy_byrole_disabling($set = NULL) {
33 static $disabling = FALSE;
34 if ($set != NULL) {
35 $disabling = $set;
36 }
37 return $disabling;
38 }
39
40
41 /**
42 * Implementation of hook_node_grants().
43 */
44 function node_privacy_byrole_node_grants($account, $op) {
45 return array(
46 'node_privacy_byrole_role' => array_keys($account->roles),
47 'node_privacy_byrole_user' => array($account->uid)
48 );
49 }
50
51
52 /**
53 * Implementation of hook_node_access_records().
54 */
55 function node_privacy_byrole_node_access_records($node) {
56 if (node_privacy_byrole_disabling()) {
57 return;
58 }
59
60 node_privacy_byrole_nodeapi_prepare($node);
61
62 $grants = array();
63
64 // permission for node owner
65 if ($node->uid > 0) {
66 $grants[] = array(
67 'realm' => 'node_privacy_byrole_user',
68 'gid' => $node->uid,
69 'grant_view' => TRUE,
70 'grant_update' => FALSE,
71 'grant_delete' => FALSE,
72 'priority' => 0,
73 );
74 }
75 // permission for node roles
76 foreach (array_keys(user_roles()) as $rid) {
77 $edit_perm = $node->node_privacy_byrole['roles'][$rid]['edit'] ? 1 : 0;
78 $delete_perm = $node->node_privacy_byrole['roles'][$rid]['delete'] ? 1 : 0;
79 $view_perm = (($edit_perm || $delete_perm) ? 1 : $node->node_privacy_byrole['roles'][$rid]['view']);
80
81 $grants[] = array(
82 'realm' => 'node_privacy_byrole_role',
83 'gid' => $rid,
84 'grant_view' => $view_perm,
85 'grant_update' => $edit_perm,
86 'grant_delete' => $delete_perm,
87 'priority' => 0,
88 );
89 }
90
91 return $grants;
92 }
93
94 /**
95 * Implementation of hook_nodeapi().
96 */
97 function node_privacy_byrole_nodeapi(&$node, $op, $arg = 0) {
98 $roles = array_keys(user_roles());
99
100 switch ($op) {
101 case 'load':
102 case 'prepare':
103 node_privacy_byrole_nodeapi_prepare($node);
104 break;
105 case 'delete':
106 db_query('DELETE FROM {node_privacy_byrole} WHERE nid = %d', $node->nid);
107 break;
108 case 'insert':
109 node_privacy_byrole_nodeapi_prepare($node); // http://drupal.org/node/256396
110
111 foreach ($roles as $rid) {
112 db_query("INSERT INTO {node_privacy_byrole} (nid, gid, realm, grant_view, grant_update, grant_delete)
113 VALUES (%d, %d, '%s', %d, %d, %d)", $node->nid, $rid, 'node_privacy_byrole_role', $node->node_privacy_byrole['roles'][$rid]['view'], $node->node_privacy_byrole['roles'][$rid]['edit'], $node->node_privacy_byrole['roles'][$rid]['delete']);
114 }
115 db_query("INSERT INTO {node_privacy_byrole} (nid, gid, realm, grant_view, grant_update, grant_delete)
116 VALUES (%d, %d, '%s', %d, %d, %d)", $node->nid, $node->uid, 'node_privacy_byrole_user', 1, 1, 1);
117 break;
118 case 'update':
119 node_privacy_byrole_nodeapi_prepare($node); // http://drupal.org/node/153588
120
121 // As a new role might have been added since creation of the node, we cannot simply "update" and so delete and reinsert
122 db_query("DELETE FROM {node_privacy_byrole} WHERE nid = %d AND realm = 'node_privacy_byrole_role'", $node->nid);
123 foreach ($roles as $rid) {
124 db_query("INSERT INTO {node_privacy_byrole} (nid, gid, realm, grant_view, grant_update, grant_delete)
125 VALUES (%d, %d, '%s', %d, %d, %d)", $node->nid, $rid, 'node_privacy_byrole_role', $node->node_privacy_byrole['roles'][$rid]['view'],
126 $node->node_privacy_byrole['roles'][$rid]['edit'], $node->node_privacy_byrole['roles'][$rid]['delete']);
127 }
128 // Record for owner exists for sure, so we can simply update it
129 db_query("UPDATE {node_privacy_byrole} SET grant_view = %d, grant_update = %d, grant_delete = %d
130 WHERE nid = %d AND gid = %d AND realm = 'node_privacy_byrole_user'", 1, 0, 0, $node->nid, $node->uid);
131 break;
132 }
133 }
134
135 function node_privacy_byrole_nodeapi_prepare(&$node) {
136 if (!isset($node->node_privacy_byrole)) {
137 $roles = array_keys(user_roles());
138 $perms = array('view', 'edit', 'delete');
139
140 if (isset($node->nid) && empty($node->is_new)) {
141 // this is an existing node, get current permissions
142 $result = db_query("SELECT gid, grant_view, grant_update, grant_delete FROM {node_privacy_byrole} "
143 ."WHERE nid = %d AND realm = 'node_privacy_byrole_role'", $node->nid);
144
145 $current_perms = array();
146 while ($role = db_fetch_object($result)) {
147 $current_perms[$role->gid]['view'] = $role->grant_view;
148 $current_perms[$role->gid]['edit'] = $role->grant_update;
149 $current_perms[$role->gid]['delete'] = $role->grant_delete;
150 }
151
152 while (list(, $rid) = each($roles)) {
153 // if the role exists in node_privacy_byrole table, fill its perm with the database ones
154 if (isset($current_perms[$rid])) {
155 while (list(, $perm) = each($perms)) {
156 $node->node_privacy_byrole['roles'][$rid][$perm] = $current_perms[$rid][$perm] ? 1 : 0;
157 }
158 }
159 else {
160 // else : the role doesn't exist in node_privacy_byrole table (it has been recently added).
161 // In this case, fill perms with default ones
162 while (list(, $perm) = each($perms)) {
163 $default_roles = _node_privacy_byrole_get_default_roles($node->type, $perm);
164 $node->node_privacy_byrole['roles'][$rid][$perm] = in_array($rid, $default_roles) ? 1 : 0;
165 }
166 }
167 reset($perms);
168 }
169 }
170 else {
171 // case where node is being created
172 while (list(, $rid) = each($roles)) {
173 while (list(, $perm) = each($perms)) {
174 $default_roles = _node_privacy_byrole_get_default_roles($node->type, $perm);
175 $node->node_privacy_byrole['roles'][$rid][$perm] = in_array($rid, $default_roles) ? 1 : 0;
176 }
177 reset($perms);
178 }
179 }
180 }
181 }
182
183 /**
184 * Implementation of hook_form_alter().
185 */
186 function node_privacy_byrole_form_alter(&$form, $form_state, $form_id) {
187 if ('node_type_form' == $form_id) {
188 node_privacy_byrole_node_type_form($form);
189 }
190 elseif ('node_configure' == $form_id) {
191 $form['npbr_default_permissions'] = array(
192 '#type' => 'checkbox',
193 '#title' => 'When rebuilding permissions, reset the node privacy by role permissions on all nodes to the content type defaults.',
194 '#weight' => 0,
195 '#default_value' => variable_get('npbr_default_permissions', 0),
196 );
197 $form['access']['#weight'] = -1;
198 }
199 elseif ('node_configure_rebuild_confirm' == $form_id) {
200 if (variable_get('npbr_default_permissions', 0)) {
201 // Make sure the npbr handler runs first.
202 $form['#submit'] = array_merge(array('node_privacy_byrole_rebuild_submit'), $form['#submit']);
203 }
204 }
205 elseif ($form['#id'] == 'node-form') {
206 if (node_privacy_byrole_user_has_meta_perm($form['#node'])) {
207 node_privacy_byrole_node_form($form);
208 }
209 }
210 }
211
212 function node_privacy_byrole_rebuild_submit($form, &$form_state) {
213 db_query('TRUNCATE TABLE {node_privacy_byrole}');
214 }
215
216 /**
217 * Checks that the active user has access to set permissions on nodes.
218 */
219 function node_privacy_byrole_user_has_meta_perm($node) {
220 global $user;
221
222 if ($user->uid == 1) {
223 return TRUE;
224 }
225
226 $permitted_roles = _node_privacy_byrole_get_default_roles($node->type, 'grant');
227 $user_roles = array_keys($user->roles);
228
229 return count(array_intersect($permitted_roles, $user_roles)) ? TRUE : FALSE;
230 }
231
232 /**
233 * Returns those role id's that are permitted to do $action on a $type node
234 */
235 function _node_privacy_byrole_get_default_roles($type, $action) {
236 return variable_get('npbr_default_'. $action .'_perms_'. $type, array());
237 }
238
239 /**
240 * Form elements that extends node type form
241 * Used for set the default permission settings per node type
242 */
243 function node_privacy_byrole_node_type_form(&$form) {
244 $type = $form['#node_type']->type;
245
246 $roles = user_roles();
247
248 $perms = array(
249 'view' => array(
250 'title' => t('Default View Permissions'),
251 'description' => t('Select roles to be given view permisions by default.'),
252 ),
253 'edit' => array(
254 'title' => t('Default Edit Permissions'),
255 'description' => t('Select roles to be given edit permissions by default.'),
256 ),
257 'delete' => array(
258 'title' => t('Default Delete Permissions'),
259 'description' => t('Select roles to be given delete permissions by default.'),
260 ),
261 'grant' => array(
262 'title' => t('Roles with rights to update permissions'),
263 'description' => t('Select which roles will have rights to alter permissions on nodes.'),
264 ),
265 );
266
267 $form['npbr_workflow_settings'] = array(
268 '#type' => 'fieldset',
269 '#title' => t('Node privacy by role'),
270 '#collapsible' => TRUE,
271 '#collapsed' => TRUE
272 );
273
274 while (list($perm, $permdata) = each($perms)) {
275 $permname = 'npbr_default_'. $perm .'_perms';
276
277 $form['npbr_workflow_settings'][$permname] = array(
278 '#tree' => TRUE,
279 '#type' => 'fieldset',
280 '#title' => $permdata['title'],
281 '#collapsible' => FALSE,
282 '#collapsed' => FALSE,
283 '#description' => $permdata['description'],
284 '#weight' => 0,
285 );
286
287 $default_perms = _node_privacy_byrole_get_default_roles($type, $perm);
288
289 foreach (array_keys($roles) as $rid) {
290 $form['npbr_workflow_settings'][$permname][$rid] = array(
291 '#type' => 'checkbox',
292 '#title' => t($roles[$rid]),
293 '#return_value' => 1,
294 '#default_value' => in_array($rid, $default_perms),
295 );
296 }
297 }
298 }
299
300 /**
301 * Form elements that extends node edit form
302 */
303 function node_privacy_byrole_node_form(&$form) {
304
305 $roles = array_keys(user_roles());
306 $perms = array('view', 'edit', 'delete');
307
308 // create checkboxes for every role and every permission
309 // later depending on the $op variable only the default values will be updated
310 $form['node_privacy_byrole'] = array(
311 '#tree' => TRUE,
312 '#theme' => 'node_privacy_byrole_node_form',
313 '#type' => 'fieldset',
314 '#title' => t('View/Edit Permissions'),
315 '#collapsible' => TRUE,
316 // collapse depends on bug when viewing tables included in collapsed fielsets in IE7:
317 // http://drupal.org/node/237565
318 '#collapsed' => strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7.0') > 0 ? FALSE : TRUE,
319 '#weight' => 9,
320 );
321
322 while (list(, $rid) = each($roles)) {
323 $form['node_privacy_byrole']['roles'][$rid] = array(
324 '#type' => 'fieldset',
325 '#collapsible' => FALSE,
326 '#collapsed' => FALSE,
327 '#weight' => 0
328 );
329 while (list(, $perm) = each($perms)) {
330 $form['node_privacy_byrole']['roles'][$rid][$perm] = array(
331 '#type' => 'checkbox',
332 '#title' => NULL,
333 '#return_value' => 1,
334 '#default_value' => $form['#node']->node_privacy_byrole['roles'][$rid][$perm]
335 );
336 }
337 reset($perms);
338 }
339 }
340
341 function node_privacy_byrole_theme() {
342 return array(
343 'node_privacy_byrole_node_form' => array(
344 'arguments' => array('form' => NULL)
345 )
346 );
347 }
348
349 /**
350 * Theming permission settings form elements on node edit form.
351 */
352 function theme_node_privacy_byrole_node_form($form) {
353 $roles = user_roles();
354 $header = array(t('Role'), t('View'), t('Edit'), t('Delete'));
355
356 $rows = array();
357 // every row is a role
358 foreach (element_children($form['roles']) as $rid) {
359 $row = array();
360 $row[] = $roles[$rid];
361 // every column is a permission
362 foreach (element_children($form['roles'][$rid]) as $i) {
363 $row[] = drupal_render($form['roles'][$rid][$i]);
364 }
365 $rows[] = $row;
366 }
367
368 return theme('form_element', array('#description' => t('Select which users can view/edit your post based on their role.')), theme('table', $header, $rows));
369 }
370
371 /**
372 * Implementation of hook_node_operations().
373 *
374 * @return array
375 */
376 function node_privacy_byrole_node_operations() {
377 $operations = array();
378
379 foreach (user_roles() as $rid => $role) {
380 $grants = array();
381 $revokes = array();
382 foreach (array('view', 'edit', 'delete') as $priv) {
383 $operations["grant-$rid-$priv"]['label'] = t('Grant !priv for !role', array('!priv' => $priv, '!role' => $role));
384 $operations["grant-$rid-$priv"]['callback'] = 'node_privacy_byrole_node_operations_update';
385 $operations["grant-$rid-$priv"]['callback arguments'] = array(1, $rid, $priv);
386 $operations["revoke-$rid-$priv"]['label'] = t('Revoke !priv for !role', array('!priv' => $priv, '!role' => $role));
387 $operations["revoke-$rid-$priv"]['callback'] = 'node_privacy_byrole_node_operations_update';
388 $operations["revoke-$rid-$priv"]['callback arguments'] = array(0, $rid, $priv);
389 }
390
391 }
392 return $operations;
393 }
394
395 function node_privacy_byrole_node_operations_update($nodes, $perm, $rid, $priv) {
396 foreach ($nodes as $node_to_update) {
397 $node = node_load($node_to_update);
398 $node->node_privacy_byrole['roles'][$rid][$priv] = $perm;
399 node_save($node);
400 }
401 }
402
403 /**
404 * Implementation of hook_action_info().
405 */
406 function node_privacy_byrole_action_info() {
407 return array(
408 'node_privacy_byrole_change_role_action' => array(
409 'description' => t('Change role permissions'),
410 'configurable' => TRUE,
411 'type' => 'node',
412 'hooks' => array(
413 'nodeapi' => array('insert', 'update')
414 )
415 ),
416 'node_privacy_byrole_rolereference_action' => array(
417 'description' => t('Change permissions based on rolereference field'),
418 'type' => 'node',
419 'configurable' => TRUE,
420 'hooks' => array(
421 'nodeapi' => array('insert', 'update')
422 )
423 )
424 );
425 }
426
427 function node_privacy_byrole_change_role_action($node, $context) {
428 /*
429 Mod $node here to have new permissions. It expects:
430 $node->node_privacy_byrole['roles'][$rid]['view']
431 $node->node_privacy_byrole['roles'][$rid]['edit']
432 $node->node_privacy_byrole['roles'][$rid]['delete']
433 Otherwise it will use defaults setup for the content type.
434 */
435 if (isset($context['node_privacy_byrole']['roles'])) {
436 $node->node_privacy_byrole['roles'] = $context['node_privacy_byrole']['roles'];
437 }
438 module_invoke('node_privacy_byrole', 'nodeapi', $node, 'update');
439 }
440
441 function node_privacy_byrole_change_role_action_form($context) {
442 $form = array();
443 $defaults['#node']->node_privacy_byrole = $context['node_privacy_byrole'];
444 $form += node_privacy_byrole_node_form($defaults);
445
446 unset($form['node_privacy_byrole']['#weight']);
447 $form['node_privacy_byrole']['#collapsed'] = FALSE;
448 return $form;
449 }
450
451 function node_privacy_byrole_change_role_action_validate($form, &$form_state) {
452 $errors = array();
453
454 if (empty($form_state['values']['node_privacy_byrole'])) {
455 $errors['node_privacy_byrole'] = t('Please use the supplied form to submit access permissions.');
456 }
457
458 foreach ($errors as $name => $message) {
459 form_set_error($name, $message);
460 }
461
462 return count($errors) == 0;
463 }
464
465 function node_privacy_byrole_change_role_action_submit($form, &$form_state) {
466 return array('node_privacy_byrole' => $form_state['values']['node_privacy_byrole']);
467 }
468
469 function node_privacy_byrole_rolereference_action($node, $context) {
470 /*
471 Mod $node here to have new permissions. It expects:
472 $node->node_privacy_byrole['roles'][$rid]['view']
473 $node->node_privacy_byrole['roles'][$rid]['edit']
474 $node->node_privacy_byrole['roles'][$rid]['delete']
475 Otherwise it will use defaults setup for the content type.
476 */
477 if (isset($context['node_privacy_byrole']['roles'])) {
478 $node->node_privacy_byrole['roles'] = $context['node_privacy_byrole']['roles'];
479 }
480 $node->node_privacy_byrole['author'] = $context['node_author'];
481 foreach ($context['permissions'] as $key => $value) {
482 // The true $values are normally literally 'view', 'edit', 'delete' or 0 for false
483 // which is required for the #default_values when loading the configuration
484 // page for an existing action, but the node access table actually works on
485 // 0 or 1 in the access tables, so convert them here because that's easier
486 // than converting 1 to 'edit' for the #default_value on the form case.
487 $context['permissions'][$key] = empty($context['permissions'][$key]) ? 0 : 1;
488 }
489 foreach (_node_privacy_byrole_walk_role_fields($node->$context['field']) as $rid) {
490 $node->node_privacy_byrole['roles'][$rid] = $context['permissions'];
491 }
492 module_invoke('node_privacy_byrole', 'nodeapi', $node, 'update');
493 }
494
495 function node_privacy_byrole_rolereference_action_form($context) {
496 $form = array();
497
498 $form['#node']->node_privacy_byrole = isset($context['node_privacy_byrole']) ? $context['node_privacy_byrole'] : NULL;
499 node_privacy_byrole_node_form($form);
500
501 unset($form['node_privacy_byrole']['#weight']);
502 $form['node_privacy_byrole']['#title'] = t('Default permissions');
503 $form['new'] = array(
504 '#type' => 'fieldset',
505 '#title' => t('New permission'),
506 '#description' => t('The new permissions to set that will override the defaults. The value of the field is expected to match a numerical role id.'),
507 '#collapsed' => TRUE,
508 '#collapsible' => TRUE
509 );
510
511 $fields = content_fields();
512 $options = array();
513 foreach ($fields as $field) {
514 $options[$field['field_name']] = t($field['widget']['label']) .' ('. $field['field_name'] .')';
515 }
516 asort($options, SORT_LOCALE_STRING);
517 $form['new']['field'] = array(
518 '#title' => t('Field'),
519 '#type' => 'select',
520 '#options' => $options,
521 '#default_value' => isset($context['field']) ? $context['field'] : ''
522 );
523 unset($fields, $field, $options);
524 $form['new']['permissions'] = array(
525 '#title' => t('Permissions'),
526 '#type' => 'checkboxes',
527 '#options' => array(
528 'view' => t('view'),
529 'edit' => t('edit'),
530 'delete' => t('delete')
531 ),
532 '#default_value' => isset($context['permissions']) ? $context['permissions'] : '',
533 '#description' => t('Edit permission implies view. Delete permission implies edit.')
534 );
535 $form['author'] = array(
536 '#type' => 'fieldset',
537 '#title' => t('Node Author'),
538 '#collapsed' => TRUE,
539 '#collapsible' => TRUE
540 );
541 $form['author']['node_author'] = array(
542 '#type' => 'checkboxes',
543 '#options' => array(
544 'view' => t('view'),
545 'edit' => t('edit'),
546 'delete' => t('delete')
547 ),
548 '#default_value' => isset($context['node_author']) ? $context['node_author'] : '',
549 '#description' => t('Edit permission implies view. Delete permission implies edit.')
550 );
551 return $form;
552 }
553
554 function node_privacy_byrole_rolereference_action_validate($form, &$form_state) {
555 $errors = array();
556
557 if (empty($$form_state['values']['node_privacy_byrole']) && empty($form_state['values']['field']) && empty($form_state['values']['permissions']) && empty($form_state['values']['node_author'])) {
558 // this isn't a great validation check because it doesn't allow for setting errors on each form item
559 // but what is there really to validate here?
560 $errors['node_privacy_byrole'] = t('Please use the supplied form to submit access permissions.');
561 }
562
563 foreach ($errors as $name => $message) {
564 form_set_error($name, $message);
565 }
566
567 return count($errors) == 0;
568 }
569
570 function node_privacy_byrole_rolereference_action_submit($form, &$form_state) {
571 $params = array(
572 'node_privacy_byrole' => $form_state['values']['node_privacy_byrole'],
573 'field' => $form_state['values']['field'],
574 'permissions' => $form_state['values']['permissions'],
575 'node_author' => $form_state['values']['node_author']
576 );
577 return $params;
578 }
579
580 /**
581 * Loop recursively through form submissions to find values of rids since we
582 * can't be sure if the field returns a string or a nested array like in a multiple select.
583 */
584 function _node_privacy_byrole_walk_role_fields($form) {
585 if (!is_array($form)) {
586 return array($form);
587 }
588 else {
589 $rids = array();
590 foreach (array_keys($form) as $getvar) {
591 if (element_child($getvar) && is_array($form) && !is_null($form[$getvar])) {
592 $returned = _node_privacy_byrole_walk_role_fields($form[$getvar]);
593 $rids = array_merge($rids, $returned);
594 }
595 else {
596 $rids[] = $getvar;
597 }
598 }
599 }
600 return $rids;
601 }

  ViewVC Help
Powered by ViewVC 1.1.2