View source  
  <?php
module_load_include('inc', 'advpoll', 'includes/advpoll_voteapi');
module_load_include('inc', 'advpoll', 'includes/advpoll_helper');
function advpoll_menu() {
  
  $menu['node/%node/advpoll/votes'] = array(
    'title' => 'Votes',
    'page callback' => 'advpoll_votes_page',
    'page arguments' => array(
      1,
    ),
    'access callback' => '_advpoll_votes_access',
    'access arguments' => array(
      1,
    ),
    'weight' => 3,
    'type' => MENU_LOCAL_TASK,
    'file' => 'advpoll.pages.inc',
    'file path' => drupal_get_path('module', 'advpoll') . '/includes',
  );
  
  $menu['node/%node/electoral-list'] = array(
    'title' => 'Electoral list',
    'page callback' => 'advpoll_electoral_list_page',
    'page arguments' => array(
      1,
    ),
    'access callback' => '_advpoll_electoral_list_access',
    'access arguments' => array(
      1,
    ),
    'weight' => 3,
    'type' => MENU_LOCAL_TASK,
    'file' => 'advpoll.pages.inc',
    'file path' => drupal_get_path('module', 'advpoll') . '/includes',
  );
  
  $menu['node/%node/remove'] = array(
    'page callback' => 'advpoll_remove_voter',
    'page arguments' => array(
      1,
    ),
    'access arguments' => array(
      'administer polls',
    ),
    'weight' => 3,
    'type' => MENU_CALLBACK,
    'file' => 'advpoll.pages.inc',
    'file path' => drupal_get_path('module', 'advpoll') . '/includes',
  );
  
  $menu['node/%node/advpoll/votes/clear'] = array(
    'page callback' => 'advpoll_clear_votes_page',
    'page arguments' => array(
      1,
    ),
    'access callback' => '_advpoll_clear_votes_access',
    'access arguments' => array(
      1,
    ),
    'weight' => 3,
    'type' => MENU_LOCAL_TASK,
    'file' => 'advpoll.pages.inc',
    'file path' => drupal_get_path('module', 'advpoll') . '/includes',
  );
  
  $menu['node/%node/write-ins'] = array(
    'title' => 'Write-ins',
    'page callback' => 'advpoll_writeins_page',
    'page arguments' => array(
      1,
    ),
    'access callback' => '_advpoll_writeins_access',
    'access arguments' => array(
      1,
    ),
    'weight' => 3,
    'type' => MENU_LOCAL_TASK,
    'file' => 'advpoll.pages.inc',
    'file path' => drupal_get_path('module', 'advpoll') . '/includes',
  );
  
  $menu['node/%node/results'] = array(
    'title' => 'Results',
    'page callback' => 'advpoll_results_page',
    'page arguments' => array(
      1,
    ),
    'access callback' => '_advpoll_results_access',
    'access arguments' => array(
      1,
    ),
    'weight' => 3,
    'type' => MENU_LOCAL_TASK,
    'file' => 'advpoll.pages.inc',
    'file path' => drupal_get_path('module', 'advpoll') . '/includes',
  );
  
  $menu['node/%node/advpoll/votes/clear'] = array(
    'page callback' => 'advpoll_clear_votes_page',
    'page arguments' => array(
      1,
    ),
    'access callback' => '_advpoll_clear_votes_access',
    'access arguments' => array(
      1,
    ),
    'weight' => 3,
    'type' => MENU_LOCAL_TASK,
    'file path' => drupal_get_path('module', 'advpoll') . '/includes',
    'file' => 'advpoll.pages.inc',
  );
  return $menu;
}
function advpoll_permission() {
  return array(
    'vote on polls' => array(
      'title' => t('Vote on polls'),
      'description' => t('User may vote on polls.'),
    ),
    'cancel own vote' => array(
      'title' => t('Cancel own vote'),
      'description' => t('User may cancel their vote in cases where individual user votes are being tracked.'),
    ),
    'administer polls' => array(
      'title' => t('Administer polls'),
      'description' => t('User may use poll administration pages.'),
      'restrict access' => TRUE,
    ),
    'inspect all votes' => array(
      'title' => t('Inspect all votes'),
      'description' => t('User may use votes administration page.'),
      'restrict access' => TRUE,
    ),
    'show vote results' => array(
      'title' => t('Show vote results'),
      'description' => t('User may view poll results in cases where access to results is generally restricted.'),
    ),
    'access electoral list' => array(
      'title' => t('Access electoral list'),
      'description' => t('User may see electoral lists associated with each poll.'),
    ),
    'add write-ins' => array(
      'title' => t('Add write-in votes'),
      'description' => t('User may add write-ins for polls that allow them.'),
      'restrict access' => TRUE,
    ),
  );
}
function advpoll_node_view($node, $view_mode) {
  if ($node->type == 'advpoll') {
    $data = advpoll_get_data($node);
    if ($data->behavior == 'approval' || $data->behavior == 'pool') {
      drupal_add_css(drupal_get_path('module', 'advpoll') . '/css/advpoll.css', array(
        'group' => CSS_DEFAULT,
        'every_page' => TRUE,
      ));
      
      unset($node->content['advpoll_choice']);
      
      if (advpoll_user_eligibility($node)) {
        
        $voteform = drupal_get_form('advpoll_choice_form', $node);
        $node->content['advpoll_choice'] = array(
          0 => $voteform,
          '#weight' => 1,
        );
      }
      else {
        
        $votes = array();
        if ($data->mode == 'normal') {
          $votes = advpoll_get_user_votes($node->nid);
        }
        
        if ($data->state == 'close' && $data->show_results != 'afterclose' || ($data->start_date > time() || $data->end_date < time())) {
          $results = theme('advpoll_closed', array(
            'data' => $data,
          ));
        }
        else {
          if ($data->electoral && $data->show_results != 'aftervote') {
            $results = theme('advpoll_ineligible', array(
              'data' => $data,
            ));
          }
          else {
            $results = advpoll_display_results($node->nid, $data);
          }
        }
        $node->content['advpoll_choice'] = array(
          '#markup' => $results,
          '#weight' => 1,
        );
      }
    }
  }
}
function advpoll_block_info() {
  $blocks['advpoll_recent'] = array(
    'info' => t('Advanced Poll: Most Recent'),
  );
  $blocks = advpoll_get_poll_info_blocks($blocks);
  return $blocks;
}
function advpoll_block_view($delta = '') {
  $block = array();
  switch ($delta) {
    case 'advpoll_recent':
      $block['subject'] = t('Most Recent Poll');
      $block['content'] = array(
        '#markup' => advpoll_get_recent(),
      );
      break;
    default:
      $block = advpoll_generate_block_view($block, $delta);
      break;
  }
  return $block;
}
function advpoll_theme($existing, $type, $theme, $path) {
  return array(
    'advpoll_bar' => array(
      'variables' => array(
        'percentage' => 0,
        'votes' => 0,
        'voted' => 0,
      ),
      'path' => drupal_get_path('module', 'advpoll') . '/templates',
      'template' => 'advpoll-bar',
    ),
    'advpoll_closed' => array(
      'variables' => array(
        'data' => null,
      ),
      'path' => drupal_get_path('module', 'advpoll') . '/templates',
      'template' => 'advpoll-closed',
    ),
    'advpoll_noresults' => array(
      'variables' => array(
        'available_date' => null,
        'votes' => null,
        'nid' => null,
        'cancel_form' => null,
      ),
      'path' => drupal_get_path('module', 'advpoll') . '/templates',
      'template' => 'advpoll-noresults',
    ),
    'advpoll_results' => array(
      'variables' => array(
        'bars' => null,
        'total' => 0,
        'voted' => null,
        'nid' => null,
        'cancel_form' => null,
      ),
      'path' => drupal_get_path('module', 'advpoll') . '/templates',
      'template' => 'advpoll-results',
    ),
    'advpoll_ineligible' => array(
      'variables' => array(
        'data' => null,
      ),
      'path' => drupal_get_path('module', 'advpoll') . '/templates',
      'template' => 'advpoll-ineligible',
    ),
  );
}
function advpoll_node_presave($node) {
  
  if ($node->type === 'advpoll') {
    
    if (isset($node->nid)) {
      $criteria = array();
      $criteria['entity_id'] = $node->nid;
      $criteria['entity_type'] = 'advpoll';
      $results = votingapi_select_votes($criteria);
      if ($results) {
        
        $choices = $node->advpoll_choice[$node->language];
        foreach ($choices as $choice) {
          $ids[] = $choice['choice_id'];
        }
        $noMatch = array();
        foreach ($results as $vote) {
          if (!in_array($vote['tag'], $ids)) {
            $noMatch[] = $vote;
          }
        }
        votingapi_delete_votes($noMatch);
      }
    }
  }
}
function advpoll_node_delete($node) {
  
  db_delete('votingapi_vote')
    ->condition('entity_id', $node->nid)
    ->execute();
}
function advpoll_form_alter(&$form, $form_state, $form_id) {
  
  if ($form_id == 'advpoll_node_form') {
    $lang = $form['language']['#value'];
    $form['advpoll_max_choices'][$lang][0]['value']['#element_validate'][] = 'advpoll_validate_max_choices';
  }
}
function advpoll_validate_max_choices($element, &$form_state, $form) {
  $input_choices = array();
  $lang = $form_state['build_info']['args'][0]->language;
  $choices = $form_state['input']['advpoll_choice'][$lang];
  foreach ($choices as $choice) {
    if ($choice['choice']) {
      $input_choices[] = $choice['choice'];
    }
  }
  $max = (int) $element['#value'];
  if ($max > count($input_choices)) {
    form_error($element, t('The max number of choices is @max.', array(
      '@max' => $max,
    )));
  }
  if (count($input_choices) < 2) {
    form_set_error('advpoll_choice', t('Please enter at least two choices.'));
  }
}
function advpoll_display_results($nid, $data) {
  $output = '';
  $form = null;
  if (user_access('cancel own vote')) {
    $form = drupal_render(drupal_get_form('advpoll_cancel_vote_form', $nid));
  }
  
  $votes = array();
  if ($data->mode == 'normal') {
    $votes = advpoll_get_user_votes($nid);
  }
  if ($data->show_results == 'never' || $data->show_results == 'afterclose' && $data->end_date > time()) {
    $output .= theme('advpoll_noresults', array(
      'data' => $data,
      'votes' => $votes,
      'nid' => $nid,
      'cancel_form' => $form,
    ));
  }
  else {
    $results = advpoll_get_votes($nid, $data->behavior);
    $bars = '';
    $final = advpoll_update_choices($data->choices, $results['choices']);
    foreach ($final as $item) {
      $voted = false;
      if (in_array($item['tag'], $votes)) {
        $voted = true;
      }
      $bars .= theme('advpoll_bar', array(
        'title' => $item['title'],
        'percentage' => $item['percentage'],
        'votes' => $item['votes'],
        'voted' => $voted,
      ));
    }
    $output .= theme('advpoll_results', array(
      'bars' => $bars,
      'total' => $results['total'],
      'voted' => $votes,
      'nid' => $nid,
      'cancel_form' => $form,
    ));
  }
  return $output;
}
function advpoll_update_choices($choices, $results) {
  $choiceSet = array();
  foreach ($choices as $choice) {
    $choiceSet[$choice['choice_id']] = $choice['choice'];
  }
  $final = array();
  foreach ($results as $result) {
    $final[] = array(
      'title' => $choiceSet[$result['index']],
      'percentage' => $result['percentage'],
      'votes' => $result['votes'],
      'tag' => $result['index'],
    );
    
    unset($choiceSet[$result['index']]);
  }
  
  if (count($choiceSet) > 0) {
    foreach ($choiceSet as $key => $choice) {
      $final[] = array(
        'title' => $choice,
        'percentage' => 0,
        'votes' => 0,
        'tag' => $key,
      );
    }
  }
  return $final;
}
function advpoll_choice_form($form, &$form_state, $values) {
  $data = advpoll_get_data($values);
  $count = count($data->choices);
  $options = array();
  $form['#id'] = 'advpoll-form-' . $values->nid;
  for ($i = 0; $i < $count; $i++) {
    if (!$data->choices[$i]['write_in']) {
      $options[] = strip_tags($data->choices[$i]['choice']);
    }
  }
  $options = drupal_map_assoc($options);
  $input_type = 'radios';
  if ($data->max_choices > 1) {
    $input_type = 'checkboxes';
  }
  if ($data->write_in && $data->mode != 'unlimited') {
    $options['write-in'] = t('(Write-in)');
    $form['choice_' + $count] = array(
      '#type' => $input_type,
      '#title' => '',
      '#options' => $options,
      '#ajax' => array(
        'callback' => 'advpoll_writein_callback',
        'wrapper' => 'advpoll-form-' . $values->nid,
        'effect' => 'fade',
      ),
    );
    if (isset($form_state['values'])) {
      foreach ($form_state['values'] as $key => $item) {
        if (is_numeric($key)) {
          break;
        }
      }
      $selected = false;
      if ($input_type == 'radios') {
        if ($item === 'write-in') {
          $selected = true;
        }
      }
      else {
        if ($item['write-in']) {
          $selected = true;
        }
      }
      if ($selected) {
        $form['write_in'] = array(
          '#type' => 'textfield',
          '#element_validate' => array(
            'advpoll_writein_validate',
          ),
          '#prefix' => '<div class="advpoll-write-in">',
          '#suffix' => '</div>',
          '#size' => '30',
        );
      }
    }
  }
  else {
    $form['choice_' + $count] = array(
      '#type' => $input_type,
      '#title' => '',
      '#options' => drupal_map_assoc($options),
    );
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#ajax' => array(
      'callback' => 'advpoll_form_submit',
      'wrapper' => 'advpoll-form-' . $values->nid,
      'name' => 'submit1',
    ),
    '#value' => t('Vote'),
  );
  return $form;
}
function advpoll_writein_validate($element, &$form_state, $form) {
  if (empty($element['#value'])) {
    form_error($element, t('Please type in your write-in choice or select a different option.'));
  }
}
function advpoll_writein_callback($form, $form_state) {
  return $form;
}
function advpoll_form_submit($form, &$form_state) {
  $data = advpoll_get_form_data($form_state);
  $count = count($data->choices);
  $votes = $form[$count]['#value'];
  $nid = $form_state['build_info']['args'][0]->nid;
  $writein = '';
  $message = advpoll_form_submit_check($data, $nid);
  if ($message) {
    $form['message'] = array(
      '#type' => 'markup',
      '#prefix' => '<div id="message">',
      '#suffix' => '</div>',
      '#markup' => $message,
    );
    return $form;
  }
  
  if ($data->write_in) {
    if (isset($form_state['values']['write_in'])) {
      $writein = trim($form_state['values']['write_in']);
      
      $writein = filter_xss($writein);
      $writein = check_plain($writein);
      if ($writein) {
        $data->choices[] = advpoll_process_writein($nid, $writein, $data);
      }
      else {
        $form['message'] = array(
          '#type' => 'markup',
          '#prefix' => '<div id="message">',
          '#suffix' => '</div>',
          '#markup' => t('Please type in a valid write-in choice or select a different option.'),
        );
        return $form;
      }
    }
  }
  
  if ($data->max_choices > 1) {
    if ($writein) {
      unset($votes['write-in']);
      $votes[$writein] = $writein;
    }
    $selected = advpoll_checkbox_selected($data->choices, $votes);
  }
  else {
    if ($writein) {
      $votes = $writein;
    }
    $selected = advpoll_radio_selected($data->choices, $votes);
  }
  if (count($selected) > 0 && count($selected) <= $data->max_choices) {
    foreach ($selected as $item) {
      $vote = array();
      $vote['type'] = 'advpoll';
      $vote['tag'] = $item;
      $vote['nid'] = $nid;
      $vote['value'] = 1;
      $vote['mode'] = $data->mode;
      $vote['duration'] = $data->cookie_duration;
      advpoll_add_votes($vote);
    }
    $element['#markup'] = advpoll_display_results($nid, $data);
    return $element;
  }
  else {
    $form['message'] = array(
      '#type' => 'markup',
      '#prefix' => '<div id="message">',
      '#suffix' => '</div>',
      '#markup' => t('Select up to @quantity @votes.', array(
        '@quantity' => $data->max_choices,
        '@votes' => format_plural($data->max_choices, 'vote', 'votes'),
      )),
    );
    return $form;
  }
}
function advpoll_form_submit_check($data, $nid) {
  if ($data->mode === 'cookie' && isset($_COOKIE['advpoll' . $nid])) {
    return t('You have already voted on this poll.');
  }
  if ($data->mode === 'normal') {
    global $user;
    $criteria = array();
    $criteria['entity_id'] = $nid;
    $criteria['entity_type'] = 'advpoll';
    $criteria['uid'] = $user->uid;
    $results = votingapi_select_votes($criteria);
    if ($results) {
      return t('You have already voted on this poll.');
    }
  }
  return;
}
function advpoll_cancel_vote_form($form, &$form_state, $nid) {
  $form['#nid'] = $nid;
  $form['submit'] = array(
    '#type' => 'submit',
    '#ajax' => array(
      'callback' => 'advpoll_cancel_vote_submit',
      'wrapper' => 'advpoll-' . $nid,
      'name' => 'submit1',
    ),
    '#value' => t('Cancel your vote'),
  );
  return $form;
}
function advpoll_cancel_vote_submit($form, &$form_state) {
  global $user;
  if ($user) {
    $nid = $form['#nid'];
    $criteria = array();
    $criteria['entity_id'] = $nid;
    $criteria['entity_type'] = 'advpoll';
    $criteria['uid'] = $user->uid;
    votingapi_delete_votes(votingapi_select_votes($criteria));
    $node = node_load($nid);
    if (advpoll_user_eligibility($node)) {
      
      return drupal_get_form('advpoll_choice_form', $node);
    }
  }
}
function advpoll_process_writein($nid, $writein, $data) {
  $node = node_load($nid);
  $id = dechex(time() * rand(5, 50));
  $writein_choice = array();
  if ($node) {
    $nodeChoices = $node->advpoll_choice[$node->language];
    $writein_choice = array(
      'choice' => $writein,
      'write_in' => 1,
      'choice_id' => $id,
    );
    $nodeChoices[] = $writein_choice;
    $node->advpoll_choice[$node->language] = $nodeChoices;
    node_save($node);
  }
  return $writein_choice;
}
function advpoll_get_recent() {
  $node = null;
  $result = db_query("SELECT n.nid FROM {node} n\n                      LEFT JOIN {field_data_advpoll_dates} d \n                      ON d.entity_id = n.nid \n                      LEFT JOIN {field_data_advpoll_closed} c\n                      ON c.entity_id = n.nid\n                      LEFT JOIN {field_data_advpoll_options} o\n                      ON o.entity_id = n.nid\n                      WHERE \n                      n.type LIKE '%advpoll%' AND\n                      o.advpoll_options_value <> 'electoral' AND\n                      n.status = 1 AND\n                      c.advpoll_closed_value = 'open' AND\n                      d.advpoll_dates_value < NOW() AND \n                      d.advpoll_dates_value2 > NOW() \n                      GROUP BY n.nid ORDER BY n.created DESC \n                      LIMIT 1");
  if ($result) {
    foreach ($result as $record) {
      $node = node_load($record->nid);
      break;
    }
    return drupal_render(node_view($node));
  }
}
function advpoll_get_poll_info_blocks($blocks) {
  $result = db_query("SELECT n.title, n.nid FROM node n\n                      LEFT JOIN field_data_advpoll_dates d \n                      ON d.entity_id = n.nid \n                      LEFT JOIN field_data_advpoll_closed c\n                      ON c.entity_id = n.nid\n                      LEFT JOIN field_data_advpoll_options o\n                      ON o.entity_id = n.nid\n                      WHERE \n                      n.type LIKE '%advpoll%' AND\n                      o.advpoll_options_value <> 'electoral' AND\n                      o.advpoll_options_value = 'block' AND\n                      n.status = 1 AND\n                      c.advpoll_closed_value = 'open' AND\n                      d.advpoll_dates_value < NOW() AND d.advpoll_dates_value2 > NOW() \n                      GROUP BY n.nid \n                      ORDER BY n.created DESC");
  if ($result) {
    foreach ($result as $record) {
      $blocks['advpoll_block_' . $record->nid] = array(
        'info' => t('Advanced Poll: @title', array(
          '@title' => $record->title,
        )),
      );
    }
  }
  return $blocks;
}
function advpoll_generate_block_view($block, $delta) {
  $parts = explode('_', $delta);
  $nid = $parts[count($parts) - 1];
  $isBlock = false;
  $node = node_load($nid);
  $options = $node->advpoll_options[$node->language];
  
  foreach ($options as $option) {
    if ($option['value'] == 'block') {
      $isBlock = true;
    }
  }
  if ($isBlock) {
    $block['subject'] = t('Poll');
    $block['content'] = array(
      '#markup' => drupal_render(node_view($node)),
    );
  }
  return $block;
}
function _advpoll_results_access($node) {
  if ($node->type == 'advpoll') {
    $data = advpoll_get_data($node);
    $votes = advpoll_get_votes($node->nid);
    return $data->show_results && $votes['total'] > 0 && (user_access("show vote results") || user_access('administer polls'));
  }
}
function _advpoll_electoral_list_access($node) {
  if ($node->type == 'advpoll') {
    $data = advpoll_get_data($node);
    return (user_access('access electoral list') || user_access('administer polls')) && $data->electoral;
  }
}
function _advpoll_votes_access($node) {
  if ($node->type == 'advpoll') {
    $data = advpoll_get_data($node);
    $votes = advpoll_get_votes($node->nid);
    return $votes['total'] > 0 && (user_access('inspect all votes') && $data->show_votes || user_access('administer polls'));
  }
}
function _advpoll_clear_votes_access($node) {
  if ($node->type == 'advpoll') {
    $votes = advpoll_get_votes($node->nid);
    return $votes['total'] > 0 && user_access('administer polls');
  }
}
function _advpoll_writeins_access($node) {
  if ($node->type == 'advpoll') {
    $data = advpoll_get_data($node);
    return user_access('administer polls') && $data->write_in;
  }
}