'Vote', 'page callback' => 'pollfield_vote', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); return $items; } /** * Implementation of hook_help(). */ function pollfield_help($path, $arg) { switch ($path) { case 'admin/help#pollfield': $output = '

'. t('The poll module can be used to create simple polls for site users. A poll is a simple multiple choice questionnaire which displays the cumulative results of the answers to the poll. Having polls on the site is a good way to get instant feedback from community members.') .'

'; $output .= '

'. t('Users can create a poll. Create a question, then enter the responses and the "base" vote counts. You can also choose the time period over which the vote will run.') .'

'; return $output; } } /** * Implementation of hook_theme(). */ function pollfield_theme() { return array( 'pollfield' => array( 'arguments' => array('element' => NULL), ), 'pollfield_formatter_default' => array( 'arguments' => array('element'), ), ); } /** * What you see in the edit node * * @param unknown_type $element * @return unknown */ function theme_pollfield($element) { $output = '
Poll'.$element['#children'].'
'; return $output; } /** * what you see in the node view * * @param unknown_type $element * @return unknown */ function theme_pollfield_formatter_default($element) { global $user; $items = $element['#item']; $node = $element['#node']; $field_name = $element['#field_name']; $field = content_fields($field_name); $show_form = true; if ($user->uid) { $kount = db_result(db_query("SELECT count(*) as kount from {pollfield_votes} WHERE nid = %d AND field_name = '%s' AND uid = %d AND field_name_delta=%d", $node->nid, $field_name, $user->uid, $items['#delta'])); $show_form = $kount > 0 ? FALSE : TRUE; } if ($show_form) { $form = pollfield_voting_form($element); $out = '
'; $out .= '
'.$element['#item']['question'].'
'; $out .= $form; $out .= '
'; return $out; } else { return '';// shoudl call theme_pollfield_results } } function pollfield_voting_form(&$element) { $form = array(); $form_state = array(); $field_name = $element['#field_name']; $items = $element['#item']; $node = $element['#node']; if ($items) { $list = array(); $choices = unserialize($items['choice']); if (!empty($choices)) { foreach ($choices as $delta => $choice) { $list[$delta] = check_plain($choice['choice']); } $form['choice'] = array('#type' => 'radios', '#title' => $question, '#default_value' => -1, '#options' => $list); } } $form['field_name'] = array('#type' => 'hidden', '#value' => $field_name); $form['nid'] = array('#type' => 'hidden', '#value' => $node->nid); $form['vote'] = array('#type' => 'submit', '#value' => t('Vote')); $form['delta'] = array('#type' => 'hidden', '#value' => $items['#delta']); $form['#action'] = url('pollfield/vote'); $form['#type'] = 'form'; $form = form_builder('voting', $form, $form_state); $output = drupal_render($form); return $output; } /** * Implementation of hook_field_info(). * * Here we indicate that the content module will use its default * handling for the view of this field. * * Callbacks can be omitted if default handing is used. * They're included here just so this module can be used * as an example for custom modules that might do things * differently. */ function pollfield_field_info() { return array( 'pollfield' => array( 'label' => t('Pollfield'), 'description' => t('This is to store poll as a field and not as a node'), ), ); } /** * Implementation of hook_field_settings(). */ function pollfield_field_settings($op, $field) { switch($op) { case 'database columns': // It would be more efficient not to store the question and runtime in // every field, but that makes the Views integration much more complex. // This way also creates an separate table with complete poll result // data for each individual pollfield, making it easier to do other // integration with or manipulation of the data. $columns['question'] = array('type' => 'text', 'not null' => TRUE, 'default' => "' '", 'sortable' => TRUE); $columns['active'] = array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'sortable' => TRUE); $columns['runtime'] = array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'sortable' => TRUE); $columns['choice'] = array('type' => 'text', 'not null' => TRUE, 'default' => "' '", 'sortable' => TRUE); $columns['votes'] = array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'sortable' => TRUE); return $columns; } } /** * Implementation of hook_field(). */ function pollfield_field($op, &$node, $field, &$items, $teaser, $page) { // do nothing for now switch ($op) { case 'validate': //debug($items); break; case 'presave': $db_info = content_database_info($field); foreach ($items as $key => $item) { $choices = array(); foreach ($item['group'] as $delta => $group) { if (empty($group['choice'])) { unset($items[$key]['group'][$delta]); } } $s = serialize($items[$key]['group']); $node->{$field['field_name']}[$key]['choice'] = $s; $items[$key]['choice'] = $s; } break; } } /** * Implementation of hook_content_is_empty(). */ function pollfield_content_is_empty($item, $field) { if(empty($item['question'])) { return TRUE; } return FALSE; } /** * Implementation of hook_field_formatter_info(). */ function pollfield_field_formatter_info() { return array( 'default' => array( 'label' => 'Default', 'field types' => array('pollfield'), 'multiple values' => CONTENT_HANDLE_CORE, ), 'choices' => array( 'label' => 'All choices', 'field types' => array('pollfield'), 'multiple values' => CONTENT_HANDLE_CORE, ), 'results' => array( 'label' => 'All results', 'field types' => array('pollfield'), 'multiple values' => CONTENT_HANDLE_CORE, ), 'voting' => array( 'label' => 'Voting widget', 'field types' => array('pollfield'), 'multiple values' => CONTENT_HANDLE_CORE, ), 'question' => array( 'label' => 'Question', 'field types' => array('pollfield'), 'multiple values' => CONTENT_HANDLE_CORE, ), 'runtime' => array( 'label' => 'Runtime', 'field types' => array('pollfield'), 'multiple values' => CONTENT_HANDLE_CORE, ), 'active' => array( 'label' => 'Active', 'field types' => array('pollfield'), 'multiple values' => CONTENT_HANDLE_CORE, ), 'choice' => array( 'label' => 'Choice item (Views only)', 'field types' => array('pollfield'), 'multiple values' => CONTENT_HANDLE_CORE, ), 'votes' => array( 'label' => 'Vote item (Views only)', 'field types' => array('pollfield'), 'multiple values' => CONTENT_HANDLE_CORE, ), ); } function theme_pollfield_formatter_results($element) { // todo and other formattings } /** * Implementation of hook_elements(). */ function pollfield_elements() { return array( 'pollfield' => array( '#input' => TRUE, '#process' => array('pollfield_pollfield_process'), ), ); } /** * Process an individual element. * * Build the form element. When creating a form using FAPI #process, * note that $element['#value'] is already set. * * The $fields array is in $form['#field_info'][$element['#field_name']]. * */ function pollfield_pollfield_process($element, $edit, $form_state, $form) { $field1 = $form['#field_info'][$element['#field_name']]; $delta = $element['#delta']; $cols = $element['#columns']; $blank_fields = $field['widget']['blanks']; $field = $cols[0]; $element[$field] = array( '#type' => 'textfield', '#title' => t('Question'), '#rows' => 2, '#default_value' => isset($element['#value'][$field]) ? $element['#value'][$field] : '', '#description' => t('The question this poll will ask.'), ); $_duration = array(0 => t('Unlimited')) + drupal_map_assoc(array(86400, 172800, 345600, 604800, 1209600, 2419200, 4838400, 9676800, 31536000), "format_interval"); $_active = array(0 => t('Closed'), 1 => t('Active')); $field = $cols[1]; $element[$field] = array( '#type' => 'radios', '#title' => t('pollfield status'), '#default_value' =>isset($element['#value'][$field]) ? $element['#value'][$field] : 1, '#options' => $_active, '#description' => t('When a pollfield is closed, visitors can no longer vote for it.') ); $field = $cols[2]; $element[$field] = array( '#type' => 'select', '#title' => t('pollfield duration'), '#default_value' => isset($element['#value'][$field]) ? $element['#value'][$field] : 1, '#options' => $_duration, '#description' => t('After this period, the pollfield will be closed automatically.') ); $max = max($blank_fields, intval(sizeof($items) - 4 + $blank_fields)); $reasons = unserialize($element['#value']['choice']); //$element['#description'] = $field['widget']['description']; foreach (range(0, $max) as $delta) { $element['group'][$delta] = array( '#type' => 'fieldset', '#title' => t('Choice #%delta', array('%delta' => intval($delta + 1))), '#tree' => TRUE, ); $element['group'][$delta]['choice'] = array( '#title' => t('Response'), '#type' => 'textfield', '#default_value' => isset($reasons[$delta]['choice']) ? $reasons[$delta]['choice'] : '', //'#required' => ($delta == 0) ? $field['required'] : FALSE, '#rows' => 2, '#weight' => floatval($field1['widget']['weight'] + ($delta / 10)), ); $element['group'][$delta]['votes'] = array( '#title' => t('Votes'), '#type' => 'textfield', '#default_value' => isset($reasons[$delta]['votes']) ? $reasons[$delta]['votes'] : '', '#size' => 10, '#weight' => floatval($field1['widget']['weight'] + ($delta / 10) + .1), ); } //debug($element); return $element; } /** * Implementation of hook_widget(). * */ function pollfield_widget(&$form, &$form_state, $field, $items, $delta = 0) { $element = array( '#type' => $field['widget']['type'], '#default_value' => isset($items[$delta]) ? $items[$delta] : NULL, ); return $element; } /** * Implementation of hook_widget_info(). */ function pollfield_widget_info() { return array( 'pollfield' => array( 'label' => 'Pollfield', 'field types' => array('pollfield'), 'multiple values' => CONTENT_HANDLE_CORE, ), ); } /** * Implementation of hook_widget_settings(). */ function pollfield_widget_settings($op, $widget) { switch ($op) { case 'form': $form = array(); $form['blanks'] = array( '#type' => 'textfield', '#title' => t('Blank questions'), '#default_value' => isset($widget['blanks']) ? $widget['blanks'] : 3, '#description' => t('The number of blank question fields to display each time the poll is edited.'), '#element_validate' => array('_pollfield_widget_settings_blank_questions_validate'), ); return $form; case 'save': return array('blanks'); } } /** * Internal callback to validate number of blank questions */ function _pollfield_widget_settings_blank_questions_validate($element, &$form_state) { $value = $form_state['values']['blanks']; if (!is_numeric($value) || intval($value) != $value || $value < 2) { form_error($element, t('"Blank Questions" must be a positive integer and it should be greater than or equal to 2.')); } } function pollfield_vote() { global $user; $form_values = $_POST; $nid = $form_values['nid']; $node = node_load($nid); if ($node->nid) { $field_name = $form_values['field_name']; $field = content_fields($form_values['field_name']); $voted = $form_values['choice']; $choices = unserialize($node->{$field_name}['0']['choice']); $valid = FALSE; foreach ($choices as $delta => $option) { if ($voted == $delta) { $valid = TRUE; break; } } if ($voted && $valid) { $voted = FALSE; if ($user->uid) { $voted = db_result(db_query("SELECT delta from {pollfield_votes} WHERE nid = %d AND field_name = '%s' AND uid = %d AND field_name_delta=%d", $node->nid, $field_name, $user->uid, $form_values['delta'])); } else { $voted = db_result(db_query("SELECT delta from {pollfield_votes} WHERE nid = %d AND field_name = '%s' AND hostname = '%s'", $node->nid, $field_name, $_SERVER['REMOTE_ADDR'])); } $choice = $form_values['choice']; //if (!$voted && $node->pollfield[$field['field_name']]['allowvotes']) { if (!$voted) { // Mark the user or host as having voted. $db_info = content_database_info($field); if ($user->uid) { db_query("INSERT INTO {pollfield_votes} (nid, field_table, field_name, field_name_delta, uid, delta) VALUES (%d, '%s', '%s', %d, %d, %d)", $node->nid, $db_info['table'], $field_name, $form_values['delta'],$user->uid, $choice); } else { db_query("INSERT INTO {pollfield_votes} (nid, field_table, field_name, field_name_delta, hostname, delta) VALUES (%d, '%s', '%s', %d, '%s', %d)", $node->nid, $db_info['table'], $field_name, $form_values['delta'],$_SERVER['REMOTE_ADDR'], $choice); } // Add one to the votes. $db_info = content_database_info($field); db_query("UPDATE {". $db_info['table'] ."} SET ". $field_name ."_votes = ". $field_name ."_votes + 1 WHERE nid = %d AND delta = %d", $node->nid, $choice); // Any time a vote is recorded, clear the CCK cache so the votes can be updated. pollfield_clear($node); $node->pollfield[$field_name]['allowvotes'] = FALSE; $node_field = $node->$field_name; $node_field[$choice]['votes']++; $node->$field_name = $node_field; drupal_set_message(t('Your vote was recorded.')); } else { drupal_set_message(t("You're not allowed to vote on this pollfield."), 'error'); } } else { drupal_set_message(t("You didn't specify a valid pollfield choice."), 'error'); } // Set destination to override #action that would redirect back to pollfield/vote. $_REQUEST['destination'] = 'node/'. $nid; drupal_goto('node/'. $nid); } else { drupal_not_found(); } } function pollfield_clear($node) { $cid = 'content:'. $node->nid .':'. $node->nid; cache_clear_all($cid, db_table_exists('cache_content') ? 'cache_content' : 'cache', TRUE); } function theme_pollfield_results($title, $results, $votes, $links, $node, $field_name) { $output .= '
'; $output .= '
'. $title .'
'; $output .= $results; $output .= '
'. t('Total votes: %votes', array('%votes' => $votes)) .'
'; $output .= ''; if ($node->page_context && isset($votes) && $votes > -1 && user_access('cancel own pollfield vote')) { $output .= drupal_get_form('pollfield_cancel_form', $node->nid, $field_name); } $output .= '
'; return $output; }