Index: cck_field_privacy.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/cck_field_privacy/cck_field_privacy.module,v
retrieving revision 1.3.2.2.2.10
diff -u -r1.3.2.2.2.10 cck_field_privacy.module
--- cck_field_privacy.module	21 Mar 2009 20:46:15 -0000	1.3.2.2.2.10
+++ cck_field_privacy.module	10 May 2009 03:39:45 -0000
@@ -143,98 +143,172 @@
  * Implementation of hook_form_alter().
  */
 function cck_field_privacy_form_alter(&$form, &$form_state, $form_id) {
+
   global $user;
-  
-  $uid = (int) isset($form['#node']->uid)? $form['#node']->uid : $user->uid; // original author or current user (authoring new node)
+
   $types = variable_get('cckfp_types', NULL);
   if (is_array($types)) {
-    if (!array_key_exists($form['#node']->type, $types) && !in_array($form['page']['#value']->options['content-type'], $types)) {
-      return; // abort
-    }
+    if (array_key_exists($form['#node']->type, $types) || in_array($form['page']['#value']->options['content-type'], $types)) {
 
-    // Get the stored fields
-    $fields = variable_get('cckfp_types', NULL);
-    $values = unserialize(variable_get('cckfp_values', array()));
-
-    $cckfp_enabled_fields = array();
-
-    // Figure out what node type (via name) we are accessing.
-    $node_name = $form['type']['#value'];
-    if (array_key_exists($node_name, $fields)) {
-      if ($fields[$node_name] != '0') {
-        foreach ($values as $name => $value) {
-          if ($name == $node_name) {
-            foreach ($value as $field => $enabled) {
-              if (!$enabled) continue;
-              if (array_key_exists($field, $form)) {
-                if (isset($form[$field][0])) {
-                  $form_field =& $form[$field][0];
-                } 
-                elseif (isset($form[$field]['keys'])) {
-                  $form_field =& $form[$field]['keys'];
-                } 
-                elseif (isset($form[$field]['key'])) {
-                  $form_field =& $form[$field]['key'];
+      $fields = variable_get('cckfp_types', NULL);
+      $values = unserialize(variable_get('cckfp_values', array()));
+      $node_type = $form['type']['#value'];
+
+      // workaround : exclude user_register to avoid fields being treated
+      // two times when the content profile registration module is used
+
+      if (($form_id != "user_register") && is_array($values[$node_type])) {
+
+        $privacyfields = array_filter($values[$node_type]); // get fields which need a padlock
+
+        if (!empty($privacyfields)) {
+
+          // get original author or current user (authoring new node)
+          $u = (int) isset($form['#node']->uid)? $form['#node']->uid : $user->uid;
+          
+          // get the widgets used for fields of this node type
+          $fieldtypes = content_fields(NULL, $node_type); // make use of results cached by _content_type_info, no db hit
+          $needpadlock = array();
+
+          foreach ($privacyfields as $field => $value) {
+
+            // Get the current state of the field and set perms that will be used with jQ impromptu
+            $field_pref_sql = db_query("SELECT permission FROM {cckfp} WHERE uid = %d AND type_name = '%s' AND field_name = '%s'", $u, $node_type, $field);
+            $field_pref = (string) db_result($field_pref_sql);
+            if ($field_pref == "") {
+              $field_pref = variable_get('cckfp_'. $node_type .'_default', 'e'); // Set to the default state of the field
+            }
+            $privacyfields[$field] = $field_pref;
+            
+            switch ($fieldtypes[$field]['widget']['type']) {
+
+              // treats special cases separately :
+              // $form['#field_info'][$field]['widget']['label'] used insted of ['#title']
+              // some other CCK fields should be treated here
+              // TODO : do not work for date fields if end dates or repetitions are set
+
+              case "email_textfield" :
+              case "date_select" :
+              case "date_combo" :
+              case "date_popup" :
+              case "date_text" :
+                if (isset($form['#field_info'][$field]['widget']['label'])) {
+                  $form['#field_info'][$field]['widget']['label'] .= " <a href='#' id='". $field ."link'><img src='". base_path() . drupal_get_path('module', 'cck_field_privacy') ."/padlock.png' alt='". t(Privacy) ."' /></a>";
                 } 
                 else {
-                  $form_field =& $form[$field];
-                }
-                // Get the current state of the field
-                $field_pref_sql = db_query("SELECT permission FROM {cckfp} WHERE uid = %d AND type_name = '%s' AND field_name = '%s'", $uid, $node_name, $field);
-                $field_pref = (string) db_result($field_pref_sql);
-                if ($field_pref == "") {
-                  //Get the default state of the field
-                  $type_default_name = 'cckfp_' . $node_name .'_default';
-                  $field_pref = variable_get($type_default_name, 'e');
-                }  
-
-                // Let's add the field name to the array of fields
-                $cckfp_enabled_fields[$field] = $field_pref;
-
-                // Add the padlock icon & link to the JQuery function
-                // @TODO: Add this via jQuery to degrade gracefully in browsers without JavaScript enabled.
-                // @TODO: Get the padlock to also appear on field group titles (fieldset legends), if selected.
-                if (isset($form_field['#title'])) {                  
-                  $form_field['#title'] .= "<a href='#' id='". $field ."link' ><img src='". base_path() . drupal_get_path('module', 'cck_field_privacy') ."/padlock.png' /></a>";
-                  //email fields are special, they must be handled a bit differently.
-                  if (in_array($form[$field][0]['#type'], array("email_textfield", "date_combo"))) {
-                    $form['#field_info'][$field]['widget']['label'] .= "<a href='#' id='". $field ."link' ><img src='". base_path() . drupal_get_path('module', 'cck_field_privacy') ."/padlock.png' /></a>";
-                  }
-                }
-                else if (isset($form[$field]['#title'])) {
-                  $form[$field]['#title'] .= "<a href='#' id='". $field ."link' ><img src='". base_path() . drupal_get_path('module', 'cck_field_privacy') ."/padlock.png' /></a>";
-                }
-                else if (isset($form_field[0]['#title'])) {
-                  $form_field[0]['#title'] .= "<a href='#' id='". $field ."link' ><img src='". base_path() . drupal_get_path('module', 'cck_field_privacy') ."/padlock.png' /></a>";
-                }
-                else {
-                  $form['#field_info'][$field]['widget']['label'] .= "<a href='#' id='". $field ."link' ><img src='". base_path() . drupal_get_path('module', 'cck_field_privacy') ."/padlock.png' /></a>";
+                  $needpadlock[$field] = TRUE;
                 }
-              }
+                break;
+              // other special case goes here
+
+              // normal cases that need will be treated  recursively throught the form
+              // case "location_element" : // shown as fieldset with various sub fields
+              // case "link" : // code needs work
+              // case "optionwidgets_select" :
+              // case "userreference_autocomplete" :
+              // case "userreference_select" :
+              default : $needpadlock[$field] = TRUE; // field still need a padlock
             }
           }
+
+          if (!empty($needpadlock)) { // look for fields left recursively throught the form
+            _cck_field_privacy_add_padlock($form, $needpadlock);
+          }
+
+          // include javascript and css only if needed
+          jquery_impromptu_add();
+          drupal_add_js(drupal_get_path('module', 'cck_field_privacy') .'/cck_field_privacy.js');
+          drupal_add_js(array(
+            'cck_field_privacy' => array(
+              'action' => url('cck_field_privacy/ajax'),
+              'uid' => $u,
+              'content_type' => $node_type,
+              'default_value' => $privacyfields,
+              ),
+            ), 'setting');
         }
       }
-
-      // include javascript and css
-      jquery_impromptu_add(); // css and js
-      drupal_add_js(drupal_get_path('module', 'cck_field_privacy') .'/cck_field_privacy.js');
-
-      // output per-page settings
-      drupal_add_js(array(
-        'cck_field_privacy' => array(
-          'action' => url('cck_field_privacy/ajax'),
-          'uid' => $uid,
-          'content_type' => $node_name,
-          'default_value' => $cckfp_enabled_fields,
-        ),
-      ), 'setting');
     }
   }
   return $form;
 }
 
 /**
+ * Recursively add a padlock where needed
+ */
+function _cck_field_privacy_add_padlock(&$elements, &$needpadlock) {
+
+  // only treats keys that are not properties (i.e., does not begin with '#')
+  foreach (element_children($elements) as $field) {
+    if (isset($elements[$field]) && $elements[$field]) {    
+      if (array_key_exists($field, $needpadlock)) { // form element is handled by cckfp
+        $lockimg = "<a href='#' id='". $field ."link'><img src='". base_path() . drupal_get_path('module', 'cck_field_privacy') ."/padlock.png' alt='". t(Privacy) ."' /></a>";
+        if (isset($elements[$field][0]['#type'])) { // content sub field first
+          switch ($elements[$field][0]['#type']) {
+            case "link" : // link widget
+              // WARNING : possibly 2 text fields with the same label shown 2 times
+              // with different suffix 'Title' and 'URL' : only the 'first label id' will work
+              // should use the widget description or some theming on the widget output
+              $elements[$field][0]['#title'] = $lockimg ." ". $elements[$field][0]['#title'];
+              break;
+
+            case "userreference_autocomplete" :
+              // ugly display if content_multiple_values is used
+              // padlock shoud be shown after $elements[$field]['#title'] but it does not react
+              $elements[$field][0]['#title'] .= " ". $lockimg;
+              break;
+                    
+            default : // assume field is a standard CCK field and not fieldgroup
+              $elements[$field][0]['#title'] .= " ". $lockimg;
+              break;
+          }
+        }
+        elseif (isset($elements[$field]['#type'])) {
+          switch ($elements[$field]['#type']) {
+            case "tabpage" :
+              // fielgroup shown as tab by the cck fieldgroup tabs module
+              // label will be already a link that should be closed first
+              // but an <h2> tag without link also use this label
+              // html validation error without modifiing tabs' template
+              $elements[$field]['#title'] .= $lockimg;
+              break;
+
+            case "fieldset" :
+              if (isset($elements[$field]['#collapsible'])
+                    && ($elements[$field]['#collapsible'] == 1)) { // collapsible fieldset
+                     // using description because a padlock in the clickable legend tag will not work
+                    $elements[$field]['#description'] = $lockimg ." ". $elements[$field]['#description'];
+              }
+              else { $elements[$field]['#title'] .= " ". $lockimg; }
+              break;
+
+            case "userreference_select" :
+            case "optionwidgets_select" :
+              $elements[$field]['#title'] .= " ". $lockimg;
+              break;
+
+            default : // TODO : field probably not properly handled
+              $elements[$field]['#title'] .= " ". $lockimg;
+              break;
+          }
+        }
+        else { 
+          /* field type not properly handled */ 
+        }
+
+        $needpadlock[$field] = FALSE;
+        $needpadlock = array_filter($needpadlock);
+      }
+
+      if (!empty($needpadlock)) {
+          // recursing through children elements if privacy fields left
+          _cck_field_privacy_add_padlock($elements[$field], $needpadlock);
+      }
+    }
+  }
+}
+
+/**
  * MENU_CALLBACK for cck_field_privacy/ajax.
  *
  * @return String

