Projet

Général

Profil

Paste
Télécharger (10,1 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / acl / acl.module @ 87dbc3bf

1
<?php
2

    
3
/**
4
 * @file
5
 * An API module providing by-user access control lists.
6
 *
7
 * This module handles ACLs on behalf of other modules. The two main reasons
8
 * to do this are so that modules using ACLs can share them with each
9
 * other without having to actually know much about them, and so that
10
 * ACLs can easily co-exist with the existing node_access system.
11
 */
12

    
13
/**
14
 * Create a new ACL.
15
 *
16
 * The client module will have to keep track of the ACL. For that it can
17
 * assign either a $name or a $number to this ACL.
18
 *
19
 * @param $module
20
 *   The name of the client module.
21
 * @param $name
22
 *   An arbitrary name for this ACL, freely defined by the client module.
23
 * @param $number
24
 *   An arbitrary number for this ACL, freely defined by the client module.
25
 * @return
26
 *   The ID of the newly created ACL.
27
 */
28
function acl_create_acl($module, $name = NULL, $number = NULL) {
29
  $acl = array(
30
    'module' => $module,
31
    'name' => $name,
32
    'number' => $number
33
  );
34
  drupal_write_record('acl', $acl);
35
  return $acl['acl_id'];
36
}
37

    
38
/**
39
 * Create a new ACL (obsolete).
40
 *
41
 * @see acl_create_acl()
42
 */
43
function acl_create_new_acl($module, $name = NULL, $number = NULL) {
44
  return acl_create_acl($module, $name, $number);
45
}
46

    
47
/**
48
 * Delete an existing ACL.
49
 */
50
function acl_delete_acl($acl_id) {
51
  db_delete('acl')
52
    ->condition('acl_id', $acl_id)
53
    ->execute();
54
  db_delete('acl_user')
55
    ->condition('acl_id', $acl_id)
56
    ->execute();
57
  db_delete('acl_node')
58
    ->condition('acl_id', $acl_id)
59
    ->execute();
60
}
61

    
62
/**
63
 * Add the specified UID to an ACL.
64
 */
65
function acl_add_user($acl_id, $uid) {
66
  $test_uid = db_query("SELECT uid FROM {acl_user} WHERE acl_id = :acl_id AND uid = :uid", array(
67
    'acl_id' => $acl_id,
68
    'uid' => $uid,
69
  ))->fetchField();
70
  if (!$test_uid) {
71
    db_insert('acl_user')
72
    ->fields(array(
73
      'acl_id' => $acl_id,
74
      'uid' => $uid,
75
    ))
76
    ->execute();
77
  }
78
}
79

    
80
/**
81
 * Remove the specified UID from an ACL.
82
 */
83
function acl_remove_user($acl_id, $uid) {
84
  db_delete('acl_user')
85
    ->condition('acl_id', $acl_id)
86
    ->condition('uid', $uid)
87
    ->execute();
88
}
89

    
90
/**
91
 * Provide a form to edit the ACL that can be embedded in other forms.
92
 * Pass $new_acl=TRUE if you have no ACL yet, but do supply a string
93
 * like 'my_module_new_acl' as $acl_id anyway.
94
 */
95
function acl_edit_form(&$form_state, $acl_id, $label = NULL, $new_acl = FALSE) {
96
  $form_state['build_info']['files'][] = _acl_module_load_include('admin.inc');
97
  return _acl_edit_form($acl_id, $label, $new_acl);
98
}
99

    
100
/**
101
 * Provide access control to all nodes selected by a subquery, based upon an ACL id.
102
 */
103
function acl_add_nodes($subselect, $acl_id, $view, $update, $delete, $priority = 0) {
104
  db_delete('acl_node')
105
    ->condition('acl_id', $acl_id)
106
    ->condition('nid', $subselect, 'IN')
107
    ->execute();
108
  $subselect->addExpression($acl_id, 'acl_id');
109
  $subselect->addExpression((int) $view, 'grant_view');
110
  $subselect->addExpression((int) $update, 'grant_update');
111
  $subselect->addExpression((int) $delete, 'grant_delete');
112
  $subselect->addExpression($priority, 'priority');
113
  db_insert('acl_node')
114
    ->from($subselect)
115
    ->execute();
116
}
117

    
118
/**
119
 * Provide access control to a node based upon an ACL id.
120
 */
121
function acl_node_add_acl($nid, $acl_id, $view, $update, $delete, $priority = 0) {
122
  acl_node_add_acl_record(array(
123
    'acl_id'       => $acl_id,
124
    'nid'          => $nid,
125
    'grant_view'   => (int) $view,
126
    'grant_update' => (int) $update,
127
    'grant_delete' => (int) $delete,
128
    'priority'     => $priority,
129
  ));
130
}
131

    
132
/**
133
 * Provide access control to a node based upon an ACL id.
134
 */
135
function acl_node_add_acl_record(array $record) {
136
  db_delete('acl_node')
137
    ->condition('acl_id', $record['acl_id'])
138
    ->condition('nid', $record['nid'])
139
    ->execute();
140
  db_insert('acl_node')
141
    ->fields($record)
142
    ->execute();
143
}
144

    
145
/**
146
 * Remove an ACL completely from a node.
147
 */
148
function acl_node_remove_acl($nid, $acl_id) {
149
  db_delete('acl_node')
150
    ->condition('acl_id', $acl_id)
151
    ->condition('nid', $nid)
152
    ->execute();
153
}
154

    
155
/**
156
 * Clear all of a module's ACLs from a node.
157
 */
158
function acl_node_clear_acls($nid, $module) {
159
  $select = db_select('acl', 'a')
160
    ->fields('a', array('acl_id'))
161
    ->condition('a.module', $module);
162
  db_delete('acl_node')
163
    ->condition('nid', $nid)
164
    ->condition('acl_id', $select, 'IN')
165
    ->execute();
166
}
167

    
168
/**
169
 * Get the id of an ACL by name (+ optionally number).
170
 */
171
function acl_get_id_by_name($module, $name, $number = NULL) {
172
  $query = db_select('acl', 'a')
173
    ->fields('a', array('acl_id'))
174
    ->condition('a.module', $module)
175
    ->condition('a.name', $name);
176
  if (isset($number)) {
177
    $query->condition('a.number', $number);
178
  }
179
  return $query->execute()->fetchField();
180
}
181

    
182
/**
183
 * Get the id of an ACL by number.
184
 */
185
function acl_get_id_by_number($module, $number) {
186
  $query = db_select('acl', 'a')
187
    ->fields('a', array('acl_id'))
188
    ->condition('a.module', $module)
189
    ->condition('a.number', $number);
190
  return $query->execute()->fetchField();
191
}
192

    
193
/**
194
 * Determine whether an ACL has some assigned users.
195
 */
196
function acl_has_users($acl_id) {
197
  return db_query("SELECT COUNT(uid) FROM {acl_user} WHERE acl_id = :acl_id", array(
198
    'acl_id' => $acl_id,
199
  ))->fetchField();
200
}
201

    
202
/**
203
 * Determine whether an ACL has a specific assigned user.
204
 */
205
function acl_has_user($acl_id, $uid) {
206
  return db_query("SELECT COUNT(uid) FROM {acl_user} WHERE acl_id = :acl_id AND uid = :uid", array(
207
    'acl_id' => $acl_id,
208
    'uid' => $uid,
209
  ))->fetchField();
210
}
211

    
212
/**
213
 * Get an array of acl_ids held by a user.
214
 */
215
function acl_get_ids_by_user($module, $uid, $name = NULL, $number = NULL) {
216
  $query = db_select('acl', 'a');
217
  $query->join('acl_user', 'au', 'a.acl_id = au.acl_id');
218
  $query
219
    ->fields('a', array('acl_id'))
220
    ->condition('a.module', $module)
221
    ->condition('au.uid', $uid);
222
  if (isset($name)) {
223
    $query->condition('a.name', $name);
224
  }
225
  if (isset($number)) {
226
    $query->condition('a.number', $number);
227
  }
228
  $acl_ids = $query->execute()->fetchCol();
229
  return $acl_ids;
230
}
231

    
232
/**
233
 * Get the uids of an ACL.
234
 */
235
function acl_get_uids($acl_id) {
236
  $uids = db_query("SELECT uid FROM {acl_user} WHERE acl_id = :acl_id", array(
237
    'acl_id' => $acl_id,
238
  ))->fetchCol();
239
  return $uids;
240
}
241

    
242
/**
243
 * Implements hook_node_access_records().
244
 */
245
function acl_node_access_records($node) {
246
  if (!$node->nid) {
247
    return;
248
  }
249
  $result = db_query("SELECT n.*, 'acl' AS realm, n.acl_id AS gid, a.module FROM {acl_node} n INNER JOIN {acl} a ON n.acl_id = a.acl_id WHERE nid = :nid", array(
250
    'nid' => $node->nid,
251
  ), array('fetch' => PDO::FETCH_ASSOC));
252
  $grants = array();
253
  foreach ($result as $grant) {
254
    if (module_invoke($grant['module'], 'enabled')) {
255
      if (acl_has_users($grant['gid'])) {
256
        $grants[] = $grant;
257
      }
258
      else {
259
        //just deny access
260
        $grants[] = array(
261
          'realm' => 'acl',
262
          'gid' => $grant['gid'],
263
          'grant_view' => 0,
264
          'grant_update' => 0,
265
          'grant_delete' => 0,
266
          'priority' => $grant['priority'],
267
        );
268
      }
269
    }
270
  }
271
  return $grants;
272
}
273

    
274
/**
275
 * Implements hook_node_grants().
276
 */
277
function acl_node_grants($account, $op) {
278
  $acl_ids = db_query("SELECT acl_id FROM {acl_user} WHERE uid = :uid", array(
279
    'uid' => $account->uid,
280
  ))->fetchCol();
281
  return (!empty($acl_ids) ? array('acl' => $acl_ids) : NULL);
282
}
283

    
284
/**
285
 * Implements hook_node_delete().
286
 */
287
function acl_node_delete($node) {
288
  db_delete('acl_node')
289
    ->condition('nid', $node->nid)
290
    ->execute();
291
}
292

    
293
/**
294
 * Implements hook_user_cancel().
295
 */
296
function acl_user_cancel($edit, $account, $method) {
297
  db_delete('acl_user')
298
    ->condition('uid', $account->uid)
299
    ->execute();
300
}
301

    
302
/**
303
 * Helper function to load include files.
304
 */
305
function _acl_module_load_include($type) {
306
  static $loaded = array();
307

    
308
  if (!isset($loaded[$type])) {
309
    $path = module_load_include($type, 'acl');
310
    $loaded[$type] = drupal_get_path('module', 'acl') . "/acl.$type";
311
  }
312
  return $loaded[$type];
313
}
314

    
315
/**
316
 * Implements hook_node_access_explain().
317
 */
318
function acl_node_access_explain($row) {
319
  static $interpretations = array();
320
  if ($row->realm == 'acl') {
321
    if (!isset($interpretations[$row->gid])) {
322
      $acl = db_query("SELECT * FROM {acl} WHERE acl_id = :acl_id", array(
323
        'acl_id' => $row->gid,
324
      ))->fetchObject();
325
      $acl->tag = '?';
326
      if (!isset($acl->name)) {
327
        $acl->tag = $acl->number;
328
      }
329
      elseif (!isset($acl->number)) {
330
        $acl->tag = $acl->name;
331
      }
332
      else {
333
        $acl->tag = $acl->name . '-' . $acl->number;
334
      }
335
      $result = db_query("SELECT u.name FROM {acl_user} au, {users} u WHERE au.acl_id = :acl_id AND au.uid = u.uid", array(
336
        'acl_id' => $row->gid,
337
      ));
338
      foreach ($result as $user) {
339
        $users[] = $user->name;
340
      }
341
      if (isset($users)) {
342
        $users = implode(', ', $users);
343
        $interpretations[$row->gid] = _acl_get_explanation("$acl->module/$acl->tag: $users", $acl->acl_id, $acl->module, $acl->name, $acl->number, $users);
344
      }
345
      elseif ($row->gid == 0) {
346
        $result = db_query("SELECT an.acl_id, a.module, a.name FROM {acl_node} an JOIN {acl} a ON an.acl_id = a.acl_id LEFT JOIN {acl_user} au ON a.acl_id = au.acl_id WHERE an.nid = :nid AND au.uid IS NULL", array(
347
          'nid' => $row->nid,
348
        ));
349
        foreach ($result as $acl) {
350
          $rows[] = _acl_get_explanation("$acl->acl_id:&nbsp;$acl->module/$acl->tag", $acl->acl_id, $acl->module, $acl->name, $acl->number);
351
        }
352
        if (!empty($rows)) {
353
          return implode('<br />', $rows);
354
        }
355
        return 'No access via ACL.';
356
      }
357
      else {
358
        $interpretations[$row->gid] = _acl_get_explanation("$acl->module/$acl->tag: no users!", $acl->acl_id, $acl->module, $acl->name, $acl->number);
359
      }
360
    }
361
    return $interpretations[$row->gid];
362
  }
363
}
364

    
365
/**
366
 * Helper function to ask the client for its interpretation of the given
367
 * grant record.
368
 */
369
function _acl_get_explanation($text, $acl_id, $module, $name, $number, $users = NULL) {
370
  $hook = $module .'_acl_explain';
371
  if (function_exists($hook)) {
372
    return '<span title="'. $hook($acl_id, $name, $number, $users) .'">'. $text .'</span>';
373
  }
374
  return $text;
375
}
376