? node_privacy_byrole.info
? npbr_20070202_drupal5.patch
Index: node_privacy_byrole.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/node_privacy_byrole/node_privacy_byrole.module,v
retrieving revision 1.27.2.2
diff -u -F^f -r1.27.2.2 node_privacy_byrole.module
--- node_privacy_byrole.module	11 Aug 2006 09:33:12 -0000	1.27.2.2
+++ node_privacy_byrole.module	2 Feb 2007 15:11:08 -0000
@@ -1,101 +1,4 @@
 <?php
-
-
-/**
- * @file
- * READ CAREFULLY!!!
- *
- * This module, when enabled, allows users to select which roles will
- * be allowed to view their posts.
- * 
- * The module uses hook_nodeapi() and hook_node_grants() to enable this 
- * functionality.  hook_nodeapi() provides formitems for the content creation 
- * page and content editing page as well as functionality that saves the user's 
- * preferences as selected via the formitems.  These preferences are saved into
- * the node_access table.
- * 
- * hook_node_grants() returns an associative array of permissions based on the 
- * operation ($op) and the global $user (even though the $user is a parameter 
- * to the hook, it is ignored at this point in time).  The _node_grants() hook 
- * is called by node_access(), a function in node.module, which is called whenever
- * a node operation is called.
- *
- * The concerns that follow are addressed via an extra settings page for the 
- * node_privacy_byrole module where the extra steps described below are carried 
- * out by a more explicit enabling/disabling functionality in the settings page. 
- * Ideally, the DB code in the settings page would automatically execute when the
- * module is enabled/disabled.  However, because Drupal does not provide hooks
- * at this time for tasks that should only happen upon disabling or enabling a 
- * module, we require the site admin to go to the settings page where the module 
- * can be properly initiated or disabled.
- *
- * For this module to be enabled properly, the following query must be performed 
- * against the database.
- * Database definition:
- * @code
- *   DELETE FROM node_access WHERE realm='all';
- * @endcode
- *
- * For this module to be properly disabled, the following query must be performed.
- * 
- * @code
- *   INSERT INTO node_access (nid, gid, realm, grant_view, grant_update, grant_delete) VALUES (0, 0, 'all', 1, 0, 0)';
- * @endcode
- *
- *
- * PROPER ENABLING OF MODULE
- * ---
- * The DELETE SQL statement above deletes the default access permission which 
- * automatically gives all users view permission for every node (while edit, 
- * and create permissions are determined by other code in node_access() in 
- * node.module).  This delete must take place since node view permissions are 
- * now being determined by this module, otherwise node_access will always return
- * TRUE for any user trying to view a node.  It must be executed when the module 
- * is enabled in order to let the module's _node_grants() function solely determine
- * which users have view permissions on a node-by-node basis since we are allowing
- * users to specify which roles can view a node on a node-by-node basis.
- *
- * ADDITIONALLY, code must be executed that essentially does the following when the 
- * module is enabled:
- *
- * for every ($node in node table) {
- *   for every ($role in role table) {
- *     INSERT INTO node_access($node->nid, $role->rid, 'node_privacy_byrole_role', 1, 0, 0);
- *   }
- *   INSERT INTO node_access($node->nid, $node->uid, 'node_privacy_byrole_user', 1, 0, 0);
- * }
- *
- * Before the module is enabled and the above DELETE SQL query is executed, every
- * node is viewable, by every user.  However, when the module is enabled and this
- * default is erased, we still want every node to be viewable by every user until
- * each node's creator decides to change that.  We also want each node's creator
- * to have view permissions to all the nodes s/he created (currently, node_access()
- * as defined in node.module, does not, by default, grant view access to a node's
- * creator.  It relies on the deleted default node_access table entry to provide
- * that permission).  
- *
- *
- * PROPER DISABLING OF MODULE
- * ---
- * The single INSERT SQL statement above is meant to reset to the default permission 
- * of allowing all users view permission for every node. 
- *
- * Again, ideally, these queries would be automatically executed when the module is
- * enabled or disabled.  However, at this point in time, drupal does not provide
- * hooks that  automatically execute upon the enabling/disabling of a module.
- *
- * Finally, there is the issue of what to do when a site admin enables this module,
- * disables the module, and then re-enables the module.  To account for this 
- * possibility, we must make sure none of the inserts described above is replicated.
- * Perhaps the site admin wants the permissions set during the first enabling to be 
- * valid after the re-enabling.  Either way, care must be taken not to duplicate the 
- * inserts from the first enabling, or to delete them from the DB altogether before 
- * doing a new set of inserts.  This is an open design decision.
- *
- * In this module, we've taken the path of inserting view permissions for every role
- * in the case of each node that has been created the previous disabling of the module.
- */
-
 /**
  * Implementation of hook_help().
  */
