Projet

Général

Profil

Paste
Télécharger (12,5 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / content_access / content_access_rules / content_access_rules.rules.inc @ 76df55b7

1
<?php
2

    
3
/**
4
 * @file
5
 * Rules specific functions that expose content_access' API.
6
 *
7
 * @todo
8
 * A way to enable per-node settings when a rule created, otherwise no effects
9
 *   will be noticed.
10
 * Clean-up function names.
11
 */
12

    
13
/**
14
 * Implements hook_rules_event_info().
15
 *
16
 * @ingroup rules
17
 */
18
function content_access_rules_rules_event_info() {
19
  $events['content_access_content_type'] = array('label' => t('Content type access control was changed'));
20
  $events['content_access_per_node'] = array('label' => t('Per node access control was changed'));
21

    
22
  if (module_exists('acl')) {
23
    $events['content_access_user_acl'] = array('label' => t('User was added to ACL'));
24
  }
25

    
26
  $items = array();
27
  foreach ($events as $name => $event) {
28
    $items[$name] = array(
29
      'label' => $event['label'],
30
      'group' => t('Content Access'),
31
    );
32
  }
33

    
34
  return $items;
35
}
36

    
37
/**
38
 * Implementation of hook_rules_action_info().
39
 *
40
 * @ingroup rules
41
 */
42
function content_access_rules_rules_action_info() {
43
  $role_actions = array(
44
    'content_access_action_grant_node_permissions' => array(
45
      'label' => t('Grant access by role'),
46
      'description' => t('Grant access to the following content'),
47
    ),
48
    'content_access_action_revoke_node_permissions' => array(
49
      'label' => t('Revoke access by role'),
50
      'description' => t('Revoke access to the following content'),
51
    ),
52
  );
53

    
54
  $reset_actions = array(
55
    'content_access_action_reset_node_permissions' => array(
56
      'label' => t('Reset access to content type defaults'),
57
      'description' => t('Reset node permissions to default permissions'),
58
    ),
59
  );
60

    
61
  $user_actions = array(
62
    'content_access_action_user_grant' => array(
63
      'label' => t('Grant access by user'),
64
      'operation' => t('Grant'),
65
      'description' => t('Grant access to the following content'),
66
    ),
67
    'content_access_action_user_revoke' => array(
68
      'label' => t('Revoke access by user'),
69
      'operation' => t('Revoke'),
70
      'description' => t('Revoke access to the following content'),
71
    ),
72
  );
73

    
74
  $items = array();
75
  foreach ($role_actions as $name => $action) {
76
    $items[$name] = array(
77
      'label' => $action['label'],
78
      'parameter' => array(
79
        'node' => array(
80
          'type' => 'node',
81
          'label' => t('Content'),
82
          'description' => $action['description'],
83
        ),
84
        'permissions' => array(
85
          'type' => 'list<text>',
86
          'label' => t('Role-based access control settings'),
87
          'optional' => TRUE,
88
          'options list' => 'content_access_action_roles_permissions_list',
89
          'restriction' => 'input',
90
        ),
91
      ),
92
      'group' => t('Content Access'),
93
      'callbacks' => array(
94
        'form_alter' => 'content_access_rules_action_form_alter',
95
      ),
96
    );
97
  }
98

    
99
  foreach ($reset_actions as $name => $action) {
100
    $items[$name] = array(
101
      'label' => $action['label'],
102
      'parameter' => array(
103
        'node' => array(
104
          'type' => 'node',
105
          'label' => t('Content'),
106
          'description' => $action['description'],
107
        ),
108
      ),
109
      'group' => t('Content Access'),
110
    );
111
  }
112

    
113
  if (module_exists('acl')) {
114
    foreach ($user_actions as $name => $action) {
115
      $items[$name] = array(
116
        'label' => $action['label'],
117
        'named parameter' => TRUE,
118
        'parameter' => array(
119
          'node' => array(
120
            'type' => 'node',
121
            'label' => t('Content'),
122
            'description' => $action['description'],
123
          ),
124
          'content_access_user_view' => array(
125
            'type' => 'user',
126
            'label' => t('@action view access', array('@action' => $action['operation'])),
127
            'optional' => TRUE,
128
            'description' => t('@action view access to the following user.', array('@action' => $action['operation'])),
129
          ),
130
          'content_access_user_update' => array(
131
            'type' => 'user',
132
            'label' => t('@action update access', array('@action' => $action['operation'])),
133
            'optional' => TRUE,
134
            'description' => t('@action edit access to the following user.', array('@action' => $action['operation'])),
135
          ),
136
          'content_access_user_delete' => array(
137
            'type' => 'user',
138
            'label' => t('@action delete access', array('@action' => $action['operation'])),
139
            'optional' => TRUE,
140
            'description' => t('@action delete access to the following user.', array('@action' => $action['operation'])),
141
          ),
142
        ),
143
        'group' => t('Content Access User'),
144
      );
145
    }
146
  }
147

    
148
  return $items;
149
}
150

    
151
/**
152
 * Returns an options list array for the content access permission parameter.
153
 */
154
function content_access_action_roles_permissions_list() {
155
  $options = array();
156
  $roles = array_map('filter_xss_admin', user_roles());
157

    
158
  foreach (_content_access_get_operations() as $op => $label) {
159
    foreach ($roles as $rid => $role) {
160
      $options[$op][$op . ':' . $rid] = $op . ' ' . $role;
161
    }
162
  }
163
  return $options;
164
}
165

    
166
/**
167
 * Alter the settings form to render the text<list> as checkboxes.
168
 */
169
function content_access_rules_action_form_alter(&$form, &$form_state) {
170
  // Per node access control should be enabled for this type of action to be
171
  // effective.
172
  drupal_set_message(t('Access control settings will not be executed for the affected node unless you enabled \'%per_node\' from the Access Control tab on content type page of the node', array('%per_node' => 'Per content node access control settings')), 'warning');
173

    
174
  // Alter the text<list> to make it into checkboxes groups
175
  $elements =& $form['parameter']['permissions']['settings']['permissions'];
176
  $elements = content_access_rules_checkboxes_form((array) $elements['#default_value']);
177

    
178
  // Add our own after build callback for fixing the form value afterwards.
179
  $elements['#after_build'][] = 'content_access_rules_action_form_after_build';
180

    
181
  // Make sure our include file is loaded when FAPI processes the form.
182
  form_load_include($form_state, 'inc', 'content_access_rules', 'content_access_rules.rules');
183
}
184

    
185
/**
186
 * Form after build callback.
187
 *
188
 * Get the form settings as checkboxes, convert them back to list<text>.
189
 */
190
function content_access_rules_action_form_after_build($element, &$form_state) {
191
  if ($form_state['process_input']) {
192
    $form_value = drupal_array_get_nested_value($form_state['values'], $element['#parents']);
193
    $value = content_access_rules_transform_to_rule_value($form_value);
194
    form_set_value($element, $value, $form_state);
195
  }
196
  return $element;
197
}
198

    
199
/**
200
 * Returns the form elements for configuring content access per-role permissions.
201
 */
202
function content_access_rules_checkboxes_form($value) {
203
  $form = array();
204
  $roles = array_map('filter_xss_admin', user_roles());
205
  $defaults = content_access_rules_transform_rules_value($value);
206

    
207
  foreach (_content_access_get_operations() as $op => $label) {
208
    $form[$op] = array(
209
      '#type' => 'checkboxes',
210
      '#prefix' => '<div class="content_access-div">',
211
      '#suffix' => '</div>',
212
      '#options' => $roles,
213
      '#title' => $label,
214
      '#default_value' => isset($defaults[$op]) ? $defaults[$op] : array(),
215
      '#process' => array('form_process_checkboxes', 'content_access_disable_checkboxes'),
216
    );
217
  }
218
  $form['clearer'] = array(
219
    '#value' => '<br clear="all" />',
220
  );
221
  drupal_add_css(drupal_get_path('module', 'content_access') . '/content_access.css');
222

    
223
  return $form;
224
}
225

    
226
/**
227
 * Transforms the array of text values used by Rules to an array keyed by $op and $rid.
228
 *
229
 * @see content_access_rules_transform_to_rule_value()
230
 */
231
function content_access_rules_transform_rules_value($value) {
232
  $array = array();
233
  foreach ($value as $op_role) {
234
    $parts = explode(':', $op_role);
235
    // The first item is $op and the second $rid.
236
    $array[$parts[0]][] = $parts[1];
237
  }
238
  return $array;
239
}
240

    
241
/**
242
 * Transform the form values array keyed by $op and $rid to an array of text values as used by Rules.
243
 *
244
 * @see content_access_rules_transform_rules_value()
245
 */
246
function content_access_rules_transform_to_rule_value($form_values) {
247
  $value = array();
248
  foreach ($form_values as $op => $array) {
249
    foreach (array_filter($array) as $rid => $data) {
250
      $value[] = $op . ':' . $rid;
251
    }
252
  }
253
  return $value;
254
}
255

    
256
/**
257
 * Action implementation: Grant permissions for a node.
258
 */
259
function content_access_action_grant_node_permissions($node, $permissions) {
260
  if (!empty($node->nid) && _content_access_rules_check_setting($node)) {
261
    // Transform the value to the content-access format.
262
    $settings = content_access_rules_transform_rules_value($permissions);
263
    $ca_settings = array();
264
    foreach (_content_access_get_operations() as $op => $label) {
265
      // Merge in the array of role-ids for each operation.
266
      $settings += array($op => array());
267
      $ca_settings[$op] = array_keys(array_flip(content_access_per_node_setting($op, $node)) + array_flip($settings[$op]));
268
    }
269
    content_access_save_per_node_settings($node, $ca_settings);
270
    content_access_action_aquire_grants($node);
271
  }
272
}
273

    
274
/**
275
 * Action implementation: Revoke permissions for a node.
276
 */
277
function content_access_action_revoke_node_permissions($node, $permissions) {
278
  if (!empty($node->nid) && _content_access_rules_check_setting($node)) {
279
    // Transform the value to the content-access format.
280
    $settings = content_access_rules_transform_rules_value($permissions);
281

    
282
    $ca_settings = array();
283
    foreach (_content_access_get_operations() as $op => $label) {
284
      $settings += array($op => array());
285
      $ca_settings[$op] = array_diff(content_access_per_node_setting($op, $node), $settings[$op]);
286
    }
287
    content_access_save_per_node_settings($node, $ca_settings);
288
    content_access_action_aquire_grants($node);
289
  }
290
}
291

    
292
/**
293
 * Action implementation: Reset permissions for a node.
294
 */
295
function content_access_action_reset_node_permissions($node) {
296
  content_access_delete_per_node_settings($node);
297
  content_access_action_aquire_grants($node);
298
}
299

    
300
/**
301
 * Verifies that per content settings are activated for the given node.
302
 */
303
function _content_access_rules_check_setting($node) {
304
  $type = $node->type;
305
  $settings = variable_get('content_access_' . $type, array());
306

    
307
  if (isset($settings['per_node']) && $settings['per_node']) {
308
    return TRUE;
309
  }
310

    
311
  // If we didn't find any settings in content access for this type return
312
  // false as we don't want to process it.
313
  rules_log("Can't set per content permissions for content type @type. Make sure to have per content settings activated for content types you want to alter access control for.", array('@type' => $node->type), RulesLog::WARN);
314
  return FALSE;
315
}
316

    
317
/**
318
 * Split the settings string into array.
319
 */
320
function content_access_action_settings($action_settings = array()) {
321
  $roles_ids = array_flip(user_roles());
322

    
323
  foreach (_content_access_get_operations() as $op => $label) {
324
    $settings[$op] = array();
325
  }
326

    
327
  foreach ($action_settings as $op_role => $role) {
328
    $op = substr($op_role, 0, strpos($op_role, ':'));
329
    $rid = $roles_ids[$role];
330
    $settings[$op][] = $rid;
331
  }
332

    
333
  return $settings;
334
}
335

    
336
/**
337
 * Action implementation: Grant user access.
338
 */
339
function content_access_action_user_grant($params) {
340
  content_access_action_user($params, 'grant');
341
}
342

    
343
/**
344
 * Action implementation: Revoke user access.
345
 */
346
function content_access_action_user_revoke($params) {
347
  content_access_action_user($params, 'revoke');
348
}
349

    
350
/**
351
 * Process Rule's param, and grant by the passed operation.
352
 */
353
function content_access_action_user($params, $type) {
354
  $ops = array('view', 'update', 'delete');
355
  $settings = array();
356
  $node = $params['node'];
357

    
358
  foreach ($ops as $op) {
359
    if ($params['content_access_user_' . $op]) {
360
      $settings[$op] = $params['content_access_user_' . $op]->uid;
361
    }
362
  }
363

    
364
  foreach ($settings as $op => $uid) {
365
    $acl_id = content_access_get_acl_id($node, $op);
366
    acl_node_add_acl($node->nid, $acl_id, (int) ($op == 'view'), (int) ($op == 'update'), (int) ($op == 'delete'), content_access_get_settings('priority', $node->type));
367

    
368
    db_delete('acl_user')
369
      ->condition('acl_id', $acl_id)
370
      ->condition('uid', $uid)
371
      ->execute();
372

    
373
    if ($type == 'grant') {
374
      db_insert('acl_user')
375
        ->fields(array(
376
          'acl_id' => $acl_id,
377
          'uid' => $uid,
378
        ))
379
        ->execute();
380
    }
381
  }
382

    
383
  content_access_action_aquire_grants($node);
384
}
385

    
386
/**
387
 * Apply the new grants to the affected node.
388
 */
389
function content_access_action_aquire_grants($node) {
390
  // node_save() does implement node_access_acquire_grants() so we don't want
391
  // to execute it again or we'll get a duplicated key exception
392
  if (!isset($node->op) ||
393
      (isset($node->op) && $node->op != 'Save')) {
394
    node_access_acquire_grants($node);
395
  }
396
}