function devel_node_access_block_view

Implements hook_block_view().

File

./devel_node_access.module, line 552

Code

function devel_node_access_block_view($delta) {
    global $user;
    global $theme_key;
    static $block1_visible, $hint = '';
    if (!isset($block1_visible)) {
        $block1_visible = db_query("SELECT status FROM {block} WHERE module = 'devel_node_access' AND delta = 'dna_user' AND theme = :theme", array(
            ':theme' => $theme_key,
        ))->fetchField();
        if (!$block1_visible) {
            $hint = t('For per-user access permissions enable the <a href="@link">%DNAbU block</a>.', array(
                '@link' => url('admin/structure/block'),
                '%DNAbU' => t('Devel Node Access by User'),
            ));
        }
    }
    if (!user_access(DNA_ACCESS_VIEW)) {
        return;
    }
    $output = array();
    switch ($delta) {
        case 'dna_node':
            if (!count(dna_visible_nodes())) {
                return;
            }
            // include rows where nid == 0
            $nids = array_merge(array(
                0 => 0,
            ), dna_visible_nodes());
            $query = db_select('node_access', 'na');
            $query->fields('na')
                ->condition('na.nid', $nids, 'IN')
                ->orderBy('na.nid')
                ->orderBy('na.realm')
                ->orderBy('na.gid');
            $nodes = node_load_multiple($nids);
            if (!variable_get('devel_node_access_debug_mode', FALSE)) {
                $headers = array(
                    t('node'),
                    t('realm'),
                    t('gid'),
                    t('view'),
                    t('update'),
                    t('delete'),
                    t('explained'),
                );
                $rows = array();
                foreach ($query->execute() as $row) {
                    $explained = module_invoke_all('node_access_explain', $row);
                    $rows[] = array(
                        empty($row->nid) ? '0' : '<a href="#node-' . $row->nid . '">' . _devel_node_access_get_node_title($nodes[$row->nid], TRUE) . '</a>',
                        $row->realm,
                        $row->gid,
                        $row->grant_view,
                        $row->grant_update,
                        $row->grant_delete,
                        implode('<br />', $explained),
                    );
                }
                $output[] = array(
                    '#theme' => 'table',
                    '#header' => $headers,
                    '#rows' => $rows,
                    '#attributes' => array(
                        'style' => 'text-align: left',
                    ),
                );
                $hint = t('To see more details enable <a href="@debug_mode">debug mode</a>.', array(
                    '@debug_mode' => url('admin/config/development/devel', array(
                        'fragment' => 'edit-devel-node-access',
                    )),
                )) . (empty($hint) ? '' : ' ' . $hint);
            }
            else {
                $tr = 't';
                $variables = array(
                    '!na' => '{node_access}',
                );
                $states = array(
                    'default' => array(
                        t('default'),
                        'ok',
                        t('Default grant supplied by core in the absence of any other non-empty grants; in !na.', $variables),
                    ),
                    'ok' => array(
                        t('ok'),
                        'ok',
                        t('Highest priority grant; in !na.', $variables),
                    ),
                    'removed' => array(
                        t('removed'),
                        '',
                        t('Was removed in @func; not in !na.', $variables + array(
                            '@func' => 'hook_node_access_records_alter()',
                        )),
                    ),
                    'static' => array(
                        t('static'),
                        'ok',
                        t('Non-standard grant in !na.', $variables),
                    ),
                    'unexpected' => array(
                        t('unexpected'),
                        'warning',
                        t('The 0/all/0/... grant applies to all nodes and all users -- usually it should not be present in !na if any node access module is active!'),
                    ),
                    'ignored' => array(
                        t('ignored'),
                        'warning',
                        t('Lower priority grant; not in !na and thus ignored.', $variables),
                    ),
                    'empty' => array(
                        t('empty'),
                        'warning',
                        t('Does not grant any access, but could block lower priority grants; not in !na.', $variables),
                    ),
                    'wrong' => array(
                        t('wrong'),
                        'error',
                        t('Is rightfully in !na but at least one access flag is wrong!', $variables),
                    ),
                    'missing' => array(
                        t('missing'),
                        'error',
                        t("Should be in !na but isn't!", $variables),
                    ),
                    'removed!' => array(
                        t('removed!'),
                        'error',
                        t('Was removed in @func; should NOT be in !na!', $variables + array(
                            '@func' => 'hook_node_access_records_alter()',
                        )),
                    ),
                    'illegitimate' => array(
                        t('illegitimate'),
                        'error',
                        t('Should NOT be in !na because of lower priority!', $variables),
                    ),
                    'alien' => array(
                        t('alien'),
                        'error',
                        t('Should NOT be in !na because of unknown origin!', $variables),
                    ),
                );
                $active_states = array(
                    'default',
                    'ok',
                    'static',
                    'unexpected',
                    'wrong',
                    'illegitimate',
                    'alien',
                );
                $headers = array(
                    t('node'),
                    t('prio'),
                    t('status'),
                    t('realm'),
                    t('gid'),
                    t('view'),
                    t('update'),
                    t('delete'),
                    t('explained'),
                );
                $headers = _devel_node_access_format_row($headers);
                $active_grants = array();
                foreach ($query->execute() as $active_grant) {
                    $active_grants[$active_grant->nid][$active_grant->realm][$active_grant->gid] = $active_grant;
                }
                $all_grants = $checked_grants = $published_nid = array();
                foreach ($nids as $nid) {
                    $acquired_grants_nid = array();
                    if ($node = node_load($nid)) {
                        // Check node_access_acquire_grants().
                        $grants = _devel_node_access_module_invoke_all('node_access_records', $node);
                        // Check drupal_alter('node_access_records').
                        $data = _devel_node_access_nar_alter($grants, $node);
                        
                        /* (This was the D6 implementation that didn't analyze the hook_node_access_records_alter() details.)
                           if (!empty($grants)) {
                             $top_priority = NULL;
                             foreach ($grants as $grant) {
                               $priority = intval($grant['priority']);
                               $top_priority = (isset($top_priority) ? max($top_priority, $priority) : $priority);
                               $grant['priority'] = (isset($grant['priority']) ? $priority : '&ndash;&nbsp;');
                               $acquired_grants_nid[$priority][$grant['realm']][$grant['gid']] = $grant + array(
                                 '#title'  => _devel_node_access_get_node_title($node, TRUE),
                                 '#module' => (isset($grant['#module']) ? $grant['#module'] : ''),
                               );
                             }
                             krsort($acquired_grants_nid);
                           }
                           /*/
                        // (This is the new D7 implementation; it retains backward compatibility.)
                        if (!empty($data)) {
                            foreach ($data as $data_by_realm) {
                                foreach ($data_by_realm as $data_by_realm_gid) {
                                    // by gid
                                    if (isset($data_by_realm_gid['current'])) {
                                        $grant = $data_by_realm_gid['current'];
                                    }
                                    elseif (isset($data_by_realm_gid['original'])) {
                                        $grant = $data_by_realm_gid['original'];
                                        $grant['#removed'] = 1;
                                    }
                                    else {
                                        continue;
                                    }
                                    $priority = intval($grant['priority']);
                                    $top_priority = isset($top_priority) ? max($top_priority, $priority) : $priority;
                                    $grant['priority'] = isset($grant['priority']) ? $priority : '&ndash;&nbsp;';
                                    $grant['history'] = $data_by_realm_gid;
                                    $acquired_grants_nid[$priority][$grant['realm']][$grant['gid']] = $grant + array(
                                        '#title' => _devel_node_access_get_node_title($node),
                                        '#module' => isset($grant['#module']) ? $grant['#module'] : '',
                                    );
                                }
                            }
                            krsort($acquired_grants_nid);
                        }
                        
                        /**/
                        
                        //dpm($acquired_grants_nid, "acquired_grants_nid =");
                        // Check node_access_grants().
                        $published_nid[$nid] = $node->status;
                        if ($node->nid) {
                            foreach (array(
                                'view',
                                'update',
                                'delete',
                            ) as $op) {
                                $grants = _devel_node_access_module_invoke_all('node_grants', $user, $op);
                                // Call all hook_node_grants_alter() implementations.
                                $ng_alter_datas[$op] = _devel_node_access_ng_alter($grants, $user, $op);
                                $checked_grants[$nid][$op] = array_merge(array(
                                    'all' => array(
                                        0,
                                    ),
                                ), $grants);
                            }
                        }
                    }
                    // Check for grants in the node_access table that aren't returned by
                    // node_access_acquire_grants().
                    if (isset($active_grants[$nid])) {
                        foreach ($active_grants[$nid] as $realm => $active_grants_realm) {
                            foreach ($active_grants_realm as $gid => $active_grant) {
                                $found = FALSE;
                                $count_nonempty_grants = 0;
                                foreach ($acquired_grants_nid as $priority => $acquired_grants_nid_priority) {
                                    if (isset($acquired_grants_nid_priority[$realm][$gid])) {
                                        $found = TRUE;
                                    }
                                }
                                if ($acquired_grants_nid_priority = reset($acquired_grants_nid)) {
                                    // highest priority only
                                    foreach ($acquired_grants_nid_priority as $acquired_grants_nid_priority_realm) {
                                        foreach ($acquired_grants_nid_priority_realm as $acquired_grants_nid_priority_realm_gid) {
                                            $count_nonempty_grants += !empty($acquired_grants_nid_priority_realm_gid['grant_view']) || !empty($acquired_grants_nid_priority_realm_gid['grant_update']) || !empty($acquired_grants_nid_priority_realm_gid['grant_delete']);
                                        }
                                    }
                                }
                                $fixed_grant = (array) $active_grant;
                                if ($count_nonempty_grants == 0 && $realm == 'all' && $gid == 0) {
                                    $fixed_grant += array(
                                        'priority' => '&ndash;',
                                        'state' => 'default',
                                    );
                                }
                                elseif (!$found) {
                                    $acknowledged = _devel_node_access_module_invoke_all('node_access_acknowledge', $fixed_grant);
                                    if (empty($acknowledged)) {
                                        // No module acknowledged this record, mark it as alien.
                                        $fixed_grant += array(
                                            'priority' => '?',
                                            'state' => 'alien',
                                        );
                                    }
                                    else {
                                        // At least one module acknowledged the record. Attribute it
                                        // to the first one.
                                        $acknowledged_keys = array_keys($acknowledged);
                                        $fixed_grant += array(
                                            'priority' => '&ndash;',
                                            'state' => 'static',
                                            '#module' => reset($acknowledged_keys),
                                        );
                                    }
                                }
                                else {
                                    continue;
                                }
                                $fixed_grant += array(
                                    'nid' => $nid,
                                    '#title' => _devel_node_access_get_node_title($node),
                                );
                                $all_grants[] = $fixed_grant;
                            }
                        }
                    }
                    // Order grants and evaluate their status.
                    foreach ($acquired_grants_nid as $priority => $acquired_grants_priority) {
                        ksort($acquired_grants_priority);
                        foreach ($acquired_grants_priority as $realm => $acquired_grants_realm) {
                            ksort($acquired_grants_realm);
                            foreach ($acquired_grants_realm as $gid => $acquired_grant) {
                                if ($priority == $top_priority) {
                                    if (empty($acquired_grant['grant_view']) && empty($acquired_grant['grant_update']) && empty($acquired_grant['grant_delete'])) {
                                        $acquired_grant['state'] = 'empty';
                                    }
                                    else {
                                        if (isset($active_grants[$nid][$realm][$gid])) {
                                            $acquired_grant['state'] = isset($acquired_grant['#removed']) ? 'removed!' : 'ok';
                                        }
                                        else {
                                            $acquired_grant['state'] = isset($acquired_grant['#removed']) ? 'removed' : 'missing';
                                        }
                                        if ($acquired_grant['state'] == 'ok') {
                                            foreach (array(
                                                'view',
                                                'update',
                                                'delete',
                                            ) as $op) {
                                                $active_grant = (array) $active_grants[$nid][$realm][$gid];
                                                if (empty($acquired_grant["grant_{$op}"]) != empty($active_grant["grant_{$op}"])) {
                                                    $acquired_grant["grant_{$op}!"] = $active_grant["grant_{$op}"];
                                                }
                                            }
                                        }
                                    }
                                }
                                else {
                                    $acquired_grant['state'] = isset($active_grants[$nid][$realm][$gid]) ? 'illegitimate' : 'ignored';
                                }
                                $all_grants[] = $acquired_grant + array(
                                    'nid' => $nid,
                                );
                            }
                        }
                    }
                }
                // Fill in the table rows.
                $rows = array();
                $error_count = 0;
                foreach ($all_grants as $grant) {
                    $row = new stdClass();
                    $row->nid = $grant['nid'];
                    $row->title = $grant['#title'];
                    $row->priority = $grant['priority'];
                    $row->state = array(
                        'data' => $states[$grant['state']][0],
                        'title' => $states[$grant['state']][2],
                    );
                    $row->realm = $grant['realm'];
                    $row->gid = $grant['gid'];
                    $row->grant_view = $grant['grant_view'];
                    $row->grant_update = $grant['grant_update'];
                    $row->grant_delete = $grant['grant_delete'];
                    $row->explained = implode('<br />', module_invoke_all('node_access_explain', $row));
                    unset($row->title);
                    // possibly needed above
                    if ($row->nid == 0 && $row->gid == 0 && $row->realm == 'all' && count($all_grants) > 1) {
                        $row->state = array(
                            'data' => $states['unexpected'][0],
                            'title' => $states['unexpected'][2],
                        );
                        $class = $states['unexpected'][1];
                    }
                    else {
                        $class = $states[$grant['state']][1];
                    }
                    $row = (array) $row;
                    foreach (array(
                        'view',
                        'update',
                        'delete',
                    ) as $op) {
                        $row["grant_{$op}"] = array(
                            'data' => $row["grant_{$op}"],
                        );
                        if ((isset($checked_grants[$grant['nid']][$op][$grant['realm']]) && in_array($grant['gid'], $checked_grants[$grant['nid']][$op][$grant['realm']]) || $row['nid'] == 0 && $row['gid'] == 0 && $row['realm'] == 'all') && !empty($row["grant_{$op}"]['data']) && in_array($grant['state'], $active_states)) {
                            $row["grant_{$op}"]['data'] .= '&prime;';
                            $row["grant_{$op}"]['title'] = t('This entry grants access to this node to this user.');
                        }
                        if (isset($grant["grant_{$op}!"])) {
                            $row["grant_{$op}"]['data'] = $grant["grant_{$op}!"] . '&gt;' . (!$row["grant_{$op}"]['data'] ? 0 : $row["grant_{$op}"]['data']);
                            $row["grant_{$op}"]['class'][] = 'error';
                            if ($class == 'ok') {
                                $row['state'] = array(
                                    'data' => $states['wrong'][0],
                                    'title' => $states['wrong'][2],
                                );
                                $class = $states['wrong'][1];
                            }
                        }
                    }
                    $error_count += $class == 'error';
                    $row['nid'] = array(
                        'data' => '<a href="#node-' . $grant['nid'] . '">' . $row['nid'] . '</a>',
                        'title' => $grant['#title'],
                    );
                    if (empty($grant['#module']) || strpos($grant['realm'], $grant['#module']) === 0) {
                        $row['realm'] = $grant['realm'];
                    }
                    else {
                        $row['realm'] = array(
                            'data' => $grant['#module'] . ':<br />' . $grant['realm'],
                            'title' => t("The '@module' module fails to adhere to the best practice of naming its realm(s) after itself.", array(
                                '@module' => $grant['#module'],
                            )),
                        );
                    }
                    // Prepend information from the D7 hook_node_access_records_alter().
                    $next_style = array();
                    if (isset($grant['history'])) {
                        $history = $grant['history'];
                        if (($num_changes = count($history['changes']) - empty($history['current'])) > 0) {
                            $first_row = TRUE;
                            while (isset($history['original']) || $num_changes--) {
                                if (isset($history['original'])) {
                                    $this_grant = $history['original'];
                                    $this_action = '[ Original by ' . $this_grant['#module'] . ':';
                                    unset($history['original']);
                                }
                                else {
                                    $change = $history['changes'][0];
                                    $this_grant = $change['grant'];
                                    $this_action = ($first_row ? '[ ' : '') . $change['op'] . ':';
                                    array_shift($history['changes']);
                                }
                                $rows[] = array(
                                    'data' => array(
                                        'data' => array(
                                            'data' => $this_action,
                                            'style' => array(
                                                'padding-bottom: 0;',
                                            ),
                                        ),
                                    ),
                                    'style' => array_merge($first_row ? array() : array(
                                        'border-top-style: dashed;',
                                        'border-top-width: 1px;',
                                    ), array(
                                        'border-bottom-style: none;',
                                    )),
                                );
                                $next_style = array(
                                    'border-top-style: none;',
                                );
                                if (count($history['changes'])) {
                                    $g = $this_grant;
                                    $rows[] = array(
                                        'data' => array(
                                            'v',
                                            $g['priority'],
                                            '',
                                            $g['realm'],
                                            $g['gid'],
                                            $g['grant_view'],
                                            $g['grant_update'],
                                            $g['grant_delete'],
                                            'v',
                                        ),
                                        'style' => array(
                                            'border-top-style: none;',
                                            'border-bottom-style: dashed;',
                                        ),
                                    );
                                    $next_style = array(
                                        'border-top-style: dashed;',
                                    );
                                }
                                $first_row = FALSE;
                            }
                        }
                    }
                    // Fix up the main row cells with the proper class (needed for
                    // Bartik).
                    foreach ($row as $key => $value) {
                        if (!is_array($value)) {
                            $row[$key] = array(
                                'data' => $value,
                            );
                        }
                        $row[$key]['class'] = array(
                            $class,
                        );
                    }
                    // Add the main row.
                    $will_append = empty($history['current']) && !empty($history['changes']);
                    $rows[] = array(
                        'data' => array_values($row),
                        'class' => array(
                            $class,
                        ),
                        'style' => array_merge($next_style, $will_append ? array(
                            'border-bottom-style: none;',
                        ) : array()),
                    );
                    // Append information from the D7 hook_node_access_records_alter().
                    if ($will_append) {
                        $last_change = end($history['changes']);
                        $rows[] = array(
                            'data' => array(
                                'data' => array(
                                    'data' => $last_change['op'] . ' ]',
                                    'style' => array(
                                        'padding-top: 0;',
                                    ),
                                ),
                            ),
                            'style' => array(
                                'border-top-style: none;',
                            ),
                        );
                    }
                }
                foreach ($rows as $i => $row) {
                    $rows[$i] = _devel_node_access_format_row($row);
                }
                $output[] = array(
                    '#theme' => 'table',
                    '#header' => $headers,
                    '#rows' => $rows,
                    '#attributes' => array(
                        'class' => array(
                            'system-status-report',
                        ),
                        'style' => 'text-align: left;',
                    ),
                );
                $output[] = array(
                    '#theme' => 'form_element',
                    '#description' => t('(Some of the table elements provide additional information if you hover your mouse over them.)'),
                );
                if ($error_count > 0) {
                    $variables['!Rebuild_permissions'] = '<a href="' . url('admin/reports/status/rebuild') . '">' . $tr('Rebuild permissions') . '</a>';
                    $output[] = array(
                        '#prefix' => "\n<div class=\"error\">",
                        '#markup' => t("You have errors in your !na table! You may be able to fix these for now by running !Rebuild_permissions, but this is likely to destroy the evidence and make it impossible to identify the underlying issues. If you don't fix those, the errors will probably come back again. <br /> DON'T do this just yet if you intend to ask for help with this situation.", $variables),
                        '#suffix' => "</div><br />\n",
                    );
                }
                // Explain whether access is granted or denied, and why (using code from
                // node_access()).
                $tr = 't';
                array_shift($nids);
                // remove the 0
                $accounts = array();
                $variables += array(
                    '!username' => '<em class="placeholder">' . theme('username', array(
                        'account' => $user,
                    )) . '</em>',
                    '%uid' => $user->uid,
                );
                if (user_access('bypass node access')) {
                    $variables['%bypass_node_access'] = $tr('bypass node access');
                    $output[] = array(
                        '#markup' => t('!username has the %bypass_node_access permission and thus full access to all nodes.', $variables),
                        '#suffix' => '<br />&nbsp;',
                    );
                }
                else {
                    $variables['!list'] = '<div style="margin-left: 2em">' . _devel_node_access_get_grant_list($nid, $ng_alter_datas['view']) . '</div>';
                    $variables['%access'] = 'view';
                    $output[] = array(
                        '#prefix' => "\n<div style='text-align: left' title='" . t('These are the grants returned by hook_node_grants() for this user.') . "'>",
                        '#markup' => t('!username (user %uid) can use these grants (if they are present above) for %access access: !list', $variables),
                        '#suffix' => "</div>\n",
                    );
                    $accounts[] = $user;
                }
                $menu_item = menu_get_item();
                $map = $menu_item['original_map'];
                if ($map[0] == 'node' && isset($map[1]) && is_numeric($map[1]) && !isset($map[2]) && !$block1_visible) {
                    // Only for single nodes.
                    if (user_is_logged_in()) {
                        $accounts[] = user_load(0);
                        // Anonymous, too
                    }
                    foreach ($accounts as $account) {
                        $account_items = array();
                        $nid_items = array();
                        foreach ($nids as $nid) {
                            $op_items = array();
                            foreach (array(
                                'create',
                                'view',
                                'update',
                                'delete',
                            ) as $op) {
                                $explain = _devel_node_access_explain_access($op, $nid, $account);
                                $op_items[] = "<div style='width: 5em; display: inline-block'>" . t('%op:', array(
                                    '%op' => $op,
                                )) . ' </div>' . $explain[2];
                            }
                            $nid_items[] = array(
                                '#theme' => 'item_list',
                                '#items' => $op_items,
                                '#type' => 'ul',
                                '#prefix' => t('to node !nid:', array(
                                    '!nid' => l($nid, 'node/' . $nid),
                                )) . "\n<div style='margin-left: 2em'>",
                                '#suffix' => '</div>',
                            );
                        }
                        if (count($nid_items) == 1) {
                            $account_items = $nid_items[0];
                        }
                        else {
                            $account_items = array(
                                '#theme' => 'item_list',
                                '#items' => $nid_items,
                                '#type' => 'ul',
                                '#prefix' => "\n<div style='margin-left: 2em'>",
                                '#suffix' => '</div>',
                            );
                        }
                        $variables['!username'] = '<em class="placeholder">' . theme('username', array(
                            'account' => $account,
                        )) . '</em>';
                        $output[] = array(
                            '#prefix' => "\n<div style='text-align: left'>",
                            '#type' => 'item',
                            'lead-in' => array(
                                '#markup' => t("!username has the following access", $variables) . ' ',
                            ),
                            'items' => $account_items,
                            '#suffix' => "\n</div>\n",
                        );
                    }
                }
            }
            if (!empty($hint)) {
                $output[] = array(
                    '#theme' => 'form_element',
                    '#description' => '(' . $hint . ')',
                );
            }
            $output[]['#markup'] = '<br /><br />';
            $subject = t('node_access entries for nodes shown on this page');
            return array(
                'subject' => $subject,
                'content' => $output,
            );
        case 'dna_user':
            // Show which users can access this node.
            $menu_item = menu_get_item();
            $map = $menu_item['original_map'];
            if ($map[0] != 'node' || !isset($map[1]) || !is_numeric($map[1]) || isset($map[2])) {
                // Ignore anything but node/%.
                return;
            }
            if (isset($menu_item['map'][1]) && is_object($node = $menu_item['map'][1])) {
                // We have the node.
            }
            elseif (is_numeric($menu_item['original_map'][1])) {
                $node = node_load($menu_item['original_map'][1]);
            }
            if (isset($node)) {
                $nid = $node->nid;
                $node_type = node_type_get_type($node);
                $variables = array(
                    '@Node_type' => $node_type ? $node_type->name : $node->type,
                );
                $create_header = '<span title="' . t("Create nodes of the '@Node_type' type.", $variables) . '">' . t('create') . '</span>';
                if (!$node_type) {
                    $create_header .= '<br /><span class="error">' . t("(missing type: '@Node_type')", $variables) . '</span>';
                }
                $headers = array(
                    t('username'),
                    $create_header,
                    t('view'),
                    t('update'),
                    t('delete'),
                );
                $rows = array();
                // Determine whether to use Ajax or prepopulate the tables.
                if ($ajax = variable_get('devel_node_access_user_ajax', FALSE)) {
                    drupal_add_js(drupal_get_path('module', 'devel_node_access') . '/devel_node_access.js');
                }
                // Find all users. The following operations are very inefficient, so we
                // limit the number of users returned.  It would be better to make a
                // pager query, or at least make the number of users configurable.  If
                // anyone is up for that please submit a patch.
                $query = db_select('users', 'u')->fields('u', array(
                    'uid',
                ))
                    ->orderBy('u.access', 'DESC')
                    ->range(0, 9);
                $uids = $query->execute()
                    ->fetchCol();
                array_unshift($uids, 0);
                $accounts = user_load_multiple($uids);
                foreach ($accounts as $account) {
                    $username = theme('username', array(
                        'account' => $account,
                    ));
                    if ($account->uid == $user->uid) {
                        $username = '<strong>' . $username . '</strong>';
                    }
                    $rows[] = array(
                        $username,
                        array(
                            'id' => 'create-' . $nid . '-' . $account->uid,
                            'class' => 'dna-permission',
                            'data' => $ajax ? NULL : theme('dna_permission', array(
                                'permission' => _devel_node_access_explain_access('create', $nid, $account),
                            )),
                        ),
                        array(
                            'id' => 'view-' . $nid . '-' . $account->uid,
                            'class' => 'dna-permission',
                            'data' => $ajax ? NULL : theme('dna_permission', array(
                                'permission' => _devel_node_access_explain_access('view', $nid, $account),
                            )),
                        ),
                        array(
                            'id' => 'update-' . $nid . '-' . $account->uid,
                            'class' => 'dna-permission',
                            'data' => $ajax ? NULL : theme('dna_permission', array(
                                'permission' => _devel_node_access_explain_access('update', $nid, $account),
                            )),
                        ),
                        array(
                            'id' => 'delete-' . $nid . '-' . $account->uid,
                            'class' => 'dna-permission',
                            'data' => $ajax ? NULL : theme('dna_permission', array(
                                'permission' => _devel_node_access_explain_access('delete', $nid, $account),
                            )),
                        ),
                    );
                }
                if (count($rows)) {
                    $output[] = array(
                        '#theme' => 'table',
                        '#header' => $headers,
                        '#rows' => $rows,
                        '#attributes' => array(
                            'style' => 'text-align: left',
                        ),
                    );
                    $output[] = array(
                        '#theme' => 'form_element',
                        '#description' => t('(This table lists the most-recently active users. Hover your mouse over each result for more details.)'),
                    );
                    return array(
                        'subject' => t('Access permissions by user'),
                        'content' => $output,
                    );
                }
            }
            break;
    }
}