@@ -103,495 +6,267 @@ function node_privacy_byrole_help($secti
   switch ($section) {
     case 'admin/help#node_privacy_byrole':
       $output = '<p>'. t('The node privacy by role module allows users, when creating or editing a post, to select which roles of users on a site will have <em>view</em> permissions for the node and which users on a site will have <em>edit</em> permissions.  Community leaders frequently want to give permissions to roles to create and manage content for a site.  The ability to publish information, that would traditionally be hoarded, allows communities to educate each other while still preserving the value of knowledge.') .'</p>';
-      $output .= '<p>'. t('The node privacy by role module must be explicitly enabled in its administration interface.  The node privacy by-role permissions are set by users for their nodes. If the node privacy by role module is disabled, the default permissions scheme will be in effect again, in which all users have view permissions for all nodes.  However, if the module is re-enabled, the node-by-node permissions that were in place during the previous period in which the module was enabled will take effect again.  Roles given edit permissions are automatically given view permissions even if the user tries to give <em>edit</em> permissions to a particular role, but not view permissions.') .'</p>';
-      $output .= '<p>'. t('You must explicitly enable or disable the module at <a href="%admin-settings-node_privacy_byrole" title="node privacy by role administration">administer &gt;&gt; settings &gt;&gt; node_privacy_byrole</a>.', array('%admin-settings-node_privacy_byrole' => url('admin/settings/node_privacy_byrole'))) .'</p>';
+      $output .= '<p>'. t('The node privacy by-role permissions are set by users for their nodes. If the node privacy by role module is disabled, the default permissions scheme will be in effect again, in which all users have view permissions for all nodes. However, if the module is re-enabled, the node-by-node permissions that were in place during the previous period in which the module was enabled will take effect again. Roles given edit permissions are automatically given view permissions even if the user tries to give <em>edit</em> permissions to a particular role, but not view permissions.') .'</p>';
       $output .= t('<p>You can</p>
 <ul>
-<li>set default permissions for each content type in the default workflow settings at <a href="%admin-node-configure-types">administer &gt;&gt; content &gt;&gt; configure &gt;&gt; content types</a> for each content type.</li>
-<li>decide who can ignore the default permissions for each content type in the default workflow settings at <a href="%admin-node-configure-types">administer &gt;&gt; content &gt;&gt; configure &gt;&gt; content types</a> for each content type.</li>
-</ul>', array('%admin-node-configure-types' => url('admin/node/configure/types')));
-      $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%node_privacy_byrole">Node privacy by role page</a>.', array('%node_privacy_byrole' => 'http://www.drupal.org/handbook/modules/node_privacy_byrole/')) .'</p>';
+<li>set default permissions for each content type in the default workflow settings at <a href="@admin-node-configure-types">Administer &gt;&gt; Content management &gt;&gt; Content types</a> for each content type.</li>
+<li>decide who can ignore the default permissions for each content type in the default workflow settings at <a href="@admin-node-configure-types">Administer &gt;&gt; Content management &gt;&gt; Content types</a> for each content type.</li>
+</ul>', array('@admin-node-configure-types' => url('admin/content/types')));
+      $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@node_privacy_byrole">Node privacy by role page</a>.', array('@node_privacy_byrole' => 'http://www.drupal.org/handbook/modules/node_privacy_byrole/')) .'</p>';
       return $output;
     case 'admin/modules#description':
       return t('Allows users to specify which roles of users can view content on a node-by-node basis.  Make sure to properly enable this module by going to the %settings_page after enabling here.', array('%settings_page' => l(t('module\'s settings page'), 'admin/settings/node_privacy_byrole')));
-    case 'admin/settings/node_privacy_byrole':
-      $node_privacy_byrole_enabled = variable_get('node_privacy_byrole_enabled', FALSE);
-      $message = '';
-      if ($node_privacy_byrole_enabled) {
-        $message .= t('The module is currently enabled.') .'<br/>';
-        $message .= t('If you wish to disable this module without encountering strange behavior afterward, please make sure to \'disable\' here BEFORE you uncheck it on the %modules_page.', array('%modules_page' => l(t('modules administration page'), 'admin/modules'))) .'<br/>';
-      }
-      else {
-        $message .= t('The module is currently disabled on this page, but must also be disabled in the %module_page_link in order for it to be fully disabled.  Failing to fully disable the module may cause erratic bugs when going back to the regular node permissions system. <br/> If you wish to fully and safely enable this module without encountering strange behavior, select \'enable\' here and save the configuration.<br/>', array('%module_page_link' => l(t('modules admin page'), 'admin/modules', array('title' => t('View more.')))));
-      }
-      return $message;
   }
 }
 
 /**
- * Here, we receive an $op and use it to determine all of global $user's permissions
- * for each node with regard to $op.  For example, if $op == view, then this function
- * returns an associative array of arrays where each subarray is keyed by the 'realm'
- * and each subarray contains a list of gids.  The gid for an entry in the node_access
- * table means whatever the implementor wants it to mean.  It's context is defined
- * by the related 'realm'.  In this implementation there are 2 realms: 
- * 'node_privacy_byrole_user' and 'node_privacy_byrole_role'.  
- *
- * In the 'node_privacy_byrole_user' realm, the gid is a uid typically used to identify 
- * the owner of the node and, in this table, used to give the owner view access to 
- * his/herb nodes irrespective of what role permissions s/he may have set in the content 
- * creation page.
- *
- * In the 'node_privacy_byrole_role' realm, the gid is a rid ("role id" as in the role 
- * DB table) and is used to define the permissions of a particular role.
- *
- * This function returns the global $user's grants using both global $user->uid and 
- * $user->roles 
+ * Implementation of hook_node_grants()
  */
-function node_privacy_byrole_node_grants($user, $op) {
-  global $user;
-  return array('node_privacy_byrole_role' => array_keys(is_array($user->roles) ? $user->roles : array()), 'node_privacy_byrole_user' => array($user->uid));
+function node_privacy_byrole_node_grants($account, $op) {
+  return array(
+    'node_privacy_byrole_role' => array_keys($account->roles),
+    'node_privacy_byrole_user' => array($account->uid)
+  );
 }
 
-function node_privacy_byrole_form_alter($form_id, &$form) {
-  if (isset($form['type']) && $form['type']['#value'] .'_node_settings' == $form_id) {
-    $type = $form['type']['#value'];
-    $roles_array = user_roles();
-    $roleids_array = array_keys($roles_array);
-    
-    $form ['npbr_workflow_settings'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('node privacy by role'),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
-      '#weight' => 0
-    );
-    
-    $form['npbr_workflow_settings']['npbr_default_view_perms'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Default View Permissions'),
-      '#collapsible' => FALSE,
-      '#collapsed' => FALSE,
-      '#description' => t('Select by role which users can, by default, view nodes of this type.'),
-      '#weight' => 0
-    );
-    
-    $form['npbr_workflow_settings']['npbr_default_edit_perms'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Default Edit Permissions'),
-      '#collapsible' => FALSE,
-      '#collapsed' => FALSE,
-      '#description' => t('Select by role which users can, by default, edit nodes of this type.'),
-      '#weight' => 0
-    );
-      
-    $form['npbr_workflow_settings']['npbr_default_meta_perms'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Permissions For Permissions'),
-      '#collapsible' => FALSE,
-      '#collapsed' => FALSE,
-      '#description' => t('Select, by role, which users can change permissions, on a node-by-node basis, from the default permissions set for this node type.'),
-      '#weight' => 0
-    );
-   
-    // Check for existing settings and prefill those with settings already set. Use 0 for default-default (i.e., 
-    // nodes whose default permissions have never been set).
+/**
+ * Implementation of hook_node_access_records()
+ */
+function node_privacy_byrole_node_access_records($node) {
+  node_privacy_byrole_nodeapi_prepare($node);
 
-    foreach ($roleids_array as $roleid) {
-      $form['npbr_workflow_settings']['npbr_default_view_perms']['npbr_forview_'. $type .'_default_'. $roleid] = array(
-        '#type' => 'checkbox',
-        '#title' => t($roles_array[$roleid]),
-        '#return_value' => 1,
-        '#default_value' => variable_get('npbr_forview_'. $type .'_default_'. $roleid, FALSE)
-      );
-      
-      $form['npbr_workflow_settings']['npbr_default_edit_perms']['npbr_foredit_'. $type .'_default_'. $roleid] = array(
-        '#type' => 'checkbox',
-        '#title' => t($roles_array[$roleid]),
-        '#return_value' => 1,
-        '#default_value' => variable_get('npbr_foredit_'. $type .'_default_'. $roleid, FALSE)
-      );
-      
-      $form['npbr_workflow_settings']['npbr_default_meta_perms']['npbr_metaperm_'. $type .'_'. $roleid] = array(
-        '#type' => 'checkbox',
-        '#title' => t($roles_array[$roleid]),
-        '#return_value' => 1,
-        '#default_value' => variable_get('npbr_metaperm_'. $type .'_'. $roleid, FALSE),
-      );
-    }
-  }
-  elseif (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
-    node_privacy_byrole_formitems($form);
+  $grants = array();
+
+  // permission for node owner
+  if ($node->uid > 0) {
+    $grants[] = array(
+      'realm' => 'node_privacy_byrole_user',
+      'gid' => $node->uid,
+      'grant_view' => TRUE,
+      'grant_update' => FALSE,
+      'grant_delete' => FALSE,
+      'priority' => 0,
+    ); 
+  }
+  // permission for node roles
+  foreach (array_keys(user_roles()) as $rid) {
+    $edit_perm = $node->node_privacy_byrole['roles'][$rid]['edit'] ? 1 : 0;
+    $view_perm = ($edit_perm ? 1 : $node->node_privacy_byrole['roles'][$rid]['view']);
+
+    $grants[] = array(
+      'realm' => 'node_privacy_byrole_role',
+      'gid' => $rid,
+      'grant_view' => $view_perm,
+      'grant_update' => $edit_perm,
+      'grant_delete' => FALSE,
+      'priority' => 0,
+    ); 
   }
+
+  return $grants; 
 }
 
 /**
  * Implementation of hook_nodeapi().
- *
  */
 function node_privacy_byrole_nodeapi(&$node, $op, $arg = 0) {
-  global $user;
-  
-  $permitted_roles = _node_privacy_byrole_meta_permitted_roles($node->type);
-    
-  $user_has_meta_perm = ($user->uid == 1 || count(array_intersect(_node_privacy_byrole_meta_permitted_roles($node->type), array_keys(is_array($user->roles) ? $user->roles : array()))) ? TRUE : FALSE);
   switch ($op) {
-    case 'form admin':
-      return '';
-    case 'delete':
-      // When a node is deleted, delete any relevant grants within realms managed by this module.
-      db_query('DELETE FROM {node_access} WHERE nid = %d AND (realm = \'node_privacy_byrole_user\' OR realm = \'node_privacy_byrole_role\')', $node->nid);
-      break;
-    case 'validate':
-      if (variable_get('node_privacy_byrole_enabled', FALSE)) {
-        _node_privacy_byrole_set_defaults($node, !$user_has_meta_perm);
-      }
-      if ($node->nid && !user_access('administer nodes')) {
-        $result = db_query('SELECT uid FROM {node} WHERE nid = %d', $node->nid);
-        if ($row = db_fetch_object($result)) {
-          $node->uid = $row->uid;
-        }
-      }
-      break;
-    case 'fields':
-      break;
-    case 'insert':
-      if ($user_has_meta_perm) {
-        node_privacy_byrole_save_permissions($node);
-      }
-      else {
-        _node_privacy_byrole_set_defaults($node, TRUE);
-        node_privacy_byrole_save_permissions($node);
-      }
-      break;
-    case 'update':
-      if ($user_has_meta_perm) {
-        node_privacy_byrole_update_permissions($node);
-      }
+    case 'prepare':
+      node_privacy_byrole_nodeapi_prepare($node);
       break;
   }
-  
 }
 
-/**
- * Sets the default permissions for permissions as dictated by settings in the default workflow
- * for each node type.  If no settings exists (perhaps because they haven't been set yet, or because
- * new roles have been added since the last adjustment to the workflow, an absence of permissions is
- * assumed for the role.
- * @param $node
- *  The node for which node_privacy_byrole is currently settings permissions.
- * @param $force
- *  Whether or not the default permissions should be set for this node regardless of what already has
- *  already been set for this node.
- *
- */
-function _node_privacy_byrole_set_defaults(&$node, $force = TRUE) {
-  $roles = user_roles();
-  
-  foreach ($roles as $rid => $role_name) {
-    $view_perm_field = 'node_privacy_byrole_forview_'. $rid;
-    $edit_perm_field = 'node_privacy_byrole_foredit_'. $rid;
-    
-    if (!isset($node->$view_perm_field)) {
-      $node->$view_perm_field = variable_get('npbr_forview_'. $node->type .'_default_'. $rid, 0);
-    }
-    else {
-      $node->$view_perm_field = $force ? variable_get('npbr_forview_'. $node->type .'_default_'. $rid, 0) : $node->$view_perm_field;
-    }
-    
-    if (!isset($node->$edit_perm_field)) {
-      $node->$edit_perm_field = variable_get('npbr_foredit_'. $node->type .'_default_'. $rid, 0);
+function node_privacy_byrole_nodeapi_prepare(&$node) {
+  if (!isset($node->node_privacy_byrole)) {
+    $roles = array_keys(user_roles());
+    $perms = array('view', 'edit');
+
+    if ($node->nid  && !$node->is_new) {
+      // this is an existing node, get current permissions
+      $result = db_query("SELECT gid, grant_view, grant_update FROM {node_access} "
+        ."WHERE nid = %d AND (grant_view = 1 OR grant_update = 1) "
+        ."AND realm = 'node_privacy_byrole_role'", $node->nid);
+
+      $current_perms = array();
+      while($role = db_fetch_object($result)) {
+        $current_perms[$role->gid]['view'] = $role->grant_view;
+        $current_perms[$role->gid]['edit'] = $role->grant_update;
+      }
+
+      foreach ($roles as $rid) {
+        foreach($perms as $perm) {
+          $node->node_privacy_byrole['roles'][$rid][$perm] = $current_perms[$rid][$perm] ? 1 : 0;
+        }
+      }
     }
     else {
-      $node->$edit_perm_field = $force ? variable_get('npbr_foredit_'. $node->type .'_default_'. $rid, 0) : $node->$edit_perm_field;
+      // case where node is being created
+      foreach ($roles as $rid) {
+        foreach($perms as $perm) {
+          $default_roles = _node_privacy_byrole_get_default_roles($node->type, $perm);
+          $node->node_privacy_byrole['roles'][$rid][$perm] = in_array($rid, $default_roles) ? 1 : 0;
+        }
+      }
     }
   }
 }
 
 /**
- * Returns the rid's or roles that are permitted to 
- *
- *
+ * Implementation of hook_form_alter().
  */
-function _node_privacy_byrole_meta_permitted_roles($type) {
-  $permitted_roles = array();
-  $roles = array_keys(user_roles());
-  foreach ($roles as $rid) {
-    if (variable_get('npbr_metaperm_'. $type .'_'. $rid, 0)) {
-      $permitted_roles[] = $rid;
+function node_privacy_byrole_form_alter($form_id, &$form) {
+  if ('node_type_form' == $form_id) {
+    node_privacy_byrole_node_type_form($form);
+  }
+  elseif (strpos($form_id, 'node_form')) {
+    if (node_privacy_byrole_user_has_meta_perm()) {
+      node_privacy_byrole_node_form($form);
     }
   }
-  return $permitted_roles;
 }
 
-
 /**
- * Saves node permissions upon node submission.
- *
+ * Checks that the active user has access to set permissions on nodes.
  */
-function node_privacy_byrole_save_permissions(&$node) {
+function node_privacy_byrole_user_has_meta_perm() {
   global $user;
 
-  $roleids_array = array_keys(user_roles());
-  $results = db_query('SELECT * FROM {role}');
-  foreach($roleids_array as $roleid) {
-    $edit_perm_field = 'node_privacy_byrole_foredit_'. $roleid;
-    $view_perm_field = 'node_privacy_byrole_forview_'. $roleid; 
-    $edit_perm = isset($node->$edit_perm_field) ? $node->$edit_perm_field : 0;
-    $view_perm = $edit_perm ? 1 : $node->$view_perm_field;
-    db_query('INSERT INTO {node_access} (nid, gid, realm, grant_view, grant_update, grant_delete) VALUES (%d, %d, \'node_privacy_byrole_role\', %d, %d, %d)', $node->nid, $roleid, $view_perm, $edit_perm, 0);
-    
-  }
-  
-  // Regardless of what permissions the user assigns, make sure s/he has view access to his/her own node
-  // The rest of node_access() ensures edit and delete permissions for the node owner, but relies on the
-  // now deleted default entry, (0,0,'all',1,0,0), to provide view perms to the everyone INCLUDING the node
-  // owner.  This needs to change!
-  
-  // Give owner access to own node always... except in cases where owner is anonymous.  If we allow anonymous
-  // to "own" node, then any anonymous user (i.e., anyone with uid==0) can view the node.  Let role-level perm
-  // determine whether anonymous user should see a node, not user-level perm since uid==0 is in the realm of
-  // the entire anonymous group, not an individual user.
-  if ($user->uid != 0) {
-    db_query('INSERT INTO {node_access} (nid, gid, realm, grant_view, grant_update, grant_delete) VALUES (%d, %d, \'node_privacy_byrole_user\', %d, %d, %d)', $node->nid, $user->uid, 1, 0, 0);
+  if ($user->uid == 1) {
+    return TRUE;
   }
-}
 
-function node_privacy_byrole_update_permissions(&$node) {
-  global $user;
-  db_query('DELETE FROM {node_access} WHERE nid = %d AND realm = \'node_privacy_byrole_role\'', $node->nid); 
-  $edit = $_POST['edit'];
-  $roleids_array = array_keys(user_roles());
-  foreach ($roleids_array as $roleid) {
-    $edit_perm_field = 'node_privacy_byrole_foredit_'. $roleid;
-    $view_perm_field = 'node_privacy_byrole_forview_'. $roleid;
-    $edit_perm = isset($node->$edit_perm_field) ? $node->$edit_perm_field : 0;
-    $view_perm = $edit_perm ? 1 : $node->$view_perm_field;    
-    db_query('INSERT INTO {node_access} (nid, gid, realm, grant_view, grant_update, grant_delete) VALUES (%d, %d, \'node_privacy_byrole_role\', %d, %d, %d)', $node->nid, $roleid, $view_perm, $edit_perm, 0);
-  }
+  $permitted_roles = _node_privacy_byrole_get_default_roles($node->type, 'meta');
+  $user_roles = array_keys($user->roles);
+
+  return count(array_intersect($permitted_roles, $user_roles)) ? TRUE : FALSE;
 }
 
-function node_privacy_byrole_delete_permissions(&$node) {
-       db_query('DELETE FROM {node_access} WHERE nid = %d AND (realm = \'node_privacy_byrole_user\' OR realm = \'node_privacy_byrole_role\')', $node->nid);
+/**
+ * Returns those role id's that are permitted to do $action on a $type node
+ */
+function _node_privacy_byrole_get_default_roles($type, $action) {
+  return variable_get('npbr_default_'. $action .'_perms_'. $type, array());
 }
 
+/**
+ * Form elements that extends node type form
+ * Used for set the default permission settings per node type
+ */
+function node_privacy_byrole_node_type_form(&$form) {
+  $type = $form['#node_type']->type;
+
+  $roles = user_roles();
 
+  $perms = array(
+    'view' => array(
+      'title' => t('Default View Permissions'),
+      'description' => t('Select by role which users can, by default, view nodes of this type.'),
+    ), 
+    'edit' => array(
+      'title' => t('Default Edit Permissions'),
+      'description' => t('Select by role which users can, by default, view nodes of this type.'),
+    ),
+    'grant' => array(
+      'title' => t('Permissions For Permissions'),
+      'description' => t('Select by role which users can, by default, edit nodes of this type.'),
+    ),
+  );
 
-function node_privacy_byrole_formitems(&$form) {
-  if (!variable_get('node_privacy_byrole_enabled', FALSE)) {
-    if (!user_access('administer site configuration')) {
-      return '';
-    }
-    else {
-      drupal_set_message(t('In order to properly enable the node_privacy_byrole module, you must also enable it in the %module_settings_link.',  array('%module_settings_link' => l(t('module\'s settings page'), 'admin/settings/node_privacy_byrole', array('title' => t('node_privacy_byrole module\'s settings page')))   )), 'error');
-      return '';
+  $form['npbr_workflow_settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Node privacy by role'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#weight' => 0
+  );
+
+  foreach($perms as $perm => $permdata) {
+    $permname = 'npbr_default_'. $perm .'_perms';
+
+    $form['npbr_workflow_settings'][$permname] = array(
+      '#tree' => TRUE,
+      '#type' => 'fieldset',
+      '#title' => $permdata['title'],
+      '#collapsible' => FALSE,
+      '#collapsed' => FALSE,
+      '#description' => $permdata['description'],
+      '#weight' => 0,
+    );
+
+    $default_perms = _node_privacy_byrole_get_default_roles($type, $perm);
+
+    foreach (array_keys($roles) as $rid) {
+      $form['npbr_workflow_settings'][$permname][$rid] = array(
+        '#type' => 'checkbox',
+        '#title' => t($roles[$rid]),
+        '#return_value' => 1,
+        '#default_value' => in_array($rid, $default_perms),
+      );
     }
   }
+}
 
+/**
+ * Form elements that extends node edit form
+ */
+function node_privacy_byrole_node_form(&$form) {
+  $roles = array_keys(user_roles());
+  $perms = array('view', 'edit');
   $type = $form['type']['#value'];
-  
   $op = $_POST['op'];
-  $formitems_view = '';
-  $formitems_edit = '';
-  
-  $roles_array = user_roles();
-  $roleids_array = array_keys($roles_array);
-  // if the node already exists, return a form where the permissions already granted are already marked in checkboxes,
-  // else, return a form where all the checkboxes are marked.
+  $node = $form['#node'];
+
+  // create checkboxes for every role and every permission
+  // later depending on the $op variable only the default values will be updated
   $form['node_privacy_byrole'] = array(
-    '#theme' => 'npbr_formitems',
+    '#tree' => TRUE,
+    '#theme' => 'npbr_node_form_items',
     '#type' => 'fieldset',
     '#title' => t('View/Edit Permissions'),
     '#collapsible' => TRUE,
-    '#collapsed' => TRUE
+    '#collapsed' => TRUE,
+    '#weight' => 9,
   );
-  
-  if ($form['nid']['#value']  && $op != t('Preview')) {
-    $current_perms_results = db_query('SELECT gid, grant_view, grant_update FROM {node_access} WHERE nid = %d AND (grant_view = 1 OR grant_update = 1) AND realm = \'node_privacy_byrole_role\'', $form['nid']['#value']);
-    $already_permitted_forview_rids = array();
-    $already_permitted_foredit_rids = array();
-    while($permitted_role = db_fetch_object($current_perms_results)) {
-      $already_permitted_forview_rids[$permitted_role->gid] = $permitted_role->grant_view;
-      $already_permitted_foredit_rids[$permitted_role->gid] = $permitted_role->grant_update;
-    }
 
-    foreach ($roleids_array as $roleid) {
-      $role_name = t($roles_array[$roleid]);
-      
-      $form['node_privacy_byrole']['roles'][$role_name] = array();
-
-      $form['node_privacy_byrole']['roles'][$role_name]['node_privacy_byrole_forview_'. $roleid] = array(
-        '#type' => 'checkbox',
-        '#title' => NULL,
-        '#return_value' => 1,
-        '#default_value' => $already_permitted_forview_rids[$roleid]
-      );
-      
-      $form['node_privacy_byrole']['roles'][$role_name]['node_privacy_byrole_foredit_'. $roleid] = array(
+  foreach ($roles as $rid) {
+    $form['node_privacy_byrole']['roles'][$rid] = array(
+      '#type' => 'fieldset',
+      '#collapsible' => FALSE,
+      '#collapsed' => FALSE,
+      '#weight' => 0
+    );
+    foreach($perms as $perm) {
+      $form['node_privacy_byrole']['roles'][$rid][$perm] = array(
         '#type' => 'checkbox',
         '#title' => NULL,
         '#return_value' => 1,
-        '#default_value' => $already_permitted_foredit_rids[$roleid],
+        '#default_value' => $node->node_privacy_byrole['roles'][$rid][$perm]
       );
-    
-      
-    }
-  }
-  else { // the following generates the form based on the assumption that the node is being created or previewed
-    if ($op == t('Preview')) { // case where node is being previewed
-      $edit = $_POST['edit'];
-      
-      foreach ($roleids_array as $roleid) {
-        $role_name = t($roles_array[$roleid]);
-        $form['node_privacy_byrole']['roles'][$role_name] = array();
-        $form['node_privacy_byrole']['roles'][$role_name]['node_privacy_byrole_forview_'. $roleid] = array(
-          '#type' => 'checkbox',
-          '#title' => NULL,
-          '#return_value' => 1,
-          '#default_value' => $edit['node_privacy_byrole_forview_'. $roleid],
-        );
-        $form['node_privacy_byrole']['roles'][$role_name]['node_privacy_byrole_foredit_'. $roleid] = array(
-          '#type' => 'checkbox',
-          '#title' => NULL,
-          '#return_value' => 1,
-          '#default_value' => $edit['node_privacy_byrole_foredit_'. $roleid],
-        );
-      }
-    }
-    else { // case where node is being created
-      foreach ($roleids_array as $roleid) {
-        $role_name = t($roles_array[$roleid]);
-
-        $form[$role_name] = array();
-        
-        $form['node_privacy_byrole']['roles'][$role_name]['node_privacy_byrole_forview_'. $roleid] = array(
-          '#type' => 'checkbox',
-          '#title' => NULL,
-          '#return_value' => 1,
-          '#default_value' => variable_get('npbr_forview_'. $type .'_default_'. $roleid, 0),
-        );
-        
-        $form['node_privacy_byrole']['roles'][$role_name]['node_privacy_byrole_foredit_'. $roleid] = array(
-          '#type' => 'checkbox',
-          '#title' => NULL,
-          '#return_value' => 1,
-          '#default_value' => variable_get('npbr_foredit_'. $type .'_default_'. $roleid, 0),
-        );
-      }
     }
   }
 }
 
-function theme_npbr_formitems($form) {
+/**
+ * Theming permission settings form elements on node edit form.
+ */
+function theme_npbr_node_form_items($form) {
+  $roles = user_roles();
   $header = array(t('Role'), t('View'), t('Edit'));
+
   $rows = array();
-  foreach (element_children($form['roles']) as $rolename) {
+  // every row is a role
+  foreach (element_children($form['roles']) as $rid) {
     $row = array();
-    $row[] = $rolename;
-    /*
-    foreach ($checkboxes as $checkbox) {
-      $row[] = form_render($checkbox);
-    }
-    */
-    foreach (element_children($form['roles'][$rolename]) as $checkboxindex) {
-      $row[] = form_render($form['roles'][$rolename][$checkboxindex]);
+    $row[] = $roles[$rid];
+    // every column is a permission
+    foreach (element_children($form['roles'][$rid]) as $i) {
+      $row[] = drupal_render($form['roles'][$rid][$i]);
     }
     $rows[] = $row;
   }
-  
-  //return theme('table', $header, $rows, array(), t('Select which users can view/edit your post based on their role.'));
-  return theme('form_element', t('View/Edit Permissions'), theme('table', $header, $rows), t('Select which users can view/edit your post based on their role.'));
-}
 
-function node_privacy_byrole_settings() {
-  if (isset($_POST['edit'])) {
-    $edit = $_POST['edit'];
-    // For some reason, it does not work when we try ($edit['node_privacy_byrole_enabled'] != $edit['node_privacy_byrole_enabled_previous')
-    // for the below if-condition
-    //if ($edit['node_privacy_byrole_enabled'] != $edit['node_privacy_byrole_enabled_previous']) {
-    if ((!$edit['node_privacy_byrole_enabled'] && $edit['node_privacy_byrole_enabled_previous']) ||
-        ($edit['node_privacy_byrole_enabled'] && !$edit['node_privacy_byrole_enabled_previous'])) {
-      cache_clear_all();
-      _node_privacy_byrole_update_db();
-    }
-  }
-  
-  $form = array();
-  
-  if (isset($edit['node_privacy_byrole_enabled'])) {
-    $default = $edit['node_privacy_byrole_enabled'] ? 1 : 0;
-  }
-  else {
-    $default = variable_get('node_privacy_byrole_enabled', FALSE) ? 1 : 0;
-  }
-  
-  $form['node_privacy_byrole_enabled_previous'] = array(
-    '#type' => 'hidden',
-    '#value' => $default,
-  );
-  
-  $form['node_privacy_byrole_enabled'] = array(
-    '#type' => 'radios', 
-    '#default_value' => $default,
-    '#options' => array(1 => t('Enable the node_privacy_byrole module.'), 0 => t('Disable the node_privacy_byrole module.'))
-  );
-  
-  return $form;   
-  
-}
-
-/**
- * Update the node_access table when a user enables/disables the module in the
- * node_privacy_byrole module's settings page.  Because Drupal does not, at this
- * time, provide hooks that run automatically upon the enabling/disabling of a 
- * module in the admin/modules page, we must force the site-admin to explicitly
- * enable/disable a module in the admin/settings/node_privacy_byrole page, in
- * addition to enabling/disabling the module in the admin/modules page.
- *
- * Here, if the user is enabling the module, we make sure the default entry in 
- * the node_access table is deleted and walk through all the nodes in the node_table 
- * and grant all roles view access as is the default case when this module is not 
- * enabled.  We only do this for nodes whose permissions haven't been set before by 
- * this module.  It is possible that a site-admin may have previously enabled the 
- * module before disabling it.  Upon re-enabling, we want to account for the old
- * permissions set by the module by not re-inserting entries for them.
- *
- * Disabling the module simply requires re-inserting the default entry back into 
- * the node access table to give 'view' perms to everyone for everything:
- * (0, 0, 'all', 1, 0, 0)
- */
-function _node_privacy_byrole_update_db() {
-  $edit = $_POST['edit'];
-  if (isset($edit['node_privacy_byrole_enabled']) && !$edit['node_privacy_byrole_enabled']) {
-    // We use the delete statement to avoid inserting a duplicate entry into the database.
-    // Without the DELETE query, this can happen when a site admin has already enabled the modules
-    // from the settings page and goes back to it and resaves the enabled setting.
-    db_query("DELETE FROM {node_access} WHERE nid = 0 AND gid = 0 AND realm = 'all'");
-    db_query("INSERT INTO {node_access} VALUES (0, 0, 'all', 1, 0, 0)");
-  }
-  else { // the module was just enabled; provide default view access to everyone for nodes that were created
-         // between the previous disabling of the module and the current enabling of the module;
-         // nodes that were created during a previous enabled period are left-alone.
-         // Permissions for those nodes will be the same as when the module was previously enabled.
-    db_query('DELETE from {node_access} where nid=0 AND gid=0 AND realm=\'all\' AND grant_view=1 AND grant_update=0 AND grant_delete=0');
-    
-    $rids = array_keys(user_roles());
-    
-    // The following two SELECTS can probably be combined via some JOIN query
-    $nids_from_node_table = db_query('SELECT nid, uid from {node}');
-    while ($current_node_table_row = db_fetch_object($nids_from_node_table)) {
-      $node_access_results = db_query('SELECT COUNT(nid) as already_in_table from {node_access} where nid = %d', $current_node_table_row->nid);
-      
-      $nid_count = db_fetch_object($node_access_results);
-      if (!$nid_count->already_in_table) {
-        foreach ($rids as $rid) {
-          db_query('INSERT INTO {node_access} VALUES (%d, %d, \'node_privacy_byrole_role\', 1, 0, 0)', $current_node_table_row->nid, $rid);
-        }
-
-        db_query('INSERT INTO {node_access} VALUES (%d, %d, \'node_privacy_byrole_user\', 1, 0, 0)', $current_node_table_row->nid, $current_node_table_row->uid);
-      }
-    }   
-  }
+  return theme('form_element', array('#title' => t('View/Edit Permissions'), '#description' => t('Select which users can view/edit your post based on their role.')), theme('table', $header, $rows));
 }
 
 ?>
