| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: content_access.admin.inc,v 1.1.2.23 2009/07/31 10:03:22 fago Exp $ 3 4 /** 5 * @file Content access administration UI. 6 */ 7 8 /** 9 * Specifies the threshold until we try to mass update node grants immediately. 10 */ 11 define('CONTENT_ACCESS_MASS_UPDATE_THRESHOLD', 1000); 12 13 /** 14 * Per node settings page. 15 */ 16 function content_access_page(&$form_state, $node) { 17 drupal_set_title(t('Access control for %title', array('%title' => $node->title))); 18 19 foreach (_content_access_get_operations() as $op) { 20 $defaults[$op] = content_access_per_node_setting($op, $node); 21 } 22 23 $form = content_access_role_based_form($defaults); 24 // Add a after_build handler that disables checkboxes, which are enforced by permissions. 25 $form['per_role']['#after_build'] = array('content_access_force_permissions'); 26 27 if (module_exists('acl')) { 28 // This is disabled when there is no node passed. 29 $form['acl'] = array( 30 '#type' => 'fieldset', 31 '#title' => t('User access control lists'), 32 '#description' => t('These settings allow you to grant access to specific users.'), 33 '#collapsible' => TRUE, 34 '#tree' => TRUE, 35 ); 36 foreach (array('view', 'update', 'delete') as $op) { 37 $acl_id = content_access_get_acl_id($node, $op); 38 acl_node_add_acl($node->nid, $acl_id, $op == 'view', $op == 'update', $op == 'delete', content_access_get_settings('priority', $node->type)); 39 $form['acl'][$op] = acl_edit_form($acl_id, t('Grant !op access', array('!op' => $op))); 40 $form['acl'][$op]['#collapsed'] = !isset($_POST['acl_'. $acl_id]) && !unserialize($form['acl'][$op]['user_list']['#default_value']); 41 } 42 } 43 44 $form_state['node'] = $node; 45 $form['submit'] = array( 46 '#type' => 'submit', 47 '#value' => t('Submit'), 48 '#weight' => 10, 49 ); 50 $form['reset'] = array( 51 '#type' => 'submit', 52 '#value' => t('Reset to defaults'), 53 '#weight' => 10, 54 '#submit' => array('content_access_page_reset'), 55 '#access' => count(content_access_get_per_node_settings($node)) > 0, 56 ); 57 58 if (!$node->status) { 59 drupal_set_message(t("Warning: Your content is not published, so this settings are not taken into account as long as the content remains unpublished."), 'error'); 60 } 61 62 return $form; 63 } 64 65 66 function content_access_page_submit($form, &$form_state) { 67 $settings = array(); 68 $node = $form_state['node']; 69 foreach (_content_access_get_operations() as $op) { 70 // Set the settings so that further calls will return this settings. 71 $settings[$op] = array_keys(array_filter($form_state['values'][$op])); 72 } 73 // Save per-node settings. 74 content_access_save_per_node_settings($node, $settings); 75 76 if (module_exists('acl')) { 77 foreach (array('view', 'update', 'delete') as $op) { 78 acl_save_form($form_state['values']['acl'][$op]); 79 } 80 } 81 82 // Apply new settings. 83 node_access_acquire_grants($node); 84 cache_clear_all(); 85 86 drupal_set_message(t('Your changes have been saved.')); 87 } 88 89 function content_access_page_reset($form, &$form_state) { 90 content_access_delete_per_node_settings($form_state['node']); 91 node_access_acquire_grants($form_state['node']); 92 cache_clear_all(); 93 drupal_set_message(t('The permissions have been reseted to the content type defaults.')); 94 } 95 96 /** 97 * Per content type administration page form. 98 */ 99 function content_access_admin_settings(&$form_state, $type) { 100 $form_state['type'] = $type; 101 102 // Add role based per content type settings 103 $defaults = array(); 104 foreach (_content_access_get_operations() as $op) { 105 $defaults[$op] = content_access_get_settings($op, $type); 106 } 107 $form = content_access_role_based_form($defaults); 108 109 // Per node: 110 $form['node'] = array( 111 '#type' => 'fieldset', 112 '#title' => t('Per content node access control settings'), 113 '#collapsible' => TRUE, 114 '#description' => t('Optionally you can enable per content node access control settings. If enabled, a new tab for the content access settings appears when viewing content. You have to configure permission to access these settings at the !permissions page.', array('!permissions' => l(t('permissions'), 'admin/user/permissions'))), 115 ); 116 $form['node']['per_node'] = array( 117 '#type' => 'checkbox', 118 '#title' => t('Enable per content node access control settings'), 119 '#default_value' => content_access_get_settings('per_node', $type), 120 ); 121 122 $form['advanced'] = array( 123 '#type' => 'fieldset', 124 '#title' => t('Advanced'), 125 '#collapsible' => TRUE, 126 '#collapsed' => TRUE, 127 ); 128 $form['advanced']['priority'] = array( 129 '#type' => 'weight', 130 '#title' => t('Give content node grants priority'), 131 '#default_value' => content_access_get_settings('priority', $type), 132 '#description' => t('If you are only using this access control module, you can safely ignore this. If you are using multiple access control modules you can adjust the priority of this module.'), 133 ); 134 $form['submit'] = array( 135 '#type' => 'submit', 136 '#value' => t('Submit'), 137 '#weight' => 10, 138 ); 139 return $form; 140 } 141 142 function content_access_admin_settings_submit($form, &$form_state) { 143 // Where possible let the drupal permissions system handle access control. 144 $permissions = content_access_get_permissions_by_role(); 145 foreach (array('update', 'update_own', 'delete', 'delete_own') as $op) { 146 foreach ($form_state['values'][$op] as $rid => $value) { 147 $permissions[$rid][ content_access_get_permission_by_op($op, $form_state['type']) ] = $value; 148 } 149 // Don't save the setting, so its default value (get permission) is applied always. 150 unset($form_state['values'][$op]); 151 } 152 content_access_save_permissions($permissions); 153 154 // Update content access settings 155 $settings = content_access_get_settings(); 156 foreach (content_access_available_settings() as $setting) { 157 unset($settings[$setting][$form_state['type']]); 158 if (isset($form_state['values'][$setting])) { 159 $settings[$setting][$form_state['type']] = is_array($form_state['values'][$setting]) ? array_keys(array_filter($form_state['values'][$setting])) : $form_state['values'][$setting]; 160 } 161 } 162 content_access_set_settings($settings); 163 164 $type = $form_state['type']; 165 // Mass update the nodes, but only if necessary. 166 if (content_access_get_settings('per_node', $type) || 167 content_access_get_settings('view', $type) != $form['per_role']['view']['#default_value'] || 168 content_access_get_settings('view_own', $type) != $form['per_role']['view_own']['#default_value'] || 169 content_access_get_settings('priority', $type) != $form['advanced']['priority']['#default_value'] || 170 content_access_get_settings('per_node', $type) != $form['node']['per_node']['#default_value'] 171 ) { 172 173 // If per node has been disabled and we use the ACL integration, we have to remove possible ACLs now. 174 if (!content_access_get_settings('per_node', $type) && $form['node']['per_node']['#default_value'] && module_exists('acl')) { 175 _content_access_remove_acls($type); 176 } 177 178 if (content_access_mass_update(array($type))) { 179 drupal_set_message(t('Permissions have been successfully rebuilt for the content type @types.', array('@types' => node_get_types('name', $type)))); 180 } 181 } 182 183 drupal_set_message(t('Your changes have been saved.')); 184 } 185 186 /** 187 * Mass updates node access records for nodes of the given types. 188 * @param $types 189 * An array of content type names. 190 * @return 191 * Whether the operation has been processed successfully (TRUE) or postponed (FALSE). 192 */ 193 function content_access_mass_update($types) { 194 $count = db_result(db_query("SELECT COUNT(DISTINCT nid) FROM {node} WHERE type IN (". db_placeholders($types, 'text') .")", $types)); 195 node_access_needs_rebuild(TRUE); 196 197 // If there not too much nodes affected, try to do it. 198 if ($count <= CONTENT_ACCESS_MASS_UPDATE_THRESHOLD) { 199 $result = db_query("SELECT nid FROM {node} WHERE type IN (". db_placeholders($types, 'text') .")", $types); 200 while ($node = db_fetch_object($result)) { 201 node_access_acquire_grants(node_load($node->nid)); 202 } 203 204 cache_clear_all(); 205 node_access_needs_rebuild(FALSE); 206 return TRUE; 207 } 208 return FALSE; 209 } 210 211 /** 212 * Gets the permissions for the role of the given id. 213 */ 214 function content_access_get_permissions_by_role() { 215 $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid'); 216 $permissions = array(); 217 while ($role = db_fetch_object($result)) { 218 $permissions[$role->rid] = array_filter(drupal_map_assoc(explode(', ', $role->perm))); 219 } 220 return $permissions; 221 } 222 223 /** 224 * Saves the given permissions by role to the database. 225 */ 226 function content_access_save_permissions($permissions) { 227 foreach ($permissions as $rid => $perms) { 228 $perms = array_filter($perms); 229 db_query('DELETE FROM {permission} WHERE rid = %d', $rid); 230 if (count($perms)) { 231 db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", $rid, implode(', ', array_keys($perms))); 232 } 233 } 234 // Make sure new permissions are applied immediately. 235 content_access_get_permission_access(FALSE, TRUE); 236 } 237 238 /** 239 * Builds the role based permission form for the given defaults. 240 * 241 * @param $defaults 242 * Array of defaults for all operations. 243 */ 244 function content_access_role_based_form($defaults = array()) { 245 246 // Make sure defaults are set properly 247 foreach (_content_access_get_operations() as $op) { 248 $defaults += array($op => array()); 249 } 250 251 $roles = array_map('filter_xss_admin', user_roles()); 252 // Per type: 253 $form['per_role'] = array( 254 '#type' => 'fieldset', 255 '#title' => t('Role based access control settings'), 256 '#collapsible' => TRUE, 257 '#description' => t('Note that users need at least the %access_content permission to be able to deal in any way with content.', array('%access_content' => t('access content'))). 258 ' '. t('Furthermore note that content which is not @published is treated in a different way by drupal: It can be viewed only by its author or users with the %administer_nodes permission.', array('@published' => t('published'), '%administer_nodes' => t('administer nodes'))), 259 ); 260 drupal_add_css(drupal_get_path('module', 'content_access') . '/content_access.css'); 261 $form['per_role']['view'] = array('#type' => 'checkboxes', 262 '#prefix' => '<div class="content_access-div">', 263 '#suffix' => '</div>', 264 '#options' => $roles, 265 '#title' => t('View any content'), 266 '#default_value' => $defaults['view'], 267 '#process' => array('expand_checkboxes', 'content_access_disable_checkboxes'), 268 ); 269 $form['per_role']['update'] = array('#type' => 'checkboxes', 270 '#prefix' => '<div class="content_access-div">', 271 '#suffix' => '</div>', 272 '#options' => $roles, 273 '#title' => t('Edit any content'), 274 '#default_value' => $defaults['update'], 275 '#process' => array('expand_checkboxes', 'content_access_disable_checkboxes'), 276 ); 277 $form['per_role']['delete'] = array('#type' => 'checkboxes', 278 '#prefix' => '<div class="content_access-div">', 279 '#suffix' => '</div>', 280 '#options' => $roles, 281 '#title' => t('Delete any content'), 282 '#default_value' => $defaults['delete'], 283 '#process' => array('expand_checkboxes', 'content_access_disable_checkboxes'), 284 ); 285 $form['per_role']['clearer'] = array( 286 '#value' => '<br clear="all" />', 287 ); 288 $form['per_role']['view_own'] = array('#type' => 'checkboxes', 289 '#prefix' => '<div class="content_access-div">', 290 '#suffix' => '</div>', 291 '#options' => $roles, 292 '#title' => t('View own content'), 293 '#default_value' => $defaults['view_own'], 294 '#process' => array('expand_checkboxes', 'content_access_disable_checkboxes'), 295 ); 296 $form['per_role']['update_own'] = array('#type' => 'checkboxes', 297 '#prefix' => '<div class="content_access-div">', 298 '#suffix' => '</div>', 299 '#options' => $roles, 300 '#title' => t('Edit own content'), 301 '#default_value' => $defaults['update_own'], 302 '#process' => array('expand_checkboxes', 'content_access_disable_checkboxes'), 303 ); 304 $form['per_role']['delete_own'] = array('#type' => 'checkboxes', 305 '#prefix' => '<div class="content_access-div">', 306 '#suffix' => '</div>', 307 '#options' => $roles, 308 '#title' => t('Delete own content'), 309 '#default_value' => $defaults['delete_own'], 310 '#process' => array('expand_checkboxes', 'content_access_disable_checkboxes'), 311 ); 312 $form['per_role']['clearer'] = array( 313 '#value' => '<br clear="all" />', 314 ); 315 316 return $form; 317 } 318 319 /** 320 * Formapi #process callback, that disables checkboxes for roles without access to content 321 */ 322 function content_access_disable_checkboxes($element) { 323 $access_roles = content_access_get_permission_access('access content'); 324 $admin_roles = content_access_get_permission_access('administer nodes'); 325 foreach (element_children($element) as $key) { 326 if (!in_array($key, $access_roles) && !($key != DRUPAL_ANONYMOUS_RID && in_array(DRUPAL_AUTHENTICATED_RID, $access_roles))) { 327 $element[$key]['#disabled'] = TRUE; 328 $element[$key]['#default_value'] = FALSE; 329 $element[$key]['#prefix'] = '<span title="'. t("This role is lacking the permission '@perm', so it has no access.", array('@perm' => t('access content'))) .'">'; 330 $element[$key]['#suffix'] = "</span>"; 331 } 332 else if (in_array($key, $admin_roles) || ($key != DRUPAL_ANONYMOUS_RID && in_array(DRUPAL_AUTHENTICATED_RID, $admin_roles))) { 333 // Fix the checkbox to be enabled for users with administer node privileges 334 $element[$key]['#disabled'] = TRUE; 335 $element[$key]['#default_value'] = TRUE; 336 $element[$key]['#prefix'] = '<span title="'. t("This role has '@perm' permission, so access is granted.", array('@perm' => t('administer nodes'))) .'">'; 337 $element[$key]['#suffix'] = "</span>"; 338 } 339 } 340 return $element; 341 } 342 343 344 /** 345 * Formapi #after_build callback, that disables checkboxes for roles without access to content. 346 */ 347 function content_access_force_permissions($element, &$form_state) { 348 foreach (array('update', 'update_own', 'delete', 'delete_own') as $op) { 349 foreach (content_access_get_settings($op, $form_state['node']->type) as $rid) { 350 $element[$op][$rid]['#disabled'] = TRUE; 351 $element[$op][$rid]['#attributes']['disabled'] = 'disabled'; 352 $element[$op][$rid]['#value'] = TRUE; 353 $element[$op][$rid]['#prefix'] = '<span title="'. t("Permission is granted due to the content type's access control settings.") .'">'; 354 $element[$op][$rid]['#suffix'] = "</span>"; 355 } 356 } 357 return $element; 358 } 359 360 361 362 /** 363 * Submit callback for the user permissions form. 364 * Trigger changes to node permissions to rebuild our grants. 365 */ 366 function content_access_user_admin_perm_submit($form, $form_state) { 367 // Check for each content type, which has per node access activated 368 // whether permissions have been changed. 369 $types = array(); 370 foreach (array_filter(content_access_get_settings('per_node')) as $type => $value) { 371 foreach (_content_access_get_node_permissions($type) as $perm) { 372 foreach (user_roles() as $rid => $role) { 373 if (isset($form_state['values'][$rid]) && in_array($perm, $form['checkboxes'][$rid]['#default_value']) != in_array($perm, $form_state['values'][$rid])) { 374 //permission changed! 375 $types[$type] = node_get_types('name', $type); 376 continue 2; 377 } 378 } 379 } 380 } 381 if ($types && content_access_mass_update(array_keys($types))) { 382 drupal_set_message(format_plural(count($types), 383 'Permissions have been successfully rebuilt for the content type @types.', 384 'Permissions have been successfully rebuilt for the content types @types.', 385 array('@types' => implode(', ', $types)) 386 )); 387 } 388 } 389 390 function _content_access_get_node_permissions($type) { 391 return array_filter(array_map('content_access_get_permission_by_op', _content_access_get_operations(), array_fill(0, 6, $type))); 392 } 393 394 /** 395 * Gets the content access acl id of the node. 396 */ 397 function content_access_get_acl_id($node, $op) { 398 $acl_id = acl_get_id_by_name('content_access', $op .'_'. $node->nid); 399 if (!$acl_id) { 400 // Create one: 401 $acl_id = acl_create_new_acl('content_access', $op .'_'. $node->nid); 402 } 403 return $acl_id; 404 } 405 406 /** 407 * Detaches all our ACLs for the nodes of the given type. 408 */ 409 function _content_access_remove_acls($type) { 410 $result = db_query("SELECT n.nid FROM {node} n WHERE type = '%s'", $type); 411 while ($node = db_fetch_object($result)) { 412 acl_node_clear_acls($node->nid, 'content_access'); 413 } 414 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |