array_keys($account->roles), 'workflow_access_owner' => array($account->uid), ); } /** * Implementation of hook_node_access_records(). * * Returns a list of grant records for the passed in node object. */ function workflow_access_node_access_records($node) { $grants = array(); $sid = db_result(db_query("SELECT sid FROM {workflow_node} WHERE nid = %d", $node->nid)); // We have state information about this node, so get permissions for this state. if (is_numeric($sid)) { $result = db_query('SELECT * FROM {workflow_access} WHERE sid = %d', $sid); while ($grant = db_fetch_object($result)) { $grants[] = array( 'realm' => ($grant->rid == -1) ? 'workflow_access_owner' : 'workflow_access', 'gid' => ($grant->rid == -1) ? $node->uid : $grant->rid, 'grant_view' => $grant->grant_view, 'grant_update' => $grant->grant_update, 'grant_delete' => $grant->grant_delete, 'priority' => 0, ); } } return $grants; } /** * Implementation of hook_node_access_explain(). */ function workflow_access_node_access_explain($row) { static $interpretations = array(); switch ($row->realm) { case 'workflow_access_owner': $interpretations[$row->gid] = t('Workflow access: author of the content may access'); break; case 'workflow_access': $roles = user_roles(); $interpretations[$row->gid] = t('Workflow access: %role may access', array('%role' => $roles[$row->gid])); break; } return (!empty($interpretations[$row->gid]) ? $interpretations[$row->gid] : NULL); } /** * Implementation of hook_form_alter(). * * Add a "three dimensional" (state, role, permission type) configuration * interface to the workflow edit form. */ function workflow_access_form_workflow_edit_form_alter(&$form, $form_state) { // A list of roles available on the site and our // special -1 role used to represent the node author. $rids = user_roles(); $rids['-1'] = t('author'); $form['workflow_access'] = array( '#type' => 'fieldset', '#title' => t('Access control'), '#collapsible' => TRUE, '#tree' => TRUE, ); // Add a table for every workflow state. $states = workflow_get_states($form['wid']['#value']); foreach ($states as $sid => $state) { if (workflow_is_system_state($state)) { // No need to set perms on creation. continue; } $view = $update = $delete = array(); $result = db_query("SELECT * from {workflow_access} where sid = %d", $sid); $count = 0; while ($access = db_fetch_object($result)) { $count++; if ($access->grant_view) { $view[] = $access->rid; } if ($access->grant_update) { $update[] = $access->rid; } if ($access->grant_delete) { $delete[] = $access->rid; } } // Allow view grants by default for anonymous and authenticated users, // if no grants were set up earlier. if (!$count) { $view = array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID); } // TODO better tables using a #theme function instead of direct #prefixing $form['workflow_access'][$sid] = array( '#type' => 'fieldset', '#title' => $state, '#collapsible' => TRUE, '#tree' => TRUE, ); $form['workflow_access'][$sid]['view'] = array( '#type' => 'checkboxes', '#options' => $rids, '#default_value' => $view, '#title' => t('Roles who can view posts in this state'), '#prefix' => '
', ); $form['workflow_access'][$sid]['update'] = array( '#type' => 'checkboxes', '#options' => $rids, '#default_value' => $update, '#title' => t('Roles who can edit posts in this state'), '#prefix' => "", ); $form['workflow_access'][$sid]['delete'] = array( '#type' => 'checkboxes', '#options' => $rids, '#default_value' => $delete, '#title' => t('Roles who can delete posts in this state'), '#prefix' => "", '#suffix' => "
", ); } // Place our block comfortably down the page. $form['submit']['#weight'] = 10; $form['#submit'][] = 'workflow_access_form_submit'; } /** * Store permission settings for workflow states. */ function workflow_access_form_submit($form, $form_state) { foreach ($form_state['values']['workflow_access'] as $sid => $access) { // Ignore irrelevant keys. if (!is_numeric($sid)) { continue; } $grants = array(); db_query("DELETE FROM {workflow_access} WHERE sid = %d", $sid); foreach ($access['view'] as $rid => $checked) { $grants[] = array( 'realm' => ($rid == -1) ? 'workflow_access_owner' : 'workflow_access', 'gid' => ($rid == -1) ? $node->uid : $rid, 'grant_view' => (bool)$checked, 'grant_update' => (bool)$access['update'][$rid], 'grant_delete' => (bool)$access['delete'][$rid], ); db_query("INSERT INTO {workflow_access} (sid, rid, grant_view, grant_update, grant_delete) VALUES (%d, %d, %d, %d, %d)", $sid, $rid, (bool)$checked, (bool)$access['update'][$rid], (bool)$access['delete'][$rid]); } // Update all nodes having same workflow state to reflect new settings. $result = db_query("SELECT n.nid FROM {node} n LEFT JOIN {workflow_node} wn ON wn.nid = n.nid WHERE wn.sid = %d", $sid); while ($node = db_fetch_object($result)) { // TODO: this only works with workflow_access realm, not the workflow_access_owner realm?! node_access_write_grants($node, $grants, 'workflow_access'); } } drupal_set_message(t('Workflow access permissions updated.')); } /** * Implementation of hook_workflow(). * * Update grants when a node changes workflow state. */ function workflow_access_workflow($op, $old_sid, $sid, $node) { if ($op == 'transition post' && $old_sid != $sid) { node_access_acquire_grants($node); } }