array( 'title' => t('View any unpublished content'), ), ); // Generate standard node permissions for all applicable node types. foreach (node_permissions_get_configured_types() as $type) { $info = node_type_get_type($type); $type = check_plain($info->type); $perms["view any unpublished $type content"] = array( 'title' => t('%type_name: View any unpublished content', array('%type_name' => $info->name)), ); } return $perms; } /** * Implements hook_node_access_records(). */ function view_unpublished_node_access_records($node) { // We only care about the node if is unpublished. If not, it is // treated just like any other node and we completely ignore it. if ($node->status == 0) { $grants = array(); // Unpublished nodes should be viewable to all editors. $grants[] = array( 'realm' => 'view_unpublished_content', 'gid' => 1, 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0, 'priority' => 0, ); $grants[] = array( 'realm' => 'view_unpublished_' . $node->type . '_content', 'gid' => 1, 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0, 'priority' => 0, ); return $grants; } } /** * Implements hook_node_grants(). */ function view_unpublished_node_grants($account, $op) { $grants = array(); if ($op == 'view') { if (user_access('view any unpublished content', $account)) { $grants['view_unpublished_content'] = array(1); return $grants; } foreach(node_permissions_get_configured_types() as $type) { if (user_access("view any unpublished $type content", $account)) { $grants['view_unpublished_' . $type . '_content'] = array(1); } } } return $grants; } /** * Implements hook_views_data_alter() */ function view_unpublished_views_data_alter(&$data) { // published status + extra handler is taken over by our handler $data['node']['status_extra']['filter']['handler'] = 'view_unpublished_handler_filter_node_status'; } /** * Implements hook_views_handlers() */ function view_unpublished_views_handlers() { return array( 'info' => array( 'path' => drupal_get_path('module', 'view_unpublished'), ), 'handlers' => array( 'view_unpublished_handler_filter_node_status' => array( 'parent' => 'views_handler_filter_node_status', ), ), ); } /** * Implements hook_views_query_substitutions(). */ function view_unpublished_views_query_substitutions() { foreach (node_type_get_types() as $type => $name) { $substitutions["***VIEWUNPUBLISHED_$type***"] = intval(user_access('view any unpublished ' . $type . ' content')); } return $substitutions; } /** * Implements hook_query_alter(); * * Modify the Content Overview page to account for view unpublished * permissions. */ function view_unpublished_query_alter($query) { global $user; if (arg(0) == 'admin' && arg(1) == 'content' && get_class($query) == 'TableSort' && $user->uid !== "1" && !user_access('bypass node access') && !user_access('administer nodes')) { $perms = view_unpublished_user_perms(); // "any" in this case means at least 1 view unpublished permission is set to TRUE. if ($perms['any']) { $conditions =& $query->conditions(); foreach ($conditions as $key => $condition) { // For some queries $condition['field'] is not a string so we need a check for that. if (isset($condition['field']) && $condition['field'] === 'n.status') { if (TRUE) { if ($key == count($conditions) - 2) { // This condition is (probably) coming from modules/node/node.admin.inc, // function node_admin_nodes(): $query->condition('n.status', 1); // We don't want it. unset($conditions[$key]); } } } } // If "view any unpublished content" (aka $perms['full']) is set, then // leave the rest of the query as-is and return all unpublished content. // Otherwise, add a WHERE/OR to the query that specifies content type, as // dictated by the user's permissions, e.g. "view any unpublished page content" if (!$perms['full']) { $content_perms = array_filter($perms['content_type']); if (count($content_perms) === 1) { $query->condition('n.type', key($content_perms)); } else { $db_or = db_or(); foreach ($content_perms as $k => $v) { $db_or->condition('n.type', $k); } $query->condition($db_or); } } } } } /** * Utility function that returns the user's view_unpublished permissions in the * following format: * * $perms['any'] = TRUE if any of the below is TRUE, otherwise FALSE. * $perms['full'] = TRUE if "view any unpublished content" is set. * $perms['content_type'] = array of content types and the user's * associated view unpublished permission. */ function view_unpublished_user_perms() { $perms = FALSE; $perms['full'] = user_access('view any unpublished content') ? TRUE : FALSE; foreach (view_unpublished_content_type_permissions(TRUE) as $machine_type => $perm_type) { $perms['content_type'][$machine_type] = user_access($perm_type) ? TRUE : FALSE; } _vup_in_array_r(TRUE, $perms, TRUE) ? $perms['any'] = TRUE : $perms['any'] = FALSE; return $perms; } /** * Utility function, return a formatted list of content types for use here. */ function view_unpublished_content_type_permissions($machine_readable = FALSE) { $perms = array(); foreach (node_permissions_get_configured_types() as $type) { $info = node_type_get_type($type); $type = check_plain($info->type); if ($machine_readable) { $perms[$type] = "view any unpublished $type content"; } else { $perms["view any unpublished $type content"] = array( 'title' => t('%type_name: View any unpublished content', array('%type_name' => $info->name)), ); } } return $perms; } /** * Utility function, multidimentional in_array(). */ function _vup_in_array_r($needle, $haystack, $strict = TRUE) { foreach ($haystack as $item) { if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && _vup_in_array_r($needle, $item, $strict))) { return TRUE; } } return FALSE; }