function _devel_node_access_explain_access

Helper function that mimicks node.module's node_access() function.

Unfortunately, this needs to be updated manually whenever node.module changes!

Return value

An array suitable for theming with theme_dna_permission().

2 calls to _devel_node_access_explain_access()
devel_node_access_block_view in ./devel_node_access.module
Implements hook_block_view().
devel_node_access_user_ajax in ./devel_node_access.module
Page callback for node access by user block ajax.

File

./devel_node_access.module, line 1169

Code

function _devel_node_access_explain_access($op, $node, $account = NULL) {
    global $user;
    if (is_numeric($node) && !($node = node_load($node))) {
        return array(
            FALSE,
            '???',
            t('Unable to load the node – this should never happen!'),
        );
    }
    if (!in_array($op, array(
        'view',
        'update',
        'delete',
        'create',
    ), TRUE)) {
        return array(
            FALSE,
            t('!NO: invalid $op', array(
                '!NO' => t('NO'),
            )),
            t("'@op' is an invalid operation!", array(
                '@op' => $op,
            )),
        );
    }
    if ($op == 'create' && is_object($node)) {
        $node = $node->type;
    }
    if (!empty($account)) {
        // To try to get the most authentic result we impersonate the given user!
        // This may reveal bugs in other modules, leading to contradictory results.
        $saved_user = $user;
        drupal_save_session(FALSE);
        $user = $account;
        $result = _devel_node_access_explain_access($op, $node, NULL);
        $user = $saved_user;
        drupal_save_session(TRUE);
        $second_opinion = node_access($op, $node, $account);
        if ($second_opinion != $result[0]) {
            $result[1] .= '<span class="' . ($second_opinion ? 'ok' : 'error') . '" title="Core seems to disagree on this item. This is a bug in either DNA or Core and should be fixed! Try to look at this node as this user and check whether there is still disagreement.">*</span>';
        }
        return $result;
    }
    $variables = array(
        '!NO' => t('NO'),
        '!YES' => t('YES'),
        '!bypass_node_access' => t('bypass node access'),
        '!access_content' => t('access content'),
    );
    if (user_access('bypass node access')) {
        return array(
            TRUE,
            t('!YES: bypass node access', $variables),
            t("!YES: This user has the '!bypass_node_access' permission and may do everything with nodes.", $variables),
        );
    }
    if (!user_access('access content')) {
        return array(
            FALSE,
            t('!NO: access content', $variables),
            t("!NO: This user does not have the '!access_content' permission and is denied doing anything with content.", $variables),
        );
    }
    foreach (module_implements('node_access') as $module) {
        $function = $module . '_node_access';
        if (function_exists($function)) {
            $result = $function($node, $op, $user);
            if ($module == 'node') {
                $module = 'node (permissions)';
            }
            if (isset($result)) {
                if ($result === NODE_ACCESS_DENY) {
                    $denied_by[] = $module;
                }
                elseif ($result === NODE_ACCESS_ALLOW) {
                    $allowed_by[] = $module;
                }
                $access[] = $result;
            }
        }
    }
    $variables += array(
        '@deniers' => empty($denied_by) ? NULL : implode(', ', $denied_by),
        '@allowers' => empty($allowed_by) ? NULL : implode(', ', $allowed_by),
    );
    if (!empty($denied_by)) {
        $variables += array(
            '%module' => $denied_by[0] . (count($denied_by) > 1 ? '+' : ''),
        );
        return array(
            FALSE,
            t('!NO: by %module', $variables),
            empty($allowed_by) ? t("!NO: hook_node_access() of the following module(s) denies this: @deniers.", $variables) : t("!NO: hook_node_access() of the following module(s) denies this: @deniers &ndash; even though the following module(s) would allow it: @allowers.", $variables),
        );
    }
    if (!empty($allowed_by)) {
        $variables += array(
            '%module' => $allowed_by[0] . (count($allowed_by) > 1 ? '+' : ''),
            '!view_own_unpublished_content' => t('view own unpublished content'),
        );
        return array(
            TRUE,
            t('!YES: by %module', $variables),
            t("!YES: hook_node_access() of the following module(s) allows this: @allowers.", $variables),
        );
    }
    if ($op == 'view' && !$node->status && user_access('view own unpublished content') && $user->uid == $node->uid && $user->uid != 0) {
        return array(
            TRUE,
            t('!YES: view own unpublished content', $variables),
            t("!YES: The node is unpublished, but the user has the '!view_own_unpublished_content' permission.", $variables),
        );
    }
    if ($op != 'create' && $node->nid) {
        if (node_access($op, $node)) {
            // delegate this part
            $variables['@node_access_table'] = '{node_access}';
            return array(
                TRUE,
                t('!YES: @node_access_table', $variables),
                t('!YES: Node access allows this based on one or more records in the @node_access_table table (see the other DNA block!).', $variables),
            );
        }
    }
    return array(
        FALSE,
        t('!NO: no reason', $variables),
        t("!NO: None of the checks resulted in allowing this, so it's denied.", $variables) . ($op == 'create' ? ' ' . t('This is most likely due to a withheld permission.') : ''),
    );
}