Projet

Général

Profil

Paste
Télécharger (42,2 ko) Statistiques
| Branche: | Révision:

root / htmltest / sites / all / modules / nodeaccess / nodeaccess.module @ 4543c6c7

1
<?php
2

    
3
/**
4
 * @file
5
 * Provide per node access control
6
 */
7

    
8
/**
9
 * Implements hook_help().
10
 */
11
function nodeaccess_help($path, $arg) {
12
  switch ($path) {
13
    case 'node/%/grant':
14
      return '<small>' . t('You can set grants per users. Enter a name or a partial name in the box and click Search or press return. You need to check the Keep? checkbox if you want to keep the user for granting. Note that user grants are additional to those coming from roles.') . '</small>';
15
  }
16
}
17

    
18
/**
19
 * Implements hook_menu().
20
 */
21
function nodeaccess_menu() {
22
  $items['admin/config/people/nodeaccess'] = array(
23
    'title' => 'Nodeaccess',
24
    'description' => 'Change default settings for the Nodeaccess module.',
25
    'page callback' => 'nodeaccess_admin',
26
    'access arguments' => array('administer nodeaccess'),
27
  );
28
  $items['node/%node/grant'] = array(
29
    'title' => 'Grant',
30
    'page callback' => 'nodeaccess_grants',
31
    'page arguments' => array(1),
32
    'access callback' => 'nodeaccess_access',
33
    'access arguments' => array('grant', 1),
34
    'weight' => 5,
35
    'type' => MENU_LOCAL_TASK,
36
  );
37
  return $items;
38
}
39

    
40
/**
41
 * Implements hook_admin_paths().
42
 */
43
function nodeaccess_admin_paths() {
44
  $paths = array(
45
    'node/*/grant' => TRUE,
46
    'admin/config/people/nodeaccess' => TRUE,
47
  );
48
  return $paths;
49
}
50

    
51
/**
52
 * Implements hook_permission().
53
 */
54
function nodeaccess_permission() {
55

    
56
  return array(
57
    'administer nodeaccess' => array(
58
      'title' => t('Administer Nodeaccess'),
59
    ),
60
    'grant node permissions' => array(
61
      'title' => t('Grant Node Permissions'),
62
    ),
63
    'grant editable node permissions' => array(
64
      'title' => t('Grant node edit permissions'),
65
    ),
66
    'grant deletable node permissions' => array(
67
      'title' => t('Grant node delete permissions'),
68
    ),
69
    'grant own node permissions' => array(
70
      'title' => t('Grant own node permissions'),
71
    ),
72
  );
73
}
74

    
75
/**
76
 * Implements hook_node_access().
77
 */
78
function nodeaccess_node_access($node, $op, $account) {
79
  switch ($op) {
80
    case 'update':
81
    case 'delete':
82
      if (!isset($account->uid)) {
83
        global $user;
84
        $account = $user;
85
      }
86
      // If the node belongs to a deleted user.
87
      if ($account->uid == 0 && $node->uid == 0) {
88
        // We check if the role has particular access to this node.
89
        $grants = _nodeaccess_get_grants($node);
90
        // If anonymous has rights to this node, we allow them.
91
        if (($grants['rid'][1]['grant_update'] && $op == 'update') ||
92
            ($grants['rid'][1]['grant_delete'] && $op == 'delete')) {
93
          return NODE_ACCESS_ALLOW;
94
        }
95
        return NODE_ACCESS_DENY;
96
      }
97
      break;
98

    
99
    case 'view':
100
      if (!isset($account->uid)) {
101
        global $user;
102
        $account = $user;
103
      }
104
      // If the node is not published. We check other permissions.
105
      if (!$node->status) {
106
        // If the current user is the author and not anonymous.
107
        if ($node->uid == $account->uid && $account->uid > 0) {
108
          // We check to see if they have access to view own unpublished.
109
          if (user_access('view own unpublished content') || user_access('bypass node access')) {
110
            return NODE_ACCESS_ALLOW;
111
          }
112
        }
113
        elseif (user_access('bypass node access')) {
114
          return NODE_ACCESS_ALLOW;
115
        }
116
        return NODE_ACCESS_IGNORE;
117
      }
118
      break;
119

    
120
  }
121
}
122

    
123
/**
124
 * Determine access to Grant tab.
125
 */
126
function nodeaccess_access($op, $node, $account = NULL) {
127
  global $user;
128
  if (!$node) {
129
    return FALSE;
130
  }
131

    
132
  // Apparently D7 no longer defaults to admin getting anything?
133
  if (user_access('administer nodeaccess')) {
134
    return TRUE;
135
  }
136

    
137
  // If no user object is supplied, the access check is for the current user.
138
  if (empty($account)) {
139
    $account = $user;
140
  }
141
  $allowed_types = variable_get('nodeaccess-types', array());
142
  if ($op == 'grant') {
143
    if ($node->nid && isset($allowed_types[$node->type]) &&
144
        (user_access('grant node permissions', $account) ||
145
         (user_access('grant editable node permissions', $account) && node_access('update', $node, $account)) ||
146
         (user_access('grant deletable node permissions', $account) && node_access('delete', $node, $account)) ||
147
         (user_access('grant own node permissions', $account) && ($account->uid == $node->uid)))) {
148
      return TRUE;
149
    }
150
  }
151
  return FALSE;
152
}
153

    
154
/**
155
 * Implements hook_theme().
156
 */
157
function nodeaccess_theme($existing, $type, $theme, $path) {
158
  return array(
159
    'nodeaccess_admin_form_roles' => array(
160
      'render element'  => 'role',
161
    ),
162
    'nodeaccess_admin_form_types' => array(
163
      'render element'  => 'form',
164
    ),
165
    'nodeaccess_grants_form'  => array(
166
      'render element'  => 'form',
167
    ),
168
  );
169
}
170

    
171
/**
172
 * Menu callback. Draws the admin page.
173
 */
174
function nodeaccess_admin() {
175
  return drupal_get_form('nodeaccess_admin_form');
176
}
177

    
178
/**
179
 * Menu callback. Draws the admin page.
180
 */
181
function nodeaccess_admin_form($form, $form_state) {
182
  // Set defaults from variable_get.
183
  $show = variable_get('nodeaccess-types', array());
184
  $roles = nodeaccess_get_role_aliases();
185
  $allowed_roles = variable_get('nodeaccess-roles', array());
186
  $allowed_grants = variable_get('nodeaccess-grants', array());
187

    
188
  $form['priority'] = array(
189
    '#type' => 'checkbox',
190
    '#title' => t('Give node grants priority'),
191
    '#default_value' => variable_get('nodeaccess-priority', 0),
192
    '#description' => '<small>' . t('If you are only using this access control module, you can safely ignore this. If you are using multiple access control modules, and you want the grants given on individual nodes to override any grants given by other modules, you should check this box.') . '</small>',
193
  );
194

    
195
  // Select whether to preserve hidden grants.
196
  $form['preserve'] = array(
197
    '#type' => 'checkbox',
198
    '#title' => t('Preserve hidden grants'),
199
    '#default_value' => variable_get('nodeaccess-preserve', 1),
200
    '#description' => '<small>' . t('If you check this box, any hidden grants are preserved when you save grants. Otherwise all grants users are not allowed to view or edit are revoked on save.') . '</small>',
201
  );
202

    
203
  // Select permissions you want to allow users to view and edit.
204
  $form['grant'] = array(
205
    '#type' => 'fieldset',
206
    '#collapsible' => TRUE,
207
    '#collapsed' => TRUE,
208
    '#title' => t('Allowed Grants'),
209
    '#tree' => TRUE,
210
    '#description' => '<small>' . t('The selected grants will be listed on individual node grants. If you wish for certain grants to be hidden from users on the node grants tab, make sure they are not selected here.') . '</small>',
211
  );
212
  $form['grant']['view'] = array(
213
    '#type' => 'checkbox',
214
    '#title' => t('View'),
215
    '#default_value' => $allowed_grants['view'],
216
  );
217
  $form['grant']['edit'] = array(
218
    '#type' => 'checkbox',
219
    '#title' => t('Edit'),
220
    '#default_value' => $allowed_grants['edit'],
221
  );
222
  $form['grant']['delete'] = array(
223
    '#type' => 'checkbox',
224
    '#title' => t('Delete'),
225
    '#default_value' => $allowed_grants['delete'],
226
  );
227

    
228
  // Select roles the permissions of which you want to allow users to
229
  // view and edit, and the aliases and weights of those roles.
230
  $form['role'] = array(
231
    '#type' => 'fieldset',
232
    '#collapsible' => TRUE,
233
    '#collapsed' => TRUE,
234
    '#title' => t('Allowed Roles'),
235
    '#tree' => TRUE,
236
    '#theme' => 'nodeaccess_admin_form_roles',
237
    '#description' => '<small>' . t('The selected roles will be listed on individual node grants. If you wish for certain roles to be hidden from users on the node grants tab, make sure they are not selected here. You may also provide an alias for each role to be displayed to the user and a weight to order them by. This is useful if your roles have machine-readable names not intended for human users.') . '</small>',
238
  );
239

    
240
  foreach ($roles as $id => $role) {
241
    // Catch NULL values.
242
    if (!$role['alias']) {
243
      $role['alias'] = '';
244
    }
245
    if (!$role['weight']) {
246
      $role['weight'] = 0;
247
    }
248
    // $form['role'][$id] = array('#tree' => TRUE);
249
    $form['role'][$id]['name'] = array(
250
      '#type' => 'hidden',
251
      '#value' => $role['name'],
252
    );
253
    $form['role'][$id]['allow'] = array(
254
      '#type' => 'checkbox',
255
      '#title' => check_plain($role['name']),
256
      '#default_value' => isset($allowed_roles[$id]) ? $allowed_roles[$id] : 0,
257
    );
258
    $form['role'][$id]['alias'] = array(
259
      '#type' => 'textfield',
260
      '#default_value' => $role['alias'],
261
      '#size' => 50,
262
      '#maxlength' => 50,
263
    );
264
    $form['role'][$id]['weight'] = array(
265
      '#type' => 'weight',
266
      '#default_value' => $role['weight'],
267
      '#delta' => 10,
268
    );
269
  }
270

    
271
  // Generate fieldsets for each node type.
272
  foreach (node_type_get_types() as $type => $bundle) {
273
    $form['nodeaccess'][$type] = array(
274
      '#type' => 'fieldset',
275
      '#collapsible' => TRUE,
276
      '#collapsed' => TRUE,
277
      '#title' => check_plain($bundle->name),
278
      '#tree' => TRUE,
279
      '#theme' => 'nodeaccess_admin_form_types',
280
    );
281

    
282
    $form['nodeaccess'][$type]['show'] = array(
283
      '#type' => 'checkbox',
284
      '#title' => t('Show grant tab for this node type'),
285
      '#default_value' => isset($show[$type]) ? $show[$type] : 0,
286
    );
287

    
288
    // Set default author permissions for node type.
289
    $author_prefs = variable_get('nodeaccess_authors', array());
290
    $form['nodeaccess'][$type]['author']['grant_view'] = array(
291
      '#type' => 'checkbox',
292
      '#default_value' => $author_prefs[$type]['grant_view'],
293
    );
294
    $form['nodeaccess'][$type]['author']['grant_update'] = array(
295
      '#type' => 'checkbox',
296
      '#default_value' => $author_prefs[$type]['grant_update'],
297
    );
298
    $form['nodeaccess'][$type]['author']['grant_delete'] = array(
299
      '#type' => 'checkbox',
300
      '#default_value' => $author_prefs[$type]['grant_delete'],
301
    );
302

    
303
    $perms = variable_get('nodeaccess_' . $type, array());
304
    foreach ($perms as $perm) {
305
      $opts[$perm['gid']] = $perm;
306
    }
307

    
308
    // Set default role permissions for node type.
309
    foreach (user_roles() as $id => $role) {
310
      $form['nodeaccess'][$type]['roles'][$id]['name'] = array('#markup' => $role);
311
      $form['nodeaccess'][$type]['roles'][$id]['grant_view'] = array(
312
        '#type' => 'checkbox',
313
        '#default_value' => isset($opts[$id]['grant_view']) ? $opts[$id]['grant_view'] : 0,
314
      );
315
      $form['nodeaccess'][$type]['roles'][$id]['grant_update'] = array(
316
        '#type' => 'checkbox',
317
        '#default_value' => isset($opts[$id]['grant_update']) ? $opts[$id]['grant_update'] : 0,
318
      );
319
      $form['nodeaccess'][$type]['roles'][$id]['grant_delete'] = array(
320
        '#type' => 'checkbox',
321
        '#default_value' => isset($opts[$id]['grant_delete']) ? $opts[$id]['grant_delete'] : 0,
322
      );
323
    }
324

    
325
    // Set the default permissions if userreference exists and is enabled on
326
    // the content type.
327
    if (module_exists('user_reference')) {
328
      $bundle = field_extract_bundle('node', $bundle);
329
      $fields = field_info_instances('node', $bundle);
330
      $user_reference_perms = variable_get('nodeaccess_' . $type . '_user_reference', array());
331

    
332
      $field_types = field_info_field_types();
333

    
334
      foreach ($fields as $field) {
335
        $field = field_info_field($field['field_name']);
336
        if ($field['type'] == 'user_reference') {
337
          $enabled = isset($user_reference_perms[$field['field_name']]['enabled']) ? $user_reference_perms[$field['field_name']]['enabled'] : 0;
338
          $view = isset($user_reference_perms[$field['field_name']]['grant_view']) ? $user_reference_perms[$field['field_name']]['grant_view'] : 0;
339
          $update = isset($user_reference_perms[$field['field_name']]['grant_update']) ? $user_reference_perms[$field['field_name']]['grant_update'] : 0;
340
          $delete = isset($user_reference_perms[$field['field_name']]['grant_delete']) ? $user_reference_perms[$field['field_name']]['grant_delete'] : 0;
341

    
342
          $form['nodeaccess'][$type]['user_reference'][$field['field_name']]['name'] = array('#value' => t($field_types[$field['type']]['label']));
343
          $form['nodeaccess'][$type]['user_reference'][$field['field_name']]['enabled'] = array(
344
            '#type' => 'checkbox',
345
            '#default_value' => $enabled,
346
          );
347
          $form['nodeaccess'][$type]['user_reference'][$field['field_name']]['grant_view'] = array(
348
            '#type' => 'checkbox',
349
            '#default_value' => $view,
350
          );
351
          $form['nodeaccess'][$type]['user_reference'][$field['field_name']]['grant_update'] = array(
352
            '#type' => 'checkbox',
353
            '#default_value' => $update,
354
          );
355
          $form['nodeaccess'][$type]['user_reference'][$field['field_name']]['grant_delete'] = array(
356
            '#type' => 'checkbox',
357
            '#default_value' => $delete,
358
          );
359
        }
360
      }
361
    }
362
  }
363
  $form['submit'] = array(
364
    '#type' => 'submit',
365
    '#value' => t('Save Grants'),
366
  );
367
  return $form;
368
}
369

    
370
/**
371
 * Submit function for nodeaccess_admin_form.
372
 */
373
function nodeaccess_admin_form_submit($form, $form_state) {
374
  $form_values = $form_state['values'];
375
  // Save priority.
376
  variable_set('nodeaccess-priority', $form_values['priority']);
377
  // Save preserve.
378
  variable_set('nodeaccess-preserve', $form_values['preserve']);
379
  // Save allowed grants.
380
  foreach ($form_values['grant'] as $id => $val) {
381
    $allowed_grants[$id] = $val;
382
  }
383
  variable_set('nodeaccess-grants', $allowed_grants);
384
  // Save allowed roles, role aliases and weights.
385
  $alias_prefs = array();
386
  $allowed_roles = array();
387
  foreach ($form_values['role'] as $id => $val) {
388
    $allowed_roles[$id] = $val['allow'];
389
    // Save alias and weight only for allowed roles.
390
    if ($val['allow']) {
391
      // If alias is empty, default to role name.
392
      if ($val['alias']) {
393
        $alias_prefs[$id]['name'] = $val['alias'];
394
      }
395
      else {
396
        $alias_prefs[$id]['name'] = $val['name'];
397
      }
398
      $alias_prefs[$id]['weight'] = $val['weight'];
399
    }
400
  }
401
  variable_set('nodeaccess-roles', $allowed_roles);
402
  nodeaccess_save_role_aliases($alias_prefs);
403
  // Save author and role permissions for each node type.
404
  $author_prefs = array();
405
  foreach (node_type_get_types() as $type => $name) {
406
    $grants = array();
407
    foreach ($form_values[$type]['roles'] as $role => $val) {
408
      $grants[] = array(
409
        'gid' => $role,
410
        'realm' => 'nodeaccess_rid',
411
        'grant_view' => $val['grant_view'],
412
        'grant_update' => $val['grant_update'],
413
        'grant_delete' => $val['grant_delete'],
414
      );
415
    }
416
    variable_set('nodeaccess_' . $type, $grants);
417
    if ($form_values[$type]['show']) {
418
      $allowed_types[$type] = 1;
419
    }
420
    else {
421
      $allowed_types[$type] = 0;
422
    }
423
    $author_prefs[$type] = $form_values[$type]['author'];
424
    // Also save userreference default permissions if enabled.
425
    if (module_exists('user_reference') && isset($form_values[$type]['user_reference'])) {
426
      $user_reference_grants = array();
427
      foreach ($form_values[$type]['user_reference'] as $user_reference_field => $val) {
428
        $user_reference_grants[$user_reference_field] = array(
429
          'gid' => 'nodeaccess_uid',
430
          'enabled' => $val['enabled'],
431
          'grant_view' => $val['grant_view'],
432
          'grant_update' => $val['grant_update'],
433
          'grant_delete' => $val['grant_delete'],
434
        );
435
      }
436
      variable_set('nodeaccess_' . $type . '_user_reference', $user_reference_grants);
437
    }
438
  }
439
  variable_set('nodeaccess_authors', $author_prefs);
440
  // Save allowed node types.
441
  variable_set('nodeaccess-types', $allowed_types);
442
  node_access_needs_rebuild(TRUE);
443
  drupal_set_message(t('Grants saved.'));
444
}
445

    
446
/**
447
 * Theme functions for nodeaccess_admin_form.
448
 */
449
function theme_nodeaccess_admin_form_roles($variables) {
450
  $output = '';
451
  $roles = $variables['role'];
452
  $header = array(t('Allow Role'), t('Alias'), t('Weight'));
453

    
454
  foreach ($roles as $role) {
455
    if (!is_array($role) || !isset($role['allow'])) {
456
      continue;
457
    }
458
    $row = array();
459
    $row[] = drupal_render($role['allow']);
460
    $row[] = drupal_render($role['alias']);
461
    $row[] = drupal_render_children($role['weight']);
462
    $rows[] = $row;
463
  }
464
  $output .= theme('table', array('header' => $header, 'rows' => $rows));
465

    
466
  return $output;
467
}
468

    
469
/**
470
 * Output the grant table.
471
 * @todo Please document this function.
472
 * @see http://drupal.org/node/1354
473
 */
