? flexinode_crud.patch
Index: flexinode.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flexinode/flexinode.module,v
retrieving revision 1.63
diff -u -F^f -r1.63 flexinode.module
--- flexinode.module	13 Dec 2005 04:31:07 -0000	1.63
+++ flexinode.module	13 Mar 2006 21:41:19 -0000
@@ -74,6 +74,7 @@ function flexinode_help($section) {
  */
 function flexinode_perm() {
   $perms = array('administer content types');
+
   foreach (flexinode_content_types() as $ctype) {
     $perms[] = 'create '. $ctype->name .' content';
     $perms[] = 'edit own '. $ctype->name .' content';
@@ -92,7 +93,7 @@ function flexinode_settings() {
     '#title' => t('Number of posts in flexinode listings'),
     '#description' => t('Number of posts to show on flexinode listing pages.'),
     '#default_value' => variable_get('flexinode_list_count', 10),
-    
+
     );
   return $form;
 }
@@ -343,7 +344,7 @@ function flexinode_page_admin($ctype_id 
     $ctype->links[] = l(t('edit content type'), 'admin/node/type/' . $ctype->ctype_id);
     $ctype->links[] = l(t('settings'), 'admin/settings/content-types/flexinode-' . $ctype->ctype_id);
 
-    
+
     $ctype->controls = flexinode_field_select($ctype->ctype_id);
 
     foreach ($ctype->fields as $field) {
@@ -353,7 +354,7 @@ function flexinode_page_admin($ctype_id 
     $output .= theme('flexinode_type', $ctype, ($first || ($ctype_id == $ctype->ctype_id)));
     $first = FALSE;
   }
-  
+
   if (strlen($output) == 0) {
     $output = '<p>'. t('No flexinode content types have been defined. You can <a href="%url">add a new content type</a>.', array('%url' => url('admin/node/type'))) .'</p>';
   }
@@ -493,16 +494,19 @@ function flexinode_access($op, $node) {
  */
 function flexinode_load($node) {
   $ctype = flexinode_load_content_type(substr($node->type, 10));
+  global $user;
 
   // build the query
   $fields_to_select = array();
   $table_joins = array();
 
   foreach ($ctype->fields as $field) {
-    $fieldname = 'flexinode_'. $field->field_id;
+    if (in_array($user->roles, $field->access['view'])) {
+      $fieldname = 'flexinode_'. $field->field_id;
 
-    $fields_to_select[] = flexinode_invoke('db_select', $field);
-    $table_joins[] = 'LEFT JOIN {flexinode_data} '. $fieldname .' ON n.nid = '. $fieldname .'.nid AND '. $fieldname .'.field_id = ' . $field->field_id;
+      $fields_to_select[] = flexinode_invoke('db_select', $field);
+      $table_joins[] = 'LEFT JOIN {flexinode_data} '. $fieldname .' ON n.nid = '. $fieldname .'.nid AND '. $fieldname .'.field_id = ' . $field->field_id;
+    }
   }
 
   if (count($fields_to_select) > 0) {
@@ -563,6 +567,7 @@ function flexinode_delete($node) {
  * Implementation of hook_form().
  */
 function flexinode_form(&$node, &$param) {
+  global $user;
   // Set form parameters so we can accept file uploads.
   $form['#attributes'] = array('enctype' => 'multipart/form-data');
 
@@ -572,11 +577,13 @@ function flexinode_form(&$node, &$param)
   $ctype = flexinode_load_content_type($node->ctype_id);
 
   foreach ($ctype->fields as $field) {
-    $items = flexinode_invoke('form', $field, $node);
-    // if anyone knows a better way to pass back an array and key value at the same time without passing the $form by
-    // ref I would like to know ;)
-    foreach($items as $key => $item) {
-      $form[$key] = $item;
+    if (in_array($user->role['edit'], $field->access)) {
+      $items = flexinode_invoke('form', $field, $node);
+      // if anyone knows a better way to pass back an array and key value at the same time without passing the $form by
+      // ref I would like to know ;)
+      foreach($items as $key => $item) {
+        $form[$key] = $item;
+      }
     }
   }
 
@@ -601,6 +608,7 @@ function flexinode_form(&$node, &$param)
  * Implementation of hook_validate().
  */
 function flexinode_validate($node) {
+  global $user;
   node_validate_title($node);
 
   if (isset($node->ctype_id)) {
@@ -608,7 +616,13 @@ function flexinode_validate($node) {
     foreach ($ctype->fields as $field) {
       $fieldname = 'flexinode_'. $field->field_id;
       $validation = flexinode_invoke('validate', $field, $node);
-      if ($field->required && !$node->$fieldname) {
+      if ($node->nid && !in_array($user->role, $field->access['edit'])) { //editing an existing node.
+        form_set_error($fieldname, t('You have no permissions to edit "'. $field->label .'".'));
+      }
+      elseif (!in_array($user->role, $field->access['create'])) {
+        form_set_error($fieldname, t('You have no permissions to create "'. $field->label .'".'));
+      }
+      elseif ($field->required && !$node->$fieldname) {
         form_set_error($fieldname, t('You must fill in the field "'. $field->label .'".'));
       }
     }
@@ -781,6 +795,10 @@ function flexinode_load_content_type($ct
   $ctype->fields = array();
   $result = db_query('SELECT * FROM {flexinode_field} WHERE ctype_id = %d ORDER BY weight ASC, label ASC', $ctype_id);
   while ($field = db_fetch_object($result)) {
+    $role_result = db_query('SELECT * FROM {flexinode_permissions} WHERE field_id = %d ORDER BY weight ASC, label ASC', $field->field_id);
+    while ($role = db_fetch_object($role_result)) {
+      $field->access[$role->type][$role->rid] = TRUE;
+    }
     $field->options = unserialize($field->options);
     $ctype->fields[] = $field;
   }
@@ -910,6 +928,42 @@ function flexinode_delete_content_type($
 }
 
 /**
+ * API to see if the action is allowed.
+ */
+function flexinode_handler_filter_role($field, $action, $custom_user = NULL) {
+  if (empty($custom_user->uid)) {
+   global $user;
+  }
+  else {
+    $user = $custom_user;
+  }
+
+  if (!$field->access['action']) {
+    //nothing defined == all access.
+    return TRUE;
+  }
+  else {
+    foreach ($field->access['action'] as $rid) {
+      if (in_array($rid, $user->roles)) {
+        return TRUE;
+      }
+    }
+  }
+  return FALSE;
+}
+/**
+ * Create a list of roles.
+ */
+function flexinode_handler_filter_role() {
+  $rids = array();
+  $result = db_query("SELECT r.rid, r.name FROM {role} r ORDER BY r.name");
+  while ($obj = db_fetch_object($result)) {
+    $rids[$obj->rid] = $obj->name;
+  }
+  return $rids;
+}
+
+/**
  * FLEXINODE FIELD FUNCTIONS
  */
 
@@ -994,6 +1048,37 @@ function flexinode_field_form($field_id,
     '#delta' => 10,
     '#description' => t('Optional. On the content editing form, the heavier fields will sink and the lighter fields will be positioned nearer the top.'),
     );
+
+   $form['access'] = array(
+     '#type' => 'fieldset',
+     '#title' => t('Permissions'),
+     '#collapsible' => true,
+     '#collapsed' => true,
+     '#tree' => true,
+     //'#description' => t('If, for a permission, no roles are checked, access will not be restricted for that permission'),
+     );
+  $form['access']['create'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Create permissions'),
+    '#default_value' => $field->access['create'],
+    '#options' => flexinode_handler_filter_role(),
+    '#description' => t('Only the checked roles will be able to fill in this field on creation of a new post.'),
+    );
+  $form['access']['view'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('View permissions'),
+    '#default_value' => $field->access['view'],
+    '#options' => flexinode_handler_filter_role(),
+    '#description' => t('Only the checked roles will be able to see the value from this field in the output.'),
+    );
+  $form['access']['edit'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Edit permissions'),
+    '#default_value' => $field->access['edit'],
+    '#options' => flexinode_handler_filter_role(),
+    '#description' => t('Only the checked roles will be able to edit the value of an existing post.'),
+    );
+
   $form['submit'] = array(
     '#type' => 'submit',
     '#value' => t('Submit'),
@@ -1102,13 +1187,24 @@ function flexinode_save_field($edit) {
 
     db_query("UPDATE {flexinode_field} SET label = '%s', default_value = '%s', rows = %d, required = %d, show_teaser = %d, show_table = %d, weight = %d, ctype_id = %d, field_type = '%s', options = '%s', description = '%s' WHERE field_id = %d", $edit['label'], $edit['default_value'], $edit['rows'], $edit['required'], $edit['show_teaser'], $edit['show_table'], $edit['weight'], $edit['ctype_id'], $edit['field_type'], serialize($options), $edit['description'], $field_id);
 
+    foreach ($edit['access'] as $type => $roles) {
+      foreach ($roles as $rid) {
+        db_query("UPDATE {flexinode_permissions} SET rid = '%d', type = '%s' WHERE field_id = %d", $rid, $type, $field_id);
+      }
+    }
+
     drupal_set_message(t('updated field "%name".', array('%name' => $edit['label'])));
   }
   else {
     $field_id = db_next_id('{flexinode_field}');
-
     db_query("INSERT INTO {flexinode_field} (label, default_value, rows, required, show_teaser, show_table, weight, ctype_id, field_type, options, description, field_id) VALUES ('%s', '%s', %d, %d, %d, %d, %d, %d, '%s', '%s', '%s', %d)", $edit['label'], $edit['default_value'], $edit['rows'], $edit['required'], $edit['show_teaser'], $edit['show_table'], $edit['weight'], $edit['ctype_id'], $edit['field_type'], serialize($options), $edit['description'], $field_id);
 
+    foreach ($edit['access'] as $type => $roles) {
+      foreach ($roles as $rid) {
+        db_query("INSERT INTO {flexinode_permissions} (rid, type, field_id) VALUES ('%d', '%s', %d)", $rid, $type, $field_id);
+      }
+    }
+
     drupal_set_message(t('created new field "%name".', array('%name' => $edit['label'])));
   }
 
@@ -1138,6 +1234,7 @@ function flexinode_delete_field($field) 
   // TODO: Delete files as appropriate.
   db_query('DELETE FROM {flexinode_field} WHERE field_id = %d', $field->field_id);
   db_query('DELETE FROM {flexinode_data} WHERE field_id = %d', $field->field_id);
+  db_query('DELETE FROM {flexinode_permissions} WHERE field_id = %d', $field->field_id);
 
   drupal_set_message(t('deleted field %name', array('%name' => $field->label)));
 }
