Hi there, I've run into some troubles trying to get this module working right (see: https://drupal.org/node/1198552#comment-7650919), here is another report to share with you some more problems and solutions.

Ok, so let's say we've got a forum-topic content type.
On this content-type we've added an optional unique pollfield, so that users can OR NOT add a poll to their topic.

CASE 1: the user create a new topic, with a poll

He sets up everything at the creation of the node, including the poll settings and choices.

In this case everything goes all right:

  1. the pollfield is referenced in the database in the 'pollfield' table
  2. the configured pollfield settings are inserted in the 'content_type_forum_topic' table (or in the 'content_field_*' table if the same pollfield is multiple times)

CASE 2: the user create a new topic, WITHOUT configuring the pollfield

Also in this case everything works as it should:

  • the pollfield is NOT referenced in the database in the 'pollfield' table (we want that)
  • In the 'content_type_forum_topic' table, the pollfield related columns are filled with NULL for strings values and 0 for numeric values (it's ok I guess, I think we want that too)

CASE 3A: the user modify this newly created topic , AGAIN WITHOUT configuring the pollfield

Now the troubles begin ;p

  1. the pollfield is NOT referenced in the database in the 'pollfield' table (ok)
  2. In the 'content_type_forum_topic' table every pollfield columns are set to NULL (hmmm... we don't want exactly that)

We want those fields values to be the same as for the other nodes already created, where the strings are NULL but the numeric values are set to 0.

CASE 3B: the user modify this newly created topic , AND CONFIGURE THE POLLFIELD

  1. the pollfield is NOT referenced in the database in the 'pollfield' table (that's NOT ok anymore)
  2. the configured pollfield settings are inserted in the 'content_type_forum_topic' table (that's ok)

In this case the poll seems to work, but I suspect that the fact that it's not referenced in the 'pollfield' table can only bring trouble.
The pollfield_cron hook for example wouldn't see those polls and won't expire them.

CASE 4: for a configured pollfield, the user REMOVE THE QUESTION

  1. The previous votes for this pollfield remain in the database (ok)
  2. The reference to this pollfield in the 'pollfield' table remain in the database (ok)
  3. ALL the pollfield settings are lost (NOT ok)

To activate the poll the first time, the pollfield module checks if there is a question, kindof a hack, but I can understand.
But when the poll is created, we don't want this check anymore, we don't want to lost all the settings when the question is missing.

CASE 5: the user want to remove completely a poll he created on a topic

  1. HE CAN'T

He can delete all the votes, but he can't delete the reference in the 'pollfield' table, and the settings can't be reset to NULLs and 0s in the database.

CASE 6: the user wants the pollfield fieldset EXPANDED when the poll is activated

Sure he wants that ;p
Here we don't only want to check the presence of the question, we want to be sure that it's a pollfield that is still referenced in the 'pollfield' table

Ok, enough with the problems, it's now time for the SOLUTIONS!
To resolve everything I spent some time and generated some quite ugly code that I'm glad to share with you! ;p

I'm sorry I'm not a patch maker, you'll have to do some copypastas (or wait for mr.j ;p)

So, in the pollfield.module file fond the function:

function pollfield_field($op, &$node, $field, &$items, $teaser, $page)

Replace ALL the function by this:

function pollfield_field($op, &$node, $field, &$items, $teaser, $page) {
  $field_table = $node->type;
  $field_name = $field['field_name'];
  $total_votes = 0;
  switch ($op) {
    case 'validate':
      break;
    case 'delete':
      pollfield_delete($node);
      break;

    // Operation  = create a new pollfield node for the first time
    case 'insert':
      foreach ($items as $key => $item) {
	  
        // Check to see if a pollfield is used or not.
		// Filling the 'question' field triggers the poll creation
        if (!empty($item['question'])) {
          pollfield_field_type_update($op, $node, $field_table, $field_name, $item, $key);

          // Serialize this pollfield's information
          $s = serialize($items[$key]['group']);
          $poll_features = serialize($items[$key]['poll_features']);

          // Store pollfield information the CCK field
          $node->{$field['field_name']}[$key]['choice'] = $s;
          $items[$key]['choice'] = $s;
          $items[$key]['votes'] = pollfield_sum_starting_votes($items[$key]['group']);
          $items[$key]['poll_features'] = $poll_features;
        
		} else {
		
		// Set to defaults
		  $result = db_result(db_query("SELECT widget_settings FROM {content_node_field_instance} WHERE field_name='%s' AND type_name='%s'", $field_name, $field_table));
          $default_settings = unserialize($result);
		  
		  $items[$key]['question'] = NULL;
		  $items[$key]['active'] = $default_settings['default_value'][$key]['active'];
		  $items[$key]['runtime'] = $default_settings['default_value'][$key]['runtime'];
		  $items[$key]['choice'] = NULL;
		  $items[$key]['votes'] = 0;
		  $items[$key]['anonymous'] = NULL;
		  $items[$key]['poll_features'] = NULL;			

		}
      }
      break;

    // Operation  = edit a node
    case 'update':
      foreach ($items as $key => $item) {
 
        // On the node edit form you have the option to delete all votes.
        // Delete all votes if this is checked.
		// ADDITIONS: This will also remove all the pollfield references and settings !
        if ($item['delete_votes']==1) {
          pollfield_delete_votes($node, $field_table, $field_name, $key);
		}  
		
		if ($item['delete_poll']==1) {
		  pollfield_delete_votes($node, $field_table, $field_name, $key);
		  db_query("DELETE from {pollfield} WHERE nid=%d AND field_name='%s' AND field_name_delta=%d",$node->nid, $field_name, $key);
		  
		  // Set to defaults
		  $result = db_result(db_query("SELECT widget_settings FROM {content_node_field_instance} WHERE field_name='%s' AND type_name='%s'",
                                        $field_name, $field_table));
          $default_settings = unserialize($result);
		  
		  $items[$key]['question'] = NULL;
		  $items[$key]['active'] = $default_settings['default_value'][$key]['active'];
		  $items[$key]['runtime'] = $default_settings['default_value'][$key]['runtime'];
		  $items[$key]['choice'] = NULL;
		  $items[$key]['votes'] = 0;
		  $items[$key]['anonymous'] = NULL;
		  $items[$key]['poll_features'] = NULL;
		  break;
        }

		// Check if the poll is referenced
		$result = db_result(db_query("SELECT COUNT(nid) FROM {pollfield}
							WHERE nid=%d AND field_name='%s' AND field_name_delta=%d",$node->nid, $field_name, $key));
		
		// Verify that the poll is referenced, or if not, check if the question field is filled
		if (($result > 0) OR ($result == 0 AND !empty($item['question']))) {
		  
		  if ($result == 0) { // Create the poll reference
		    pollfield_field_type_update('insert', $node, $field_table, $field_name, $item, $key);
		  } else { // Update the poll reference
		    pollfield_field_type_update($op, $node, $field_table, $field_name, $item, $key);
		  }

		  // Serialize this pollfield's information
		  $s = serialize($items[$key]['group']);
		  $poll_features = serialize($items[$key]['poll_features']);

		  // Store pollfield information the CCK field
		  $node->{$field['field_name']}[$key]['choice'] = $s;
		  $items[$key]['choice'] = $s;
		  $items[$key]['votes'] = pollfield_sum_starting_votes($items[$key]['group']);
		  $items[$key]['poll_features'] = $poll_features;
		
		// Else there is no poll, we must set everything to defaults
		} else {
		  // Set to defaults
		  $result = db_result(db_query("SELECT widget_settings FROM {content_node_field_instance} WHERE field_name='%s' AND type_name='%s'", $field_name, $field_table));
		  $default_settings = unserialize($result);
	  
		  $items[$key]['question'] = NULL;
		  $items[$key]['active'] = $default_settings['default_value'][$key]['active'];
		  $items[$key]['runtime'] = $default_settings['default_value'][$key]['runtime'];
		  $items[$key]['choice'] = NULL;
		  $items[$key]['votes'] = 0;
		  $items[$key]['anonymous'] = NULL;
		  $items[$key]['poll_features'] = NULL;		
		}

      }
      break;
  }
}

Then the function:

function pollfield_content_is_empty($item, $field) {

We bypass it (the work is done in the pollfield_field function)

So it gives:

function pollfield_content_is_empty($item, $field) {
  return FALSE;
}

And finally in:

function pollfield_pollfield_process($element, $edit, $form_state, $form) {

After the 'delete_votes' array declaration we add:

  $_delete_poll = array(0 => t('Not delete'), 1 => t('Delete'));
  $element['delete_poll'] = array(
    '#type' => 'checkbox',
    '#title' => t('REMOVE THE POLL'),
    '#description' => t('Delete all references, settings and VOTES on this poll. THIS ACTION CAN NOT BE UNDONE!'),
    '#default_value' => 0,
    '#access' => $admin_pollfield,
  );

To make the fieldset expanded when a poll is activated find this function:

function theme_pollfield($element) {

replace this line:

'#collapsed' => isset($element['#collapsed']) ? $element['#collapsed'] : TRUE,

by this line:

'#collapsed' => isset($element['#collapsed']) ? $element['#collapsed'] : strlen($element['#value']['choice']) == 0,

(this checks that the string value is not NULL, which now happen only when a pollfield has been configured once)

Now everything seems to work has it should on my side, I hope it will on your side too ^^
Don't hesitate to correct my ugly code and tell me if I've done something wrong.

Cheers! ^^

Comments

lemartialou’s picture

Wait! There is one more!

CASE 7: a user WITHOUT pollfield rights edits a topic WITH a pollfield configured and then saves it

  1. choices, votes and features in the 'content_type_forum_topic' table are crushed !!!

Now can we correct that?

YES!

In the big pollfield_field function that I remade and replaced in the previous post find this spot in the case 'update' part :

		  // Serialize this pollfield's information
		  $s = serialize($items[$key]['group']);
		  $poll_features = serialize($items[$key]['poll_features']);

		  // Store pollfield information the CCK field
		  $node->{$field['field_name']}[$key]['choice'] = $s;
		  $items[$key]['choice'] = $s;
		  $items[$key]['votes'] = pollfield_sum_starting_votes($items[$key]['group']);
		  $items[$key]['poll_features'] = $poll_features;

And embrace it with an if:

		  if (!empty($items[$key]['group'])) {
		    
		    // Serialize this pollfield's information
		    $s = serialize($items[$key]['group']);
		    $poll_features = serialize($items[$key]['poll_features']);
		  
		    // Store pollfield information the CCK field
		    $node->{$field['field_name']}[$key]['choice'] = $s;
		    $items[$key]['choice'] = $s;
		    $items[$key]['votes'] = pollfield_sum_starting_votes($items[$key]['group']);
		    $items[$key]['poll_features'] = $poll_features;
		  }

Et voilà! Now the non-authorized user doesn't crush anything, and that's good! ;p

Hope I'm done with bugs now, I really need some sleep... ^^