474
function theme_nodeaccess_admin_form_types($variables) {
475
  // @todo Number of parameters does not match hook_theme.
476
  $form = $variables['form'];
477
  $output = drupal_render($form['show']);
478
  $roles = element_children($form['roles']);
479
  $header = array(t('Role'), t('View'), t('Edit'), t('Delete'));
480
  foreach ($roles as $role) {
481
    $row = array();
482
    $row[] = drupal_render($form['roles'][$role]['name']);
483
    $row[] = drupal_render($form['roles'][$role]['grant_view']);
484
    $row[] = drupal_render($form['roles'][$role]['grant_update']);
485
    $row[] = drupal_render($form['roles'][$role]['grant_delete']);
486
    $rows[] = $row;
487
  }
488
  $output .= theme('table', array('header' => $header, 'rows' => $rows));
489
  $header = array(t('Author Settings'), t('View'), t('Edit'), t('Delete'));
490
  $row = array();
491
  $row[] = t('Node author');
492
  $row[] = drupal_render($form['author']['grant_view']);
493
  $row[] = drupal_render($form['author']['grant_update']);
494
  $row[] = drupal_render($form['author']['grant_delete']);
495

    
496
  $output .= theme('table', array('header' => $header, 'rows' => array($row)));
497

    
498
  $output .= '<small>' . t('The settings selected for the node author will define what permissions the node author has. This cannot be changed on individual node grants.') . '</small>';
499

    
500
  if (module_exists('user_reference') && isset($form['user_reference'])) {
501
    $user_reference_fields = element_children($form['user_reference']);
502
    $header = array(t('User Reference Field'),
503
      t('Enable this field'),
504
      t('View'),
505
      t('Edit'),
506
      t('Delete'),
507
    );
508
    $rows = array();
509
    foreach ($user_reference_fields as $user_reference_field) {
510
      $row = array();
511

    
512
      $row[] = $form['user_reference'][$user_reference_field]['name']['#value'];
513
      $row[] = drupal_render($form['user_reference'][$user_reference_field]['enabled']);
514
      $row[] = drupal_render($form['user_reference'][$user_reference_field]['grant_view']);
515
      $row[] = drupal_render($form['user_reference'][$user_reference_field]['grant_update']);
516
      $row[] = drupal_render_children($form['user_reference'][$user_reference_field]['grant_delete']);
517
      $rows[] = $row;
518
    }
519
    $output .= theme('table', array(
520
        'header' => $header,
521
        'rows' => $rows,
522
      ));
523
    $output .= '<small>' . t('If enabled, the value of the user reference field will be granted the associated permissions. If a user changes the value of the user reference field on a node, the associated user will be modified in the node-specific access table.') . '</small>';
524
  }
525
  return $output;
526
}
527

    
528
/**
529
 * Menu callback. Draws the grant tab.
530
 */
531
function nodeaccess_grants($node) {
532
  return drupal_get_form('nodeaccess_grants_form', $node);
533
}
534

    
535
/**
536
 * Menu callback. Draws the grant tab.
537
 */
538
function nodeaccess_grants_form($form, &$form_state, $node) {
539
  $form_values = &$form_state['values'];
540
  if (!$form_values) {
541
    $form_values = array();
542
    // Load all roles.
543
    $result = db_query("SELECT r.rid, nra.name, na.grant_view, na.grant_update, na.grant_delete FROM {role} r LEFT JOIN {nodeaccess_role_alias} nra ON r.rid = nra.rid LEFT JOIN {node_access} na ON r.rid = na.gid AND na.realm = :realm AND na.nid = :nid ORDER BY nra.weight, nra.name", array(':realm' => 'nodeaccess_rid', ':nid' => $node->nid));
544
    foreach ($result as $grant) {
545
      $form_values['rid'][$grant->rid] = array(
546
        'name' => $grant->name,
547
        'grant_view' => (boolean) $grant->grant_view,
548
        'grant_update' => (boolean) $grant->grant_update,
549
        'grant_delete' => (boolean) $grant->grant_delete,
550
      );
551
    }
552
    // Load users from node_access.
553
    $results = db_query("SELECT uid, name, grant_view, grant_update, grant_delete FROM {node_access} LEFT JOIN {users} ON uid = gid WHERE nid = :nid AND realm = :realm ORDER BY name", array(
554
        ':nid' => $node->nid,
555
        ':realm' => 'nodeaccess_uid',
556
      ));
557
    foreach ($results as $account) {
558
      $form_values['uid'][$account->uid] = array(
559
        'name' => $account->name,
560
        'keep' => 1,
561
        'grant_view' => $account->grant_view,
562
        'grant_update' => $account->grant_update,
563
        'grant_delete' => $account->grant_delete,
564
      );
565
    }
566
  }
567
  else {
568
    // Perform search.
569
    if ($form_values['keys']) {
570
      // @todo rewrite
571
      $params = array();
572
      $sql = "SELECT uid, name FROM {users} WHERE name LIKE :name";
573
      $name = preg_replace('!\*+!', '%', $form_values['keys']);
574
      $params[':name'] = $name;
575
      $users = '';
576
      if (isset($form_values['uid']) && is_array($form_values['uid'])) {
577
        $sql .= ' AND uid NOT IN (:uid)';
578
        $users = implode(',', array_keys($form_values['uid']));
579
        $params[':uid'] = $users;
580
      }
581

    
582
      $result = db_query($sql, $params);
583
      foreach ($result as $account) {
584

    
585
        $form_values['uid'][$account->uid] = array(
586
          'name' => $account->name,
587
          'keep' => 0,
588
        );
589
      }
590
    }
591
    // Calculate default grants for found users.
592
    // rewrite
593
    if (isset($form_values['uid']) && is_array($form_values['uid'])) {
594
      foreach (array_keys($form_values['uid']) as $uid) {
595
        if (!$form_values['uid'][$uid]['keep']) {
596
          foreach (array('grant_view', 'grant_update', 'grant_delete') as $grant_type) {
597
            $form_values['uid'][$uid][$grant_type] = db_query_range("SELECT count(*) FROM {node_access} na LEFT JOIN {users_roles} r ON na.gid = r.rid WHERE nid = :nid AND realm = :realm AND uid = :uid AND :type = 1",
598
              0, 1,
599
              array(
600
                ':nid' => $node->nid,
601
                ':realm' => 'nodeaccess_rid',
602
                ':uid' => $uid,
603
                ':type' => $grant_type,
604
              ))->fetchField() ||
605
              db_query_range("SELECT count(*) FROM {node_access} na WHERE nid = :nid AND realm = :realm AND gid = :gid AND :type = 1",
606
                0, 1,
607
                array(
608
                  ':nid' => $node->nid,
609
                  ':realm' => 'nodeaccess_uid',
610
                  ':gid' => $uid,
611
                  ':type' => $grant_type,
612
                )
613
                )->fetchField();
614
          }
615
          $form_values['uid'][$uid]['keep'] = TRUE;
616
        }
617
      }
618
    }
619
  }
620
  if (!isset($form_values['rid'])) {
621
    $form_values['rid'] = array();
622
  }
623

    
624
  if (!isset($form_values['uid'])) {
625
    $form_values['uid'] = array();
626
  }
627

    
628
  $roles = $form_values['rid'];
629
  $users = $form_values['uid'];
630

    
631
  $form['nid'] = array(
632
    '#type' => 'hidden',
633
    '#value' => $node->nid,
634
  );
635

    
636
  $allowed_roles = variable_get('nodeaccess-roles', array());
637
  $allowed_grants = variable_get('nodeaccess-grants', array());
638
  // If $preserve is TRUE, the fields the user is not allowed to view or
639
  // edit are included in the form as hidden fields to preserve them.
640
  $preserve = variable_get('nodeaccess-preserve', 1);
641

    
642
  // Roles table.
643
  if (is_array($roles)) {
644
    $form['rid'] = array('#tree' => TRUE);
645
    foreach ($roles as $key => $field) {
646
      if (isset($allowed_roles[$key]) && $allowed_roles[$key]) {
647
          $form['rid'][$key]['name'] = array(
648
            '#type' => 'hidden',
649
            '#value' => $field['name'],
650
          );
651
          if ($allowed_grants['view']) {
652
            $form['rid'][$key]['grant_view'] = array(
653
              '#type' => 'checkbox',
654
              '#default_value' => $field['grant_view'],
655
            );
656
          }
657
          elseif ($preserve) {
658
            $form['rid'][$key]['grant_view'] = array(
659
              '#type' => 'hidden',
660
              '#value' => $field['grant_view'],
661
            );
662
          }
663
          if ($allowed_grants['edit']) {
664
            $form['rid'][$key]['grant_update'] = array(
665
              '#type' => 'checkbox',
666
              '#default_value' => $field['grant_update'],
667
            );
668
          }
669
          elseif ($preserve) {
670
            $form['rid'][$key]['grant_update'] = array(
671
              '#type' => 'hidden',
672
              '#value' => $field['grant_update'],
673
            );
674
          }
675
          if ($allowed_grants['delete']) {
676
            $form['rid'][$key]['grant_delete'] = array(
677
              '#type' => 'checkbox',
678
              '#default_value' => $field['grant_delete'],
679
            );
680
          }
681
          elseif ($preserve) {
682
            $form['rid'][$key]['grant_delete'] = array(
683
              '#type' => 'hidden',
684
              '#value' => $field['grant_delete'],
685
            );
686
          }
687
      }
688
      elseif ($preserve) {
689
        $form['rid'][$key]['name'] = array(
690
          '#type' => 'hidden',
691
          '#value' => $field['name'],
692
        );
693
        $form['rid'][$key]['grant_view'] = array(
694
          '#type' => 'hidden',
695
          '#value' => $field['grant_view'],
696
        );
697
        $form['rid'][$key]['grant_update'] = array(
698
          '#type' => 'hidden',
699
          '#value' => $field['grant_update'],
700
        );
701
        $form['rid'][$key]['grant_delete'] = array(
702
          '#type' => 'hidden',
703
          '#value' => $field['grant_delete'],
704
        );
705
      }
706
    }
707
  }
708

    
709
  // Users table.
710
  if (is_array($users)) {
711
    $form['uid'] = array('#tree' => TRUE);
712
    foreach ($users as $key => $field) {
713
      $form['uid'][$key]['name'] = array(
714
        '#type' => 'hidden',
715
        '#value' => $field['name'],
716
      );
717
      $form['uid'][$key]['keep'] = array(
718
        '#type' => 'checkbox',
719
        '#default_value' => $field['keep'],
720
      );
721
      if ($allowed_grants['view']) {
722
        $form['uid'][$key]['grant_view'] = array(
723
          '#type' => 'checkbox',
724
          '#default_value' => $field['grant_view'],
725
        );
726
      }
727
      elseif ($preserve) {
728
        $form['uid'][$key]['grant_view'] = array(
729
          '#type' => 'hidden',
730
          '#value' => $field['grant_view'],
731
        );
732
      }
733
      if ($allowed_grants['edit']) {
734
        $form['uid'][$key]['grant_update'] = array(
735
          '#type' => 'checkbox',
736
          '#default_value' => $field['grant_update'],
737
        );
738
      }
739
      elseif ($preserve) {
740
        $form['uid'][$key]['grant_update'] = array(
741
          '#type' => 'hidden',
742
          '#value' => $field['grant_update'],
743
        );
744
      }
745
      if ($allowed_grants['delete']) {
746
        $form['uid'][$key]['grant_delete'] = array(
747
          '#type' => 'checkbox',
748
          '#default_value' => $field['grant_delete'],
749
        );
750
      }
751
      elseif ($preserve) {
752
        $form['uid'][$key]['grant_delete'] = array(
753
          '#type' => 'hidden',
754
          '#value' => $field['grant_delete'],
755
        );
756
      }
757
    }
758
  }
759

    
760
  // Autocomplete returns errors if users don't have access to profiles.
761
  if (user_access('access user profiles')) {
762
    $form['keys'] = array(
763
      '#type' => 'textfield',
764
      '#default_value' => isset($form_values['keys']) ? $form_values['keys'] : '',
765
      '#size' => 40,
766
      '#autocomplete_path' => 'user/autocomplete',
767
    );
768
  }
769
  else {
770
    $form['keys'] = array(
771
      '#type' => 'textfield',
772
      '#default_value' => isset($form_values['keys'])? $form_values['keys'] : '',
773
      '#size' => 40,
774
    );
775
  }
776

    
777
  $form['search'] = array(
778
    '#type' => 'submit',
779
    '#value' => t('Search'),
780
  );
781

    
782
  $form['submit'] = array(
783
    '#type' => 'submit',
784
    '#value' => t('Save Grants'),
785
  );
786
  return $form;
787
}
788

    
789
/**
790
 * Validate function for nodeaccess_grants_form.
791
 */
