View source
<?php
require_once dirname(__FILE__) . '/module_grants.node.inc';
function module_grants_help($path, $arg) {
switch ($path) {
case 'admin/help#module_grants':
$s = t('For help and full documentation see the <a href="@module_grants">Module Grants project page</a>', array(
'@module_grants' => url('http://drupal.org/project/module_grants'),
));
break;
}
return empty($s) ? '' : '<p>' . $s . '</p>';
}
function module_grants_menu() {
$items = array();
$items['admin/config/system/module_grants'] = array(
'title' => 'Module grants',
'description' => 'Configure how node access modules interact and customise the <em>Accessible-content</em> page.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'module_grants_admin_configure',
),
'access arguments' => array(
'administer site configuration',
),
'file' => 'module_grants.admin.inc',
);
return $items;
}
function module_grants_module_implements_alter(&$implementations, $hook) {
if ($hook == 'node_access') {
$mg_name = 'module_grants';
$mg_group = $implementations[$mg_name];
unset($implementations[$mg_name]);
module_grants_set_node_access_implementations($implementations);
foreach ($implementations as $module => $group) {
unset($implementations[$module]);
}
$implementations[$mg_name] = $mg_group;
}
else {
if ($hook == 'query_node_access_alter') {
unset($implementations['node']);
}
else {
if ($hook == 'query_entity_field_access_alter') {
unset($implementations['node']);
}
}
}
}
function module_grants_set_node_access_implementations($implements = NULL) {
$implementations =& drupal_static(__FUNCTION__);
if (isset($implements)) {
cache_set('module_implements_node_access', $implements, 'cache_bootstrap');
}
if (empty($implementations)) {
$implementations = cache_get('module_implements_node_access', 'cache_bootstrap');
if ($implementations === FALSE) {
$implementations = array();
}
else {
$implementations = $implementations->data;
}
}
return $implementations;
}
function module_grants_invoke_node_access($node, $op, $account) {
$hook = 'node_access';
$modules = array_keys(module_grants_set_node_access_implementations());
$return = array();
foreach ($modules as $module) {
$result = module_invoke($module, $hook, $node, $op, $account);
if (isset($result) && is_array($result)) {
$return = array_merge_recursive($return, $result);
}
elseif (isset($result)) {
$return[] = $result;
}
}
return $return;
}
function module_grants_is_disabled() {
return variable_get('module_grants_OR_modules', FALSE) || count(module_implements('node_grants')) <= 1;
}
function module_grants_node_access($node, $op, $account) {
return _module_grants_node_access($op, $node, $account) ? NODE_ACCESS_ALLOW : NODE_ACCESS_DENY;
}
function module_grants_query_node_access_alter(QueryAlterableInterface $query) {
if (module_grants_is_disabled()) {
_node_query_node_access_alter($query, 'node');
}
else {
_module_grants_node_query_node_access_alter($query, 'node');
}
}
function module_grants_query_entity_field_access_alter(QueryAlterableInterface $query) {
if (module_grants_is_disabled()) {
_node_query_node_access_alter($query, 'entity');
}
else {
_module_grants_node_query_node_access_alter($query, 'entity');
}
}
function module_grants_node_access_records_alter(&$grants, $node) {
module_grants_clear_node_access_cache();
}
function _module_grants_apply_node_access_grants_conditions($module, $grants, $grants_conditions, $nalias = NULL) {
$grants_conditions
->condition(db_and()
->condition('gid', 0)
->condition('realm', 'all'));
$nalias = isset($nalias) ? $nalias . '.' : '';
foreach ($grants as $realm => $gids) {
foreach ($gids as $gid) {
$grants_conditions
->where($nalias . 'gid=' . $gid . ' AND ' . $nalias . 'realm=\'' . $realm . '\'');
}
}
}
function module_grants_get_node_access_result($node, $op, $account) {
$module_grants = module_grants_by_module($op, $account);
if (count(array_filter($module_grants)) == 0) {
$query = _module_grants_get_node_access_query($node, $op);
$query
->condition(db_and()
->condition('gid', 0)
->condition('realm', 'all'));
return (bool) $query
->execute()
->fetchField();
}
else {
foreach ($module_grants as $module => $grants) {
if (variable_get('module_grants_lenient', TRUE) && count(module_grants_get_node_access_realms_for_module($module, $node)) == 0) {
continue;
}
$query = _module_grants_get_node_access_query($node, $op);
$grant_conditions = db_or();
_module_grants_apply_node_access_grants_conditions($module, $grants, $grant_conditions);
$query
->condition($grant_conditions);
$result = (bool) $query
->execute()
->fetchField();
if (!$result) {
return false;
}
}
return true;
}
}
function _module_grants_get_node_access_query($node, $op) {
$query = db_select('node_access');
$query
->addExpression('1');
$query
->condition('grant_' . $op, 1, '>=');
$nids = db_or()
->condition('nid', $node->nid);
if ($node->status) {
$nids
->condition('nid', 0);
}
$query
->condition($nids);
$query
->range(0, 1);
return $query;
}
function module_grants_get_node_access_view_all_nodes_result($account) {
$op = 'view';
$module_grants = module_grants_by_module($op, $account);
if (count(array_filter($module_grants)) == 0) {
$query = _module_grants_get_node_access_view_all_nodes_query();
$query
->condition(db_and()
->condition('gid', 0)
->condition('realm', 'all'));
return (bool) $query
->execute()
->fetchField();
}
else {
foreach ($module_grants as $module => $grants) {
if (variable_get('module_grants_lenient', TRUE) && count(module_grants_get_node_access_realms_for_module($module)) == 0) {
continue;
}
$query = _module_grants_get_node_access_view_all_nodes_query();
$grant_conditions = db_or();
_module_grants_apply_node_access_grants_conditions($module, $grants, $grant_conditions);
$query
->condition($grant_conditions);
$result = $query
->execute()
->fetchField();
if (!$result) {
return false;
}
}
return true;
}
}
function _module_grants_get_node_access_view_all_nodes_query() {
$query = db_select('node_access');
$query
->addExpression('COUNT(*)');
$query
->condition('nid', 0)
->condition('grant_view', 1, '>=');
return $query;
}
function module_grants_apply_subquery_for_node_query_node_access_alter($query, $type, $base_table, $op, $account) {
$tables = $query
->getTables();
$all_grants = module_grants_by_module($op, $account);
if ($type == 'entity') {
$node_conditions = db_and();
}
foreach ($tables as $nalias => $tableinfo) {
$table = $tableinfo['table'];
if (!$table instanceof SelectQueryInterface && $table == $base_table) {
$subquery_condition = db_and();
$module_grants_na_count = 0;
foreach ($all_grants as $module => $grants) {
$module_na_realms = module_grants_get_node_access_realms_for_module($module);
if (variable_get('module_grants_lenient', TRUE) && empty($module_na_realms)) {
continue;
}
$module_grants_na_count++;
$module_grants_na_alias = 'mgna' . $module_grants_na_count;
$subquery = db_select('node_access', $module_grants_na_alias)
->fields($module_grants_na_alias, array(
'nid',
));
$grant_conditions = db_or();
if (variable_get('module_grants_lenient', TRUE)) {
$lenient_na_alias = 'mglna' . $module_grants_na_count;
$lenient_subquery = db_select('node_access', $lenient_na_alias)
->fields($lenient_na_alias, array(
'gid',
))
->condition(db_or()
->where("{$lenient_na_alias}.nid = {$module_grants_na_alias}.nid")
->condition("{$lenient_na_alias}.nid", 0))
->condition("{$lenient_na_alias}.realm", $module_na_realms, 'IN');
$grant_conditions
->notExists($lenient_subquery);
}
_module_grants_apply_node_access_grants_conditions($module, $grants, $grant_conditions, $module_grants_na_alias);
$subquery
->condition($grant_conditions);
$subquery
->condition("{$module_grants_na_alias}.grant_" . $op, 1, '>=');
$field = 'nid';
if ($type == 'entity') {
$base_alias = $nalias;
$field = 'entity_id';
}
$subquery
->condition(db_or()
->where("{$nalias}.{$field} = {$module_grants_na_alias}.nid")
->condition("{$module_grants_na_alias}.nid", 0));
$subquery_condition
->exists($subquery);
}
if (count($subquery_condition)) {
if ($type == 'entity') {
$node_conditions
->condition($subquery_condition);
}
else {
$query
->condition($subquery_condition);
}
}
}
}
if ($type == 'entity' && count($node_conditions)) {
$node_conditions
->condition("{$base_alias}.entity_type", 'node');
$or = db_or();
$or
->condition($node_conditions);
$or
->condition("{$base_alias}.entity_type", 'node', '<>');
$query
->condition($or);
}
}
function module_grants_by_module($op, $account = NULL) {
if (!isset($account)) {
$account = $GLOBALS['user'];
}
$grants = module_invoke_all('node_grants', $account, $op);
drupal_alter('node_grants', $grants, $account, $op);
$all_grants = array();
foreach (module_implements('node_grants') as $module) {
$module_grants = array();
foreach ($grants as $realm => $gids) {
if (module_grants_is_realm_by_module($realm, $module)) {
$module_grants[$realm] = $gids;
unset($grants[$realm]);
}
}
$all_grants[$module] = $module_grants;
}
return $all_grants;
}
function module_grants_is_realm_by_module($realm, $module) {
$realm_functions =& drupal_static(__FUNCTION__);
if (!isset($realm_functions)) {
$realm_functions = array();
$access_modules = module_implements('node_grants');
foreach ($access_modules as $module_name) {
$realm_functions[$module_name] = function ($realm) use ($module_name) {
return _modules_grants_prefix_match($module_name, $realm);
};
}
drupal_alter('module_grants_realm_function_register', $realm_functions);
}
return isset($realm_functions[$module]) ? $realm_functions[$module]($realm) : false;
}
function _modules_grants_prefix_match($prefix, $realm) {
return strncmp($prefix, $realm, strlen($prefix)) == 0;
}
function module_grants_get_node_access_realms_for_module($module, $node = NULL) {
$node_access_realms_for_module =& drupal_static(__FUNCTION__);
$nid = $node ? $node->nid : 0;
if (!isset($node_access_realms_for_module[$module][$nid])) {
$node_access_realms = module_grants_get_node_access_realms($node);
$node_access_realms_for_module[$module][$nid] = array();
foreach ($node_access_realms as $realm => $count) {
if (module_grants_is_realm_by_module($realm, $module)) {
$node_access_realms_for_module[$module][$nid][] = $realm;
}
}
}
return $node_access_realms_for_module[$module][$nid];
}
function module_grants_get_node_access_realms($node = NULL) {
$node_access_realms =& drupal_static(__FUNCTION__);
$nid = $node ? $node->nid : 0;
if (!isset($node_access_realms[$nid])) {
$query = db_select('node_access', 'na')
->fields('na', array(
'realm',
));
$query
->addExpression('COUNT(na.gid)', 'gid_count');
if ($node) {
$nid_condition = db_or()
->condition('na.nid', $node->nid)
->condition('na.nid', 0);
$query
->condition($nid_condition);
}
$query
->groupBy('na.realm');
$node_access_realms[$nid] = $query
->execute()
->fetchAllKeyed();
}
return $node_access_realms[$nid];
}
function module_grants_clear_node_access_cache() {
drupal_static_reset('module_grants_get_node_access_realms');
drupal_static_reset('module_grants_get_node_access_realms_for_module');
}