View source
<?php
if (module_exists('workflow_ng')) {
include_once drupal_get_path('module', 'content_access') . '/content_access.workflow_ng.inc';
}
function content_access_menu($may_cache) {
global $user;
$items = array();
if (!$may_cache) {
if (arg(0) == 'node' && is_numeric(arg(1))) {
$node = node_load(arg(1));
if (!empty($node) && content_access_get_settings('per_node', $node->type)) {
$items[] = array(
'path' => 'node/' . $node->nid . '/access',
'title' => t('Access control'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'content_access_page',
$node->nid,
),
'access' => user_access('grant content access') || user_access('grant own content access') && $user->uid == $node->uid,
'weight' => 5,
'type' => MENU_LOCAL_TASK,
);
}
}
if (arg(0) == 'admin' && arg(1) == 'content' && arg(2) == 'types' && arg(3)) {
$type = str_replace('-', '_', arg(3));
if ($type_name = node_get_types('name', $type)) {
$items[] = array(
'path' => 'admin/content/types/' . arg(3) . '/edit',
'title' => t('Edit'),
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items[] = array(
'path' => 'admin/content/types/' . arg(3) . '/access',
'title' => t('Access control'),
'description' => t('Configure content access control.'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'content_access_admin_settings',
$type,
),
'access' => user_access('administer nodes') && user_access('administer content types'),
'type' => MENU_LOCAL_TASK,
'weight' => 2,
);
}
}
}
return $items;
}
function content_access_perm() {
return array(
'grant content access',
'grant own content access',
);
}
function content_access_node_grants($account, $op) {
$return = array(
'content_access_rid' => array_keys($account->roles),
);
return $account->uid ? array(
'content_access_author' => array(
$account->uid,
),
) + $return : $return;
}
function content_access_page($nid) {
$node = node_load($nid);
drupal_set_title(check_plain($node->title));
foreach (array(
'view',
'update',
'delete',
) as $i) {
$defaults[$i] = content_access_per_node_setting($i, $node);
}
$form = content_access_page_form($defaults, $node);
$form['node'] = array(
'#type' => 'value',
'#value' => $node,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
'#weight' => 10,
);
return $form;
}
function content_access_page_form($defaults = array(), $node = FALSE) {
foreach (array(
'view',
'update',
'delete',
) as $op) {
if (!isset($defaults[$op])) {
$defaults[$op] = array();
}
}
$roles = content_access_get_roles_and_author();
$form['settings'] = array(
'#type' => 'fieldset',
'#title' => t('Role access control settings'),
'#collapsible' => TRUE,
);
if (!$node) {
$form['settings']['#description'] = t('Warning: No defaults are set; be sure to fill out all boxes appropriately.');
}
drupal_add_css(drupal_get_path('module', 'content_access') . '/content_access.css');
$form['settings']['view'] = array(
'#type' => 'checkboxes',
'#prefix' => '<div class="content_access-div">',
'#suffix' => '</div>',
'#options' => $roles,
'#title' => t('View'),
'#default_value' => $defaults['view'],
);
$form['settings']['update'] = array(
'#type' => 'checkboxes',
'#prefix' => '<div class="content_access-div">',
'#suffix' => '</div>',
'#options' => $roles,
'#title' => t('Edit'),
'#default_value' => $defaults['update'],
);
$form['settings']['delete'] = array(
'#type' => 'checkboxes',
'#prefix' => '<div class="content_access-div">',
'#suffix' => '</div>',
'#options' => $roles,
'#title' => t('Delete'),
'#default_value' => $defaults['delete'],
);
$form['settings']['clearer'] = array(
'#value' => '<br clear="all" />',
);
if (module_exists('acl') && $node) {
$form['acl'] = array(
'#type' => 'fieldset',
'#title' => t('User access control lists'),
'#description' => t('These settings allow you to grant access to specific users.'),
'#collapsible' => TRUE,
'#tree' => TRUE,
);
foreach (array(
'view',
'update',
'delete',
) as $op) {
$acl_id = acl_get_id_by_name('content_access', $op . '_' . $node->nid);
if (!$acl_id) {
$acl_id = acl_create_new_acl('content_access', $op . '_' . $node->nid);
}
acl_node_add_acl($node->nid, $acl_id, $op == 'view', $op == 'update', $op == 'delete', content_access_get_settings('priority', $node->type));
$form['acl'][$op] = acl_edit_form($acl_id, 'Grant ' . $op . ' access');
$form['acl'][$op]['#collapsed'] = !isset($_POST['acl'][$op]['add_button']) && !isset($_POST['acl'][$op]['delete_button']);
}
}
return $form;
}
function content_access_page_submit($form_id, $form_values) {
$node = $form_values['node'];
$settings = array();
foreach (array(
'view',
'update',
'delete',
) as $op) {
unset($form_values[$op][0]);
$settings[$op] = array_filter($form_values[$op]);
if (module_exists('acl') && isset($form_values['acl'][$op])) {
acl_save_form($form_values['acl'][$op]);
}
}
content_access_save_per_node_settings($node, $settings);
node_access_acquire_grants($node);
cache_clear_all();
drupal_set_message('Your changes have been saved.');
}
function content_access_admin_settings($type) {
$roles = content_access_get_roles_and_author();
$form['node'] = array(
'#type' => 'fieldset',
'#title' => t('Per node access control settings'),
'#collapsible' => TRUE,
'#description' => t('Optionally you can enable per node access control settings. ' . 'Configure access to the per node access settings at drupal\'s access control permission page.'),
);
$form['node']['per_node'] = array(
'#type' => 'checkbox',
'#title' => t('Enable per node access control settings'),
'#default_value' => content_access_get_settings('per_node', $type),
);
$form['defaults'] = array(
'#type' => 'fieldset',
'#title' => t('Default access control settings'),
'#collapsible' => TRUE,
'#description' => t('If per node settings are available, the default settings will be overridden by them.'),
);
drupal_add_css(drupal_get_path('module', 'content_access') . '/content_access.css');
$form['defaults']['view'] = array(
'#type' => 'checkboxes',
'#prefix' => '<div class="content_access-div">',
'#suffix' => '</div>',
'#options' => $roles,
'#title' => t('View'),
'#default_value' => content_access_get_settings('view', $type),
);
$form['defaults']['update'] = array(
'#type' => 'checkboxes',
'#prefix' => '<div class="content_access-div">',
'#suffix' => '</div>',
'#options' => $roles,
'#title' => t('Edit'),
'#default_value' => content_access_get_settings('update', $type),
);
$form['defaults']['delete'] = array(
'#type' => 'checkboxes',
'#prefix' => '<div class="content_access-div">',
'#suffix' => '</div>',
'#options' => $roles,
'#title' => t('Delete'),
'#default_value' => content_access_get_settings('delete', $type),
);
$form['defaults']['clearer'] = array(
'#value' => '<br clear="all" />',
);
$priority = content_access_get_settings('priority', $type);
$form['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['advanced']['priority'] = array(
'#type' => 'weight',
'#title' => t('Give node grants priority'),
'#default_value' => $priority,
'#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.'),
);
$form['type'] = array(
'#type' => 'value',
'#value' => $type,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
'#weight' => 10,
);
return $form;
}
function content_access_admin_settings_submit($form_id, $form_values) {
$per_node_old = content_access_get_settings('per_node', $form_values['type']);
$settings = content_access_get_settings();
foreach (content_access_available_settings() as $setting) {
if (is_array($form_values[$setting])) {
unset($form_values[$setting][0]);
$form_values[$setting] = array_filter($form_values[$setting]);
}
$settings[$setting][$form_values['type']] = $form_values[$setting];
}
content_access_set_settings($settings);
if (content_access_get_settings('per_node', $form_values['type']) && $per_node_old) {
$sql = "SELECT n.nid FROM {node} n LEFT JOIN {content_access} na ON na.nid = n.nid\n WHERE type = '%s' AND na.nid IS NULL";
}
else {
$sql = "SELECT n.nid FROM {node} n WHERE type = '%s'";
}
$remove_acls = !content_access_get_settings('per_node', $form_values['type']) && $per_node_old && module_exists('acl');
$result = db_query($sql, $form_values['type']);
while ($node = db_fetch_object($result)) {
if ($remove_acls) {
acl_node_clear_acls($node->nid, 'content_access');
}
node_access_acquire_grants(node_load($node->nid));
}
cache_clear_all();
drupal_set_message('Your changes have been saved.');
}
function content_access_node_access_records($node, $optimize = TRUE) {
if (content_access_disabling()) {
return;
}
if (content_access_get_settings('per_node', $node->type)) {
$grants = array();
foreach (array(
'view',
'update',
'delete',
) as $op) {
foreach (content_access_per_node_setting($op, $node) as $rid) {
$grants[$rid]['grant_' . $op] = 1;
}
}
foreach ($grants as $rid => $grant) {
$grants[$rid] = content_access_proccess_grant($grant, $rid, $node);
}
}
else {
$grants = content_access_get_default_grant($node);
}
if (empty($grants)) {
$grants[] = array(
'grant_view' => 0,
'realm' => 'content_access_rid',
'gid' => 0,
);
}
else {
if ($optimize) {
content_access_optimize_grants($grants, $node);
}
}
return $grants;
}
function content_access_nodeapi($node, $op, $teaser, $page) {
if ($op == 'delete') {
db_query("DELETE FROM {content_access} WHERE nid = %d", $node->nid);
}
}
function content_access_enable() {
node_access_rebuild();
}
function content_access_enabled() {
return !content_access_disabling();
}
function content_access_disable() {
content_access_disabling(TRUE);
node_access_rebuild();
}
function content_access_disabling($set = NULL) {
static $disabling = FALSE;
if (isset($set)) {
$disabling = $set;
}
return $disabling;
}
function content_access_get_settings($return = 'all', $type = NULL) {
if ($return == 'all') {
return variable_get('content_access_settings', array());
}
if (isset($type)) {
$settings = content_access_get_settings($return);
return isset($settings[$type]) ? $settings[$type] : content_access_get_setting_defaults($return, $type);
}
if (!isset($type)) {
$settings = content_access_get_settings();
return isset($settings[$return]) ? $settings[$return] : array();
}
return array();
}
function content_access_set_settings($settings) {
foreach (content_access_available_settings() as $setting) {
if (isset($settings[$setting])) {
foreach ($settings[$setting] as $type => $value) {
if (!isset($value)) {
unset($settings[$setting][$type]);
}
}
}
}
variable_set('content_access_settings', $settings);
}
function content_access_available_settings() {
return array(
'view',
'update',
'delete',
'per_node',
'priority',
);
}
function content_access_get_setting_defaults($setting, $type) {
switch ($setting) {
default:
return array();
case 'view':
return array(
DRUPAL_ANONYMOUS_RID,
DRUPAL_AUTHENTICATED_RID,
);
case 'delete':
case 'update':
$roles = content_access_get_permission_access('edit ' . $type . ' content');
if (count(array_diff(array(
DRUPAL_ANONYMOUS_RID,
DRUPAL_AUTHENTICATED_RID,
), content_access_get_permission_access('edit own ' . $type . ' content'))) == 0) {
$roles[] = 'author';
}
return $roles;
case 'priority':
return 0;
}
}
function content_access_get_permission_access($perm) {
static $roles = array();
if (!isset($roles[$perm])) {
$roles[$perm] = array_keys(user_roles(0, $perm));
}
return $roles[$perm];
}
function content_access_get_roles_and_author() {
static $roles;
if (!isset($roles)) {
$roles = array(
'author' => t('author'),
) + array_map('filter_xss_admin', user_roles());
}
return $roles;
}
function content_access_get_default_grant($node) {
static $defaults = array();
if (!isset($defaults[$node->type])) {
$grants = array();
foreach (array(
'view',
'update',
'delete',
) as $op) {
foreach (content_access_get_settings($op, $node->type) as $rid) {
$grants[$rid]['grant_' . $op] = 1;
}
}
foreach ($grants as $rid => $grant) {
$grants[$rid] = content_access_proccess_grant($grant, $rid, $node);
}
$defaults[$node->type] = $grants;
}
else {
if (isset($defaults[$node->type]['author'])) {
$defaults[$node->type]['author']['gid'] = $node->uid;
}
}
return $defaults[$node->type];
}
function content_access_proccess_grant($grant, $rid, $node) {
$grant['realm'] = $rid == 'author' ? 'content_access_author' : 'content_access_rid';
$grant['gid'] = $rid == 'author' ? $node->uid : $rid;
$grant['priority'] = content_access_get_settings('priority', $node->type);
return $grant;
}
function content_access_per_node_setting($op, $node, $settings = NULL) {
static $grants = array();
if (isset($settings)) {
$grants[$node->nid] = $settings;
return;
}
if (!isset($grants[$node->nid])) {
$grants[$node->nid] = content_access_get_per_node_settings($node);
}
return isset($grants[$node->nid][$op]) ? $grants[$node->nid][$op] : content_access_get_settings($op, $node->type);
}
function content_access_save_per_node_settings($node, $settings) {
db_query("UPDATE {content_access} SET settings = '%s' WHERE nid = %d", serialize($settings), $node->nid);
if (!db_affected_rows()) {
db_query("INSERT INTO {content_access} (nid, settings) VALUES(%d, '%s')", $node->nid, serialize($settings));
}
content_access_per_node_setting(NULL, $node, $settings);
}
function content_access_get_per_node_settings($node) {
$settings = db_result(db_query("SELECT settings FROM {content_access} WHERE nid = %d", $node->nid));
if (!$settings) {
return array();
}
return unserialize($settings);
}
function content_access_optimize_grants(&$grants, $node) {
foreach (array(
'view',
'update',
'delete',
) as $op) {
${$op} = array();
}
foreach ($grants as $key => $grant) {
foreach (array(
'view',
'update',
'delete',
) as $op) {
if ($grant['grant_' . $op]) {
${$op}[] = $key;
}
}
}
$all = array(
DRUPAL_ANONYMOUS_RID,
DRUPAL_AUTHENTICATED_RID,
);
if (count(array_diff($all, $view)) == 0) {
$view = array(
'all',
);
$grants['all'] = array(
'realm' => 'all',
'gid' => 0,
'grant_view' => 1,
'grant_update' => 0,
'grant_delete' => 0,
'priority' => content_access_get_settings('priority', $node->type),
);
}
$edit_perm_roles = content_access_get_permission_access('edit ' . $node->type . ' content');
$edit_own_roles = content_access_get_permission_access('edit own ' . $node->type . ' content');
if (in_array(DRUPAL_AUTHENTICATED_RID, $edit_own_roles)) {
$edit_perm_roles[] = 'author';
}
foreach (array(
'update',
'delete',
) as $op) {
${$op} = array_diff(${$op}, $edit_perm_roles);
}
foreach ($grants as $key => $grant) {
foreach (array(
'view',
'update',
'delete',
) as $op) {
if ($grant['grant_' . $op] && in_array($key, ${$op})) {
continue 2;
}
}
unset($grants[$key]);
}
}
function content_access_node_type($op, $info) {
switch ($op) {
case 'delete':
$settings = content_access_get_settings();
foreach (content_access_available_settings() as $setting) {
unset($settings[$setting][$info->type]);
}
content_access_set_settings($settings);
break;
case 'update':
if (!empty($info->old_type) && $info->old_type != $info->type) {
$settings = content_access_get_settings();
foreach (content_access_available_settings() as $setting) {
$settings[$setting][$info->type] = $settings[$setting][$info->old_type];
unset($settings[$setting][$info->old_type]);
}
content_access_set_settings($settings);
}
break;
}
}
function content_access_node_access_explain($row) {
static $roles;
if (!isset($roles)) {
$roles = user_roles();
}
if (!$row->gid && $row->realm == 'content_access_rid') {
return t('Content access: No access is granted.');
}
switch ($row->realm) {
case 'content_access_author':
return t('Content access: author of the content can access');
case 'content_access_rid':
return t('Content access: %role can access', array(
'%role' => $roles[$row->gid],
));
}
}