792
function nodeaccess_grants_form_validate($form, $form_state) {
793
  $form_values = &$form_state['values'];
794
  // Delete unkept users.
795
  if (isset($form_values['uid']) && is_array($form_values['uid'])) {
796
    foreach ($form_values['uid'] as $uid => $row) {
797
      if (!$row['keep']) {
798
        unset($form_values['uid'][$uid]);
799
      }
800
    }
801
  }
802
  if (!isset($form_values['uid'])) {
803
    unset($form_values['uid']);
804
  }
805

    
806
}
807

    
808
/**
809
 * Submit function for nodeaccess_grants_form.
810
 */
811
function nodeaccess_grants_form_submit($form, &$form_state) {
812

    
813
  if ($form_state['clicked_button']['#id'] == 'edit-search') {
814
    $form_state['rebuild'] = TRUE;
815
    $form_state['storage']['values'] = $form_state['values'];
816
  }
817
  else {
818
    unset($form_state['rebuild']);
819
    _nodeaccess_grants_form_submit($form, $form_state);
820
    drupal_set_message(t('Grants saved.'));
821
  }
822
}
823

    
824
/**
825
 * Private function to submit the per-node grants table.
826
 */
827
function _nodeaccess_grants_form_submit($form, $form_state) {
828
  $form_values = &$form_state['values'];
829
  global $user;
830
  $grants = array();
831
  $nid = $form_values['nid'];
832
  $node = node_load($nid);
833
  foreach (array('uid', 'rid') as $type) {
834
    $realm = 'nodeaccess_' . $type;
835
    if (isset($form_values[$type]) && is_array($form_values[$type])) {
836
      foreach ($form_values[$type] as $gid => $line) {
837
        $grant = array(
838
          'gid' => $gid,
839
          'realm' => $realm,
840
          'grant_view' => empty($line['grant_view']) ? 0 : $line['grant_view'],
841
          'grant_update' => empty($line['grant_update']) ? 0 : $line['grant_update'],
842
          'grant_delete' => empty($line['grant_delete']) ? 0 : $line['grant_delete'],
843
        );
844
        if ($grant['grant_view'] || $grant['grant_update'] || $grant['grant_delete']) {
845
          $grants[] = $grant;
846
        }
847
      }
848
    }
849
    node_access_write_grants($node, $grants, $realm);
850
  }
851

    
852
  // Save role and user grants to our own table.
853
  db_delete('nodeaccess')
854
  ->condition('nid', $nid)
855
  ->execute();
856
  foreach ($grants as $grant) {
857
    $id = db_insert('nodeaccess')
858
        ->fields(array(
859
          'nid' => $nid,
860
          'gid' => $grant['gid'],
861
          'realm' => $grant['realm'],
862
          'grant_view' => $grant['grant_view'],
863
          'grant_update' => $grant['grant_update'],
864
          'grant_delete' => $grant['grant_delete'],
865
        ))
866
    ->execute();
867
  }
868
}
869

    
870
/**
871
 * Theme function for nodeaccess_grants_form.
872
 */
873
function theme_nodeaccess_grants_form($variables) {
874
  $output = '';
875
  // @todo: Number of parameters in this theme funcion does not match number
876
  // of parameters found in hook_theme.
877
  $form = $variables['form'];
878
  $allowed_roles = variable_get('nodeaccess-roles', array());
879
  $allowed_grants = variable_get('nodeaccess-grants', array());
880
  // Retrieve role names for columns.
881
  $role_names = user_roles();
882
  // Roles table.
883
  $roles = element_children($form['rid']);
884

    
885
  if (count($roles) && count($allowed_roles)) {
886
    $header = array();
887
    $header[] = t('Role');
888
    if ($allowed_grants['view']) {
889
      $header[] = t('View');
890
    }
891
    if ($allowed_grants['edit']) {
892
      $header[] = t('Edit');
893
    }
894
    if ($allowed_grants['delete']) {
895
      $header[] = t('Delete');
896
    }
897
    foreach ($roles as $key) {
898
      if (isset($allowed_roles[$key]) && $allowed_roles[$key]) {
899
        $row = array();
900
        $row[] = $role_names[$key] . drupal_render($form['rid'][$key]['name']);
901
        if ($allowed_grants['view']) {
902
          $row[] = drupal_render($form['rid'][$key]['grant_view']);
903
        }
904
        if ($allowed_grants['edit']) {
905
          $row[] = drupal_render($form['rid'][$key]['grant_update']);
906
        }
907
        if ($allowed_grants['delete']) {
908
          $row[] = drupal_render($form['rid'][$key]['grant_delete']);
909
        }
910
        $rows[] = $row;
911
      }
912
    }
913
    $output .= theme('table', array('header' => $header, 'rows' => $rows));
914
  }
915

    
916
  // Search form.
917
  $output .= '<p><div class="search-form">';
918
  $output .= '<strong>' . t('Enter names to search for users:') . '</strong>';
919
  $output .= '<div class="container-inline">';
920
  $output .= drupal_render($form['keys']);
921
  $output .= drupal_render($form['search']);
922
  $output .= '</div></div></p>';
923

    
924
  // Users table.
925
  unset($rows);
926
  $users = element_children($form['uid']);
927
  if (count($users) > 0) {
928
    $header = array();
929
    $rows = array();
930
    $header[] = t('User');
931
    $header[] = t('Keep?');
932
    if ($allowed_grants['view']) {
933
      $header[] = t('View');
934
    }
935
    if ($allowed_grants['edit']) {
936
      $header[] = t('Edit');
937
    }
938
    if ($allowed_grants['delete']) {
939
      $header[] = t('Delete');
940
    }
941
    foreach ($users as $key) {
942
      $row = array();
943
      $row[] = $form['uid'][$key]['name']['#value'];
944
      $row[] = drupal_render($form['uid'][$key]['keep']);
945
      if ($allowed_grants['view']) {
946
        $row[] = drupal_render($form['uid'][$key]['grant_view']);
947
      }
948
      if ($allowed_grants['edit']) {
949
        $row[] = drupal_render($form['uid'][$key]['grant_update']);
950
      }
951
      if ($allowed_grants['delete']) {
952
        $row[] = drupal_render($form['uid'][$key]['grant_delete']);
953
      }
954
      $rows[] = $row;
955
    }
956
    $output .= theme('table', array('header' => $header, 'rows' => $rows));
957
  }
958

    
959
  $output .= drupal_render_children($form);
960

    
961
  return $output;
962
}
963

    
964
/**
965
 * Implements hook_node_grants().
966
 */
967
function nodeaccess_node_grants($account, $op) {
968
  $roles = is_array($account->roles) ? array_keys($account->roles) : array(-1);
969
  return array(
970
    'nodeaccess_rid' => $roles,
971
    'nodeaccess_uid' => array($account->uid),
972
    'nodeaccess_author' => array($account->uid),
973
  );
974
}
975

    
976
/**
977
 * Implements hook_node_update().
978
 */
979
function nodeaccess_node_update($node) {
980
  // Node author may have changed, overwrite old record.
981
  $author_prefs = variable_get('nodeaccess_authors', array());
982
  // Array is prepopulated with grant values.
983
  $grant = $author_prefs[$node->type];
984
  $grant['gid'] = $node->uid;
985
  $grant['realm'] = 'nodeaccess_author';
986
  $grants = array();
987
  $grants[] = $grant;
988
  node_access_write_grants($node, $grants, 'nodeaccess_author');
989
  if (module_exists('user_reference')) {
990
    $fields = variable_get('nodeaccess_' . $node->type . '_user_reference', array());
991
    foreach (array_keys($fields) as $field_name) {
992
      if (isset($node->$field_name)) {
993
        $old_node = node_load($node->nid);
994
        // Delete the old user as it's changed.
995
        if ($node->$field_name != $old_node->$field_name) {
996
          nodeaccess_delete_user_reference($old_node);
997
          nodeaccess_insert_user_reference($node);
998
        }
999
        break;
1000
      }
1001
    }
1002
  }
1003
  // Done, author permissions are not written into nodeaccess.
1004
}
1005

    
1006
/**
1007
 * Implements hook_node_delete().
1008
 */
1009
function nodeaccess_node_delete($node) {
1010
  // Deleting node, delete related permissions.
1011
  db_delete('nodeaccess')
1012
  ->condition('nid', $node->nid)
1013
  ->execute();
1014
  foreach (array('uid', 'rid', 'author') as $type) {
1015
    $realm = 'nodeaccess_' . $type;
1016
    node_access_write_grants($node, array(), $realm);
1017
  }
1018
}
1019
/**
1020
 * Implements hook_node_access_records().
1021
 */
1022
function nodeaccess_node_access_records($node) {
1023
  if (nodeaccess_disabling()) {
1024
    return;
1025
  }
1026
  // Need to find out if node has own grants or whether to use defaults.
1027
  $default = variable_get('nodeaccess_' . $node->type, array());
1028
  // Load priority setting.
1029
  $priority = variable_get('nodeaccess-priority', 0);
1030
  $result = db_query("SELECT count(*) FROM {nodeaccess} WHERE nid = :nid", array(':nid' => $node->nid))->fetchField();
1031
  if ($result < 1) {
1032
    // Node has no own grants, use defaults.
1033
    $grants = $default;
1034
    foreach ($grants as $id => $grant) {
1035
      $grants[$id]['priority'] = $priority;
1036
    }
1037
  }
1038
  else {
1039
    // Node has own grants, use them.
1040
    $result = db_query("SELECT nid, gid, realm, grant_view, grant_update, grant_delete FROM {nodeaccess} WHERE nid = :nid", array(':nid' => $node->nid));
1041
    $grants = array();
1042
    foreach ($result as $row) {
1043
      $grants[] = array(
1044
        'gid' => $row->gid,
1045
        'realm' => $row->realm,
1046
        'grant_view' => $row->grant_view,
1047
        'grant_update' => $row->grant_update,
1048
        'grant_delete' => $row->grant_delete,
1049
        'priority' => $priority,
1050
      );
1051
    }
1052
  }
1053
  // Apply author grants.
1054
  $author_prefs = variable_get('nodeaccess_authors', array());
1055
  // Array is prepopulated with grant values.
1056
  $grant = $author_prefs[$node->type];
1057
  $grant['gid'] = $node->uid;
1058
  $grant['realm'] = 'nodeaccess_author';
1059
  $grant['priority'] = $priority;
1060
  // Include author grant even with all values FALSE, it may be
1061
  // needed to overwrite an older value.
1062
  $grants[] = $grant;
1063
  return $grants;
1064
}
1065

    
1066
/**
1067
 * @todo Please document this function.
1068
 * @see http://drupal.org/node/1354
1069
 */
1070
function nodeaccess_disabling($set = NULL) {
1071
  static $disabling = FALSE;
1072
  if ($set !== NULL) {
1073
    $disabling = $set;
1074
  }
1075
  return $disabling;
1076
}
1077

    
1078
/**
1079
 * Implements hook_node_type_delete().
1080
 */
1081
function nodeaccess_node_type_delete($info) {
1082
  // Node type is being deleted, delete its preferences.
1083
  variable_del('nodeaccess_' . $info->type);
1084
  $author_prefs = variable_get('nodeaccess_authors', array());
1085
  unset($author_prefs[$info->type]);
1086
  variable_set('nodeaccess_authors', $author_prefs);
1087
}
1088

    
1089
/**
1090
 * Implements hook_node_type_update().
1091
 */
1092
function nodeaccess_node_type_update($info) {
1093
  // Node type has changed, move preferences to new type.
1094
  if (!empty($info->old_type) && $info->old_type != $info->type) {
1095
    $setting = variable_get('nodeaccess_' . $info->old_type, array());
1096
    variable_del('nodeaccess_' . $info->old_type);
1097
    variable_set('nodeaccess_' . $info->type, $setting);
1098
    $author_prefs = variable_get('nodeaccess_authors', array());
1099
    $author_prefs[$info->type] = array(
1100
      'grant_view' => $author_prefs[$info->old_type]['grant_view'],
1101
      'grant_update' => $author_prefs[$info->old_type]['grant_update'],
1102
      'grant_delete' => $author_prefs[$info->old_type]['grant_delete'],
1103
    );
1104
    unset($author_prefs[$info->old_type]);
1105
    variable_set('nodeaccess_authors', $author_prefs);
1106
  }
1107
}
1108

    
1109
/**
1110
 * Implements hook_node_type_insert().
1111
 */
1112
function nodeaccess_node_type_insert($info) {
1113
  // New node type, default to whatever is set for access content permission.
1114
  $role_perms = user_role_permissions(array(1 => 1, 2 => 2));
1115
  $role_perms[1]['access content'] = isset($role_perms[1]['access content'])?
1116
                                      intval($role_perms[1]['access content']) : 0;
1117
  $role_perms[2]['access content'] = isset($role_perms[2]['access content'])?
1118
                                      intval($role_perms[2]['access content']) : 0;
1119
  $grants[] = array(
1120
    'gid' => 1,
1121
    'realm' => 'nodeaccess_rid',
1122
    'grant_view' => $role_perms[1]['access content'],
1123
    'grant_update' => 0,
1124
    'grant_delete' => 0,
1125
  );
1126
  $grants[] = array(
1127
    'gid' => 2,
1128
    'realm' => 'nodeaccess_rid',
1129
    'grant_view' => $role_perms[1]['access content'],
1130
    'grant_update' => 0,
1131
    'grant_delete' => 0,
1132
  );
1133
  variable_set('nodeaccess_' . $info->type, $grants);
1134
  // Add all permissions for author.
1135
  $author_prefs = variable_get('nodeaccess_authors', array());
1136
  $author_prefs[$info->type] = array(
1137
    'grant_view' => 1,
1138
    'grant_update' => 1,
1139
    'grant_delete' => 1,
1140
  );
1141
  variable_set('nodeaccess_authors', $author_prefs);
1142
  node_access_needs_rebuild(TRUE);
1143
}
1144

    
1145
/**
1146
 * @todo Please document this function.
1147
 * @see http://drupal.org/node/1354
1148
 */
1149
function nodeaccess_get_role_aliases() {
1150
  $aliases = array();
1151
  $results = db_query('SELECT r.rid, r.name, a.name AS alias, a.weight FROM {role} r LEFT JOIN {nodeaccess_role_alias} a ON r.rid = a.rid ORDER BY r.name');
1152
  foreach ($results as $a) {
1153
    $aliases[$a->rid]['name'] = $a->name;
1154
    $aliases[$a->rid]['alias'] = $a->alias;
1155
    $aliases[$a->rid]['weight'] = $a->weight;
1156
  }
1157
  return $aliases;
1158
}
1159

    
1160
/**
1161
 * @todo Please document this function.
1162
 * @see http://drupal.org/node/1354
1163
 */
1164
function nodeaccess_save_role_aliases($edit) {
1165
  db_delete('nodeaccess_role_alias')->execute();
1166
  if (is_array($edit)) {
1167
    foreach ($edit as $key => $value) {
1168
      db_insert('nodeaccess_role_alias')->fields(array(
1169
        'rid' => $key,
1170
        'name' => $value['name'],
1171
        'weight' => $value['weight'],
1172
      ))->execute();
1173
    }
1174
  }
1175

    
1176
  return;
1177
}
1178

    
1179
/**
1180
 * Insert userreference grants from a node.
1181
 */
1182
function nodeaccess_insert_user_reference($node) {
1183
  $form_values = _nodeaccess_get_grants($node);
1184
  // Now, append or overwrite the uid with what was specified in the user
1185
  // reference field.
1186
  $fields = variable_get('nodeaccess_' . $node->type . '_user_reference', array());
1187
  foreach ($fields as $field_name => $field) {
1188
    $user_uids = field_get_items('node', $node, $field_name);
1189
    $user_references = user_load_multiple($user_uids);
1190
    // Add each of the referenced users a form value.
1191
    foreach ($user_references as $user) {
1192
      $form_values['uid'][$user->uid] = array(
1193
        'name' => $user->name,
1194
        'keep' => 1,
1195
        'grant_view' => $field['grant_view'],
1196
        'grant_update' => $field['grant_update'],
1197
        'grant_delete' => $field['grant_delete'],
1198
      );
1199
    }
1200
  }
1201
  // Only do the changes if there are users to save.
1202
  if (count($form_values['uid']) > 0) {
1203
    $form_values['nid'] = $node->nid;
1204
    $form_state = array('values' => $form_values);
1205
    _nodeaccess_grants_form_submit(NULL, $form_state);
1206
  }
1207
}
1208

    
1209
/**
1210
 * Delete all userreference user grants from a node.
1211
 */
1212
function nodeaccess_delete_user_reference($node) {
1213
  $form_values = _nodeaccess_get_grants($node);
1214
  // Now, append or overwrite the uid with what was specified in the user
1215
  // reference field.
1216
  $fields = variable_get('nodeaccess_' . $node->type . '_user_reference', array());
1217
  foreach ($fields as $field_name => $field) {
1218
    $user_uids = field_get_items('node', $node, $field_name);
1219
    $user_references = user_load_multiple($user_uids);
1220
    foreach ($user_references as $user) {
1221
      unset($form_values['uid'][$user->uid]);
1222
    }
1223
  }
1224
  $form_values['nid'] = $node->nid;
1225
  $form_state = array('values' => $form_values);
1226
  _nodeaccess_grants_form_submit(NULL, $form_state);
1227
}
1228

    
1229
/**
1230
 * Return the grants applied to a node object used for Grant form.
1231
 *
1232
 * @return array
1233
 *   An array of grants with keys 'rid' for roles and 'uid' for users.
1234
 */
1235
function _nodeaccess_get_grants($node) {
1236
  $grants = array();
1237
  // Load all roles.
1238
  $result = db_query("SELECT r.rid, nra.name, na.grant_view, na.grant_update, na.grant_delete FROM {role} r LEFT JOIN {nodeaccess_role_alias} nra ON r.rid = nra.rid LEFT JOIN {node_access} na ON r.rid = na.gid AND na.realm = :realm AND na.nid = :nid ORDER BY nra.weight, nra.name",
1239
    array(
1240
      ':realm' => 'nodeaccess_rid',
1241
      ':nid' => $node->nid,
1242
    ));
1243
  foreach ($result as $grant) {
1244
    $grants['rid'][$grant->rid] = array(
1245
      'name' => $grant->name,
1246
      'grant_view' => (boolean) $grant->grant_view,
1247
      'grant_update' => (boolean) $grant->grant_update,
1248
      'grant_delete' => (boolean) $grant->grant_delete,
1249
    );
1250
  }
1251
  // Load users from node_access.
1252
  $result = db_query("SELECT uid, name, grant_view, grant_update, grant_delete FROM {node_access} LEFT JOIN {users} ON uid = gid WHERE nid = :nid AND realm = :realm ORDER BY name",
1253
    array(
1254
      ':nid' => $node->nid,
1255
      ':realm' => 'nodeaccess_uid',
1256
    ));
1257
  foreach ($result as $account) {
1258
    $grants['uid'][$account->uid] = array(
1259
      'name' => $account->name,
1260
      'keep' => 1,
1261
      'grant_view' => $account->grant_view,
1262
      'grant_update' => $account->grant_update,
1263
      'grant_delete' => $account->grant_delete,
1264
    );
1265
  }
1266
  return $grants;
1267
}