Advertisement
btmash

Untitled

Sep 5th, 2011
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 19.49 KB | None | 0 0
  1. <?php
  2. // $Id$
  3.  
  4. define('CONTEST_PENDING_PHASE', 0);
  5. define('CONTEST_VOTING_PHASE', 1);
  6. define('CONTEST_BLACKOUT_PHASE', 2);
  7. define('CONTEST_CLOSED_PHASE', 3);
  8.  
  9. /**
  10.  * Implementation of hook_access
  11.  */
  12. function contest_access($op, $node, $account) {
  13.   if ($op == 'create' || $op == 'update' || $op == 'delete') {
  14.     return user_access('manage contests');
  15.   }
  16.   else if ($op == 'view') {
  17.     if ($node->contest_phase == CONTEST_PENDING_PHASE) {
  18.       return user_access('manage contests');
  19.     }
  20.   }
  21. }
  22.  
  23. /**
  24.  * Implementation of hook_help
  25.  */
  26. function contest_help($path, $arg) {
  27.   switch ($path) {
  28.     case 'admin/help#contest':
  29.       return '<p>'. t('The contest module allows a contest creator to add multiple nodes to a contest which will then be placed into a round robin contest of 1 on 1.  Each time the user reloads the page, another tuple will appear for them to choose from. So if you have a lot of nodes to \'fight\' against each other, then more fun for the user!') .'</p>';
  30.   }
  31. }
  32.  
  33. /**
  34.  * Implementation of hook_perm
  35.  */
  36. function contest_perm() {
  37.   return array('administer contests', 'manage contests', 'vote in contest');
  38. }
  39.  
  40. /**
  41.  * Implementation of hook_menu
  42.  */
  43. function contest_menu() {
  44.   $items = array();
  45.   $items['contest/%node/change_phase/voting'] = array(
  46.     'title' => 'Change to voting phase',
  47.     'page callback' => 'contest_set_voting_phase',
  48.     'page arguments' => array(1),
  49.     'access callback' => 'user_access',
  50.     'access arguments' => array('manage contests'),
  51.     'type' => MENU_CALLBACK,
  52.   );
  53.   $items['contest/%node/change_phase/blackout'] = array(
  54.     'title' => 'Change to voting phase',
  55.     'page callback' => 'contest_set_blackout_phase',
  56.     'page arguments' => array(1),
  57.     'access callback' => 'user_access',
  58.     'access arguments' => array('manage contests'),
  59.     'type' => MENU_CALLBACK,
  60.   );
  61.   $items['contest/%node/change_phase/closed'] = array(
  62.     'title' => 'Change to voting phase',
  63.     'page callback' => 'contest_set_closed_phase',
  64.     'page arguments' => array(1),
  65.     'access callback' => 'user_access',
  66.     'access arguments' => array('manage contests'),
  67.     'type' => MENU_CALLBACK,
  68.   );
  69.   $items['contest/js/vote'] = array(
  70.     'page callback' => 'contest_js_vote',
  71.     'access arguments' => array('vote in contest'),
  72.     'type' => MENU_CALLBACK,
  73.   );
  74.   return $items;
  75. }
  76.  
  77. /**
  78.  * Implementation of hook_node_info
  79.  */
  80. function contest_node_info() {
  81.   return array(
  82.     'contest' => array(
  83.       'name' => t('Contest'),
  84.       'module' => 'contest',
  85.       'description' => t('Creates a contest consisting of N nodes which then participate in a round-robin contest'),
  86.       'has_title' => TRUE,
  87.       'title_label' => t('Contest Title'),
  88.       'has_body' => TRUE,
  89.       'body_label' => t('Contest details'),
  90.       'locked' => TRUE,
  91.     )
  92.   );
  93. }
  94.  
  95. /**
  96.  * Return types of allowed contests
  97.  */
  98. function contest_types() {
  99.   static $contest_types;
  100.   if (!isset($contest_types)) {
  101.     $contest_types = array(
  102.       'nodes' => t('Nodes'),
  103.       'users' => t('Users'),
  104.     );
  105.   }
  106.   return $contest_types;
  107. }
  108.  
  109. /**
  110.  * Implementation of hook_form
  111.  */
  112. function contest_form(&$node, &$param) {
  113.   $type = node_get_types('type', $node);
  114.  
  115.   $form = array();
  116.   $form['title'] = array(
  117.     '#type' => 'textfield',
  118.     '#title' => check_plain($type->title_label),
  119.     '#default_value' => $node->title,
  120.     '#required' => TRUE,
  121.   );
  122.   $form['body'] = array(
  123.     '#type' => 'textarea',
  124.     '#title' => check_plain($type->body_label),
  125.     '#default_value' => $node->body,
  126.     '#rows' => 10,
  127.     '#required' => TRUE,
  128.   );
  129.   if (module_exists('filter')) {
  130.     $node->format = isset($node->format) ? $node->format : FILTER_FORMAT_DEFAULT;
  131.     $form['format'] = filter_form($node->format);
  132.   }
  133.   $form['contest_type'] = array(
  134.     '#type' => 'radios',
  135.     '#title' => t('Type of contest'),
  136.     '#default_value' => $node->contest_type,
  137.     '#options' => contest_types(),
  138.     '#required' => TRUE,
  139.   );
  140.   $form['contestants'] = array(
  141.     '#type' => 'textarea',
  142.     '#title' => t('Nodes for contest'),
  143.     '#description' => t('The nodes that are participating in this competition (type one ID per line)'),
  144.     '#default_value' => implode("\n", $node->contestants),
  145.     '#rows' => 15,
  146.     '#required' => TRUE,
  147.   );
  148.   $form['contenders_per_vote'] = array(
  149.     '#type' => 'textfield',
  150.     '#title' => t('Contenders per showdown'),
  151.     '#description' => t('The number of contenders that the user must choose between per vote-off (between 2 and 99)'),
  152.     '#default_value' => ($node->contenders_per_vote) ? $node->contenders_per_vote : 2,
  153.     '#size' => 2,
  154.     '#maxlength' => 2,
  155.     '#required' => TRUE,
  156.   );
  157.  
  158.   $form['contest_phase'] = array(
  159.     '#type' => 'radios',
  160.     '#title' => t('Select the phase of the contest'),
  161.     '#description' => t("Pending means the contest is not yet ready for users to vote for, voting means users can vote and see the current results, blackout means the users can vote but not see the results while closed means the users will only see the results of the contest."),
  162.     '#options' => _contest_get_phases(),
  163.     '#default_value' => isset($node->contest_phase) ? $node->contest_phase : CONTEST_PENDING_PHASE,
  164.     '#required' => TRUE,
  165.   );
  166.  
  167.   return $form;
  168. }
  169.  
  170. /**
  171.  * Implementation of hook_validate
  172.  *
  173.  * At time to contest create/edit, make sure the expressed nodes are valid
  174.  */
  175. function contest_validate($node) {
  176.   // Validate the number of contestants
  177.   $size = 2;
  178.   if (!preg_match('/^[1-9][0-9]*$/', $node->contenders_per_vote) || $node->contenders_per_vote < 2) {
  179.     form_set_error('contenders_per_vote', t('Invalid number of contenders per vote.  Please select a value between 2 and 99'));
  180.   }
  181.   else {
  182.     $size = $node->contenders_per_vote;
  183.   }
  184.  
  185.   // Validate that the contestants are published for users to view
  186.   $contestants = explode("\n", preg_replace('/\r\n|\r/', "\n", trim($node->contestants)));
  187.   $contestants = array_unique($contestants);
  188.   if (sizeof($contestants) < $size) {
  189.     form_set_error('contestants', t('Need more contestants'));
  190.     return;
  191.   }
  192.   $check = TRUE;
  193.   foreach ($contestants as $contestant) {
  194.     if (!preg_match('/^[1-9][0-9]*$/', $contestant)) {
  195.       form_set_error('contestants', t('Invalid format of contestant ID specified: @contestant', array('@contestant' => $contestant)));
  196.       $check = FALSE;
  197.     }
  198.     else {
  199.       if ('users' === $node->contest_type) {
  200.         $result = db_result(db_query("SELECT uid FROM {users} WHERE uid=%d AND status = 1", $contestant));
  201.       }
  202.       else {
  203.         $result = db_result(db_query("SELECT nid FROM {node} WHERE nid=%d AND status = 1", $contestant));
  204.       }
  205.       if ($result != $contestant) {
  206.         form_set_error('contestants', t('Contestant is not published: @contestant', array('@contestant' => $contestant)));
  207.         $check = FALSE;
  208.       }
  209.     }
  210.   }
  211.   if ($check === FALSE) {
  212.     return;
  213.   }
  214.  
  215.   // Validate the current status of the contest
  216.   if ($node->contest_phase < CONTEST_PENDING_PHASE || $node->contest_phase > CONTEST_CLOSED_PHASE) {
  217.     form_set_error('contest_phase', t('Invalid contest phase.  Choose correctly from the list.'));
  218.   }
  219. }
  220.  
  221. /**
  222.  * Implementation of hook_insert
  223.  */
  224. function contest_insert($node) {
  225.   $contestants = explode("\n", preg_replace('/\r\n|\r/', "\n", trim($node->contestants)));
  226.   $contestants = serialize(array_unique($contestants));
  227.   db_query("INSERT INTO {contest} (nid, contest_type, contestants, contenders_per_vote, contest_phase) VALUES (%d, '%s', '%s', %d, %d)",
  228.     $node->nid, $node->contest_type, $contestants, $node->contenders_per_vote, $node->contest_phase);
  229. }
  230.  
  231. /**
  232.  * Implementation of hook_update
  233.  */
  234. function contest_update($node) {
  235.   cache_clear_all("contest-$node->nid-contestants", 'cache');
  236.   $contestants = explode("\n", preg_replace('/\r\n|\r/', "\n", trim($node->contestants)));
  237.   $contestants = serialize(array_unique($contestants));
  238.   db_query("UPDATE {contest} SET contest_type='%s', contestants='%s', contenders_per_vote=%d, contest_phase=%d WHERE nid=%d",
  239.     $node->contest_type, $contestants, $node->contenders_per_vote, $node->contest_phase, $node->nid);
  240. }
  241.  
  242. /**
  243.  * Implementation of hook_load
  244.  */
  245. function contest_load($node) {
  246.   $additions = db_fetch_object(db_query("SELECT * FROM {contest} WHERE nid=%d", $node->nid));
  247.   $additions->contestants = unserialize($additions->contestants);
  248.   $additions->contestant_objects = cache_get("contest-$node->nid-contestants");
  249.   if (empty($additions->contestant_objects)) {
  250.     $additions->contestant_objects = array();
  251.     foreach ($additions->contestants as $contestant) {
  252.       $additions->contestant_objects["contestant-$contestant"] = _contest_load_object($contestant, $node->contest_type);
  253.     }
  254.     cache_set("contest-$node->nid-contestants", $additions->contestant_objects);
  255.   }
  256.   else {
  257.     $additions->contestant_objects = $additions->contestant_objects->data;
  258.   }
  259.   $additions->contest_phase = intval($additions->contest_phase);
  260.   return $additions;
  261. }
  262.  
  263. /*
  264. function contest_link($type, $object, $teaser) {
  265.   $links = array();
  266.   if ($type === 'node' && !$teaser) {
  267.     if ($object->type === 'contest' && user_access('manage contests')) {
  268.       if ($object->contest_phase === CONTEST_PENDING_PHASE) {
  269.         $links['contest_'. $object->nid .'_voting'] = array(
  270.           'title' => t('Change to voting phase'),
  271.           'href' => "contest/$object->nid/change_phase/voting",
  272.           'attributes' => array('title' => t('Allow users to vote on this contest')),
  273.         );
  274.       }
  275.       if ($object->contest_phase === CONTEST_VOTING_PHASE) {
  276.         $links['contest_'. $object->nid .'_blackout'] = array(
  277.           'title' => t('Change to blackout phase'),
  278.           'href' => "contest/$object->nid/change_phase/blackout",
  279.           'attributes' => array('title' => t('Allow users to vote on this contest but do not show the results')),
  280.         );
  281.       }
  282.       if ($object->contest_phase === CONTEST_BLACKOUT_PHASE) {
  283.         $links['contest_'. $object->nid .'_voting'] = array(
  284.           'title' => t('Change to closed phase'),
  285.           'href' => "contest/$object->nid/change_phase/closed",
  286.           'attributes' => array('title' => t('Stop voting and allow users to see the results!')),
  287.         );
  288.       }
  289.     }
  290.   }
  291.   return $links;
  292. }
  293. */
  294.  
  295. /**
  296.  * Implementation of hook_view
  297.  */
  298. function contest_view($node, $teaser = FALSE, $page = FALSE, $links = FALSE) {
  299.   node_prepare($node);
  300.   unset($node->content['body']);
  301.   $content = '';
  302.   if ($node->contest_phase === CONTEST_VOTING_PHASE || $node->contest_phase === CONTEST_BLACKOUT_PHASE) {
  303.     $content .= theme('contest_entry_list', _contest_get_contender_forms($node));
  304.   }
  305.   $content .= theme('contest_details', $node->body);
  306.   if ($node->contest_phase === CONTEST_VOTING_PHASE ||
  307.       $node->contest_phase === CONTEST_CLOSED_PHASE ||
  308.       user_access('administer contests') ||
  309.       user_access('manage contests')) {
  310.     $content .= theme('contest_results', contest_get_results($node));
  311.   }
  312.   if ($page) {
  313.     $node->content['contest'] = array(
  314.       '#value' => '<div id="contest-container">'. $content .'</div>'
  315.     );
  316.   }
  317.   else {
  318.     $node->content['contest'] = array(
  319.       '#value' => $content
  320.     );
  321.   }
  322.   return $node;
  323. }
  324.  
  325. function contest_get_results($node) {
  326.   $results = cache_get("contest-$node->nid-results");
  327.   if ($node->contest_phase !== CONTEST_CLOSED_PHASE || empty($results)) {
  328.     $contestants = $node->contestants;
  329.     $results = array();
  330.     foreach ($contestants as $contestant) {
  331.       $criteria = array(
  332.         'content_id' => $contestant,
  333.         'content_type' => 'contest-'. $node->nid,
  334.         'function' => 'count',
  335.       );
  336.       $results["contestant-$contestant"] = votingapi_select_results($criteria);
  337.       $results["contestant-$contestant"] = (empty($results["contestant-$contestant"])) ? 0 : intval($results["contestant-$contestant"][0]['value']);
  338.     }
  339.     arsort($results, SORT_NUMERIC);
  340.     if ($node->contest_phase === CONTEST_CLOSED_PHASE) {
  341.       contest_set_results($node, $results);
  342.     }
  343.   }
  344.   return $results;
  345. }
  346.  
  347. function contest_forms() {
  348.   $args = func_get_args();
  349.   $form_id = $args[0];
  350.  
  351.   $forms = array();
  352.   if (strpos($form_id, "contest_evaluate_form") === 0) {
  353.     $forms[$form_id] = array('callback' => 'contest_evaluate_form');
  354.   }
  355.   return $forms;
  356. }
  357.  
  358. function contest_set_results($node, $results) {
  359.   cache_set("contest-$node->nid-results", $results);
  360. }
  361.  
  362. /**
  363.  * Return a contest evaluation form with the number of specified nodes
  364.  */
  365. function contest_evaluate_form($form_state, $node, $cid) {
  366.   global $theme_key;
  367.   $form = array('#cache' => TRUE);
  368.   $form['#attributes']['class'] = 'contestant-form';
  369.   $form['#validate'][] = 'contest_evaluate_form_validate';
  370.   $form['#submit'][] = 'contest_evaluate_form_submit';
  371.  
  372.   $form['nid'] = array(
  373.     '#type' => 'value',
  374.     '#value' => $node->nid,
  375.   );
  376.   $form['cid'] = array(
  377.     '#type' => 'value',
  378.     '#value' => $cid,
  379.   );
  380.  
  381.   if ($node->contest_type === 'users') {
  382.     $theme = 'contest_user_view';
  383.   }
  384.   else {
  385.     $theme = 'contest_node_view';
  386.   }
  387.    
  388.   $form['op'] = array(
  389.     '#prefix' => theme($theme, $node->contestant_objects["contestant-$cid"]),
  390.     '#type' => 'submit',
  391. //    '#type' => 'image_button',
  392. //    '#src' => drupal_get_path('theme', $theme_key).'/images/contest-vote-button.gif',
  393.     '#value' => t('Vote'),
  394.     '#ahah' => array(
  395.       'path' => 'contest/js/vote',
  396.       'wrapper' => 'contest-container',
  397.       'method' => 'replace',
  398.       'effect' => 'fade'
  399.     ),
  400.   );
  401.   return $form;
  402. }
  403.  
  404. function contest_evaluate_form_submit($form, &$form_state) {
  405.   global $user;
  406.   $values = $form_state['values'];
  407.   $op = $form_state['clicked_button']['#value'];
  408.   if (t('Vote') === $op) {
  409.     // Perform the voting
  410.     $vote_id = $values['cid'];
  411.     $nid = $values['nid'];
  412.     $vote = array();
  413.     $vote['content_type'] = "contest-$nid";
  414.     $vote['content_id'] = $vote_id;
  415.     $vote['value_type'] = 'points';
  416.     $vote['value'] = 1;
  417.     $criteria = array();
  418.     votingapi_set_votes($vote, $criteria);
  419.     if ($values['ahah'] !== TRUE) {
  420.       drupal_set_message(t('Thank you for voting!'));
  421.     }
  422.   }
  423. }
  424.  
  425. function contest_js_vote() {
  426.   // Submit the form here
  427.   $form_build_id = 'form_'. $_POST['form_build_id'];
  428.   $cache = cache_get($form_build_id, 'cache_form');
  429.   $form = $cache->data;
  430.   $form_state = array('values' => $_POST);  
  431.   $form_state['values']['nid'] = $form['nid']['#value'];
  432.   $form_state['values']['cid'] = $form['cid']['#value'];
  433.   $form_state['values']['ahah'] = TRUE;
  434.   $form_state['clicked_button']['#value'] = $form_state['values']['op'];
  435.   contest_evaluate_form_submit($form, $form_state);
  436.  
  437.   // Rebuild a new form with new contestants
  438.   $_POST = array();
  439.   $node = $form['#parameters'][2];
  440.   drupal_set_message(t('Thank you for voting!'));
  441.   $content = theme('status_messages');
  442.   $content .= node_view($node, TRUE, FALSE, FALSE);
  443.   print drupal_to_js(array('status' => FALSE, 'data' => $content));
  444.   cache_clear_all($form_build_id, 'cache_form');
  445. }
  446.  
  447. function _contest_get_contender_forms($node) {
  448.   $contenders = _contest_get_contenders($node);
  449.   $forms = array();
  450.   $id = 1;
  451.   foreach ($contenders as $contender) {
  452.     $forms[] = drupal_get_form("contest_evaluate_form-$id", $node, $contender);
  453.     $id++;
  454.   }
  455.   return $forms;
  456. }
  457.  
  458. function _contest_get_contenders($node) {
  459.   $contestants = $node->contestants;
  460.   $limit = $node->contenders_per_vote;
  461.   $contenders = array();
  462.  
  463.   // Perform a seed to be on the safe side
  464.   srand((float) microtime() * 10000000);
  465.   $random_contestants = array_rand($contestants, $limit);
  466.   foreach ($random_contestants as $value) {
  467.     $contenders["contestant-$value"] = $contestants[$value];
  468.   }
  469.   $contenders_temp = $contenders;
  470.  
  471.   foreach ($contenders_temp as $key => $value) {
  472.     $contenders[$key] = $value; // DO SOME THEMING STUFF SO IT WORKS BETTER FOR YOU THIS WAY!!!
  473.   }
  474.   return $contenders;
  475. }
  476.  
  477. function _contest_load_object($oid, $type) {
  478.   if ($type === 'user') {
  479.     return user_load(array('uid' => $oid));
  480.   }
  481.   else {
  482.     return node_load($oid);
  483.   }
  484. }
  485.  
  486. function _contest_get_phases() {
  487.   return array(
  488.     CONTEST_PENDING_PHASE => t('Pending'),
  489.     CONTEST_VOTING_PHASE => t('Voting'),
  490.     CONTEST_BLACKOUT_PHASE => t('Blackout'),
  491.     CONTEST_CLOSED_PHASE => t('Closed'),
  492.   );
  493. }
  494.  
  495. /**
  496.  * Implementation of hook_votingapi_results_alter
  497.  */
  498. function contest_votingapi_results_alter(&$cache, $votes, $content_type, $content_id = NULL) {
  499.   // Remove any extra rows that aren't necessary - we only need the counter in this instance
  500.   if (strpos($content_type, 'contest-') === 0) {
  501.     unset($cache['vote']['points']['sum']);
  502.     unset($cache['vote']['points']['average']);
  503.   }
  504. }
  505.  
  506. function contest_set_voting_phase($node) {
  507.   if (!isset($node->contest_phase)) {
  508.     return drupal_not_found();
  509.   }
  510.   db_query("UPDATE {contest} SET contest_phase = %d WHERE nid = %d", CONTEST_VOTING_PHASE, $node->nid);
  511.   drupal_goto("node/$node->nid");
  512. }
  513.  
  514. function contest_set_blackout_phase($node) {
  515.   if (!isset($node->contest_phase)) {
  516.     return drupal_not_found();
  517.   }
  518.   db_query("UPDATE {contest} SET contest_phase = %d WHERE nid = %d", CONTEST_BLACKOUT_PHASE, $node->nid);
  519.   drupal_goto("node/$node->nid");
  520. }
  521.  
  522. function contest_set_closed_phase($node) {
  523.   if (!isset($node->contest_phase)) {
  524.     return drupal_not_found();
  525.   }
  526.   db_query("UPDATE {contest} SET contest_phase = %d WHERE nid = %d", CONTEST_CLOSED_PHASE, $node->nid);
  527.   $results = contest_get_results($node);
  528.   contest_set_results($node, $results);
  529.   drupal_goto("node/$node->nid");
  530. }
  531.  
  532. /**
  533.  * Implementation of hook_theme
  534.  */
  535. function contest_theme() {
  536.   $themes = array();
  537.   $themes['contest_details'] = array(
  538.     'arguments' => array(
  539.       'details' => '',
  540.     ),
  541.   );
  542.   $themes['contest_entry_list'] = array(
  543.     'arguments' => array(
  544.       'list' => array(),
  545.     ),
  546.   );
  547.   $themes['contest_entry_list_item'] = array(
  548.     'arguments' => array(
  549.       'item' => array(),
  550.       'attributes' => array()
  551.     ),
  552.   );
  553.   $themes['contest_results'] = array(
  554.     'arguments' => array(
  555.       'results' => array(),
  556.     ),
  557.   );
  558.   $themes['contest_node_view'] = array(
  559.     'template' => 'contest_node_view',
  560.     'arguments' => array(
  561.       'node' => NULL
  562.     ),
  563.   );
  564.   $themes['contest_user_view'] = array(
  565.     'template' => 'contest_user_view',
  566.     'arguments' => array(
  567.       'account' => NULL
  568.     ),
  569.   );
  570.   return $themes;
  571. }
  572.  
  573. function theme_contest_details($details = '') {
  574.   $output = '';
  575.   $output .= '<div class="contest-details-container">';
  576.     $output .= $details;
  577.   $output .= '</div>';
  578.   return $output;
  579. }
  580.  
  581. function theme_contest_entry_list($list = array()) {
  582.   $output = '<ul class="contest-entry-list clear-block">';
  583.   foreach ($list as $item) {
  584.     $output .= theme('contest_entry_list_item', $item);
  585.   }
  586.   $output .= '</ul>';
  587.   return $output;
  588. }
  589.  
  590. function theme_contest_entry_list_item($item = null, $attributes = array()) {
  591.   if (!empty($item)) {
  592.     if (!isset($attributes['class'])) {
  593.       $attributes['class'] = '';
  594.     }
  595.     $attributes['class'] .= ' contest-entry';
  596.     $output = '<li '. drupal_attributes($attributes) .'>'. $item .'</li>';
  597.   }
  598.   return $output;
  599. }
  600.  
  601. function theme_contest_results($results = array()) {
  602.   $sum = 0;
  603.   $header = array(t('Node ID'), t('Votes'));
  604.   $rows = array();
  605.   foreach ($results as $nid => $value) {
  606.     $rows[] = array(str_replace('contestant-', '', $nid), $value);
  607.   }
  608.   return theme('table', $header, $rows);
  609. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement