| 1 |
<?php
|
| 2 |
// $Id: bookmaker.module,v 1.70 2008/11/03 10:29:26 toddy Exp $
|
| 3 |
/*
|
| 4 |
* Copyright (C) 2006-2008 Tobias Quathamer <t.quathamer@gmx.net>
|
| 5 |
*
|
| 6 |
* This file is part of Bookmaker.
|
| 7 |
*
|
| 8 |
* Bookmaker is free software; you can redistribute it and/or modify
|
| 9 |
* it under the terms of the GNU General Public License as published by
|
| 10 |
* the Free Software Foundation; either version 2 of the License, or
|
| 11 |
* (at your option) any later version.
|
| 12 |
*
|
| 13 |
* Bookmaker is distributed in the hope that it will be useful,
|
| 14 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 15 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 16 |
* GNU General Public License for more details.
|
| 17 |
*
|
| 18 |
* You should have received a copy of the GNU General Public License
|
| 19 |
* along with Bookmaker; if not, write to the Free Software
|
| 20 |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
| 21 |
*/
|
| 22 |
|
| 23 |
|
| 24 |
|
| 25 |
/**
|
| 26 |
* @file
|
| 27 |
* Enables users to place bets on anything
|
| 28 |
*
|
| 29 |
* Enables your users to place a bet on virtually anything; you decide
|
| 30 |
* which bets you offer. After the outcome of the bet offer is published,
|
| 31 |
* the module automatically calculates the amount of points each user
|
| 32 |
* gets.
|
| 33 |
*
|
| 34 |
* The module is compatible with Drupal 6.x
|
| 35 |
*
|
| 36 |
* @author Tobias Quathamer
|
| 37 |
*/
|
| 38 |
|
| 39 |
|
| 40 |
|
| 41 |
// Include helper tools
|
| 42 |
require_once drupal_get_path('module', 'bookmaker') .'/bookmaker.inc';
|
| 43 |
|
| 44 |
|
| 45 |
|
| 46 |
/*********************************************************************
|
| 47 |
* General Drupal hooks for registering the module
|
| 48 |
********************************************************************/
|
| 49 |
|
| 50 |
|
| 51 |
|
| 52 |
/**
|
| 53 |
* Implementation of hook_node_info().
|
| 54 |
*
|
| 55 |
* This function registers the provided node types. Currently,
|
| 56 |
* this is only "bet_offer".
|
| 57 |
*/
|
| 58 |
function bookmaker_node_info() {
|
| 59 |
return array(
|
| 60 |
'bet_offer' => array(
|
| 61 |
'name' => t('Bet offer'),
|
| 62 |
'module' => 'bookmaker_betoffer',
|
| 63 |
'description' => t('Bet offers enable other users to place a bet on the bet offer. You can specify how long the bet offer is accepting user bets. There is also the possibility of assigning points to correct guesses, which will be summed up for each individual user.')
|
| 64 |
)
|
| 65 |
);
|
| 66 |
}
|
| 67 |
|
| 68 |
|
| 69 |
|
| 70 |
/**
|
| 71 |
* Implementation of hook_menu().
|
| 72 |
*/
|
| 73 |
function bookmaker_menu() {
|
| 74 |
$items['bookmaker'] = array(
|
| 75 |
'title' => 'Bet offers',
|
| 76 |
'description' => 'Show a list of all available bet offers',
|
| 77 |
'page callback' => 'bookmaker_show_betoffers',
|
| 78 |
'access arguments' => array('access content'),
|
| 79 |
);
|
| 80 |
$items['bookmaker/place_bet/%node'] = array(
|
| 81 |
'title' => 'Place a bet',
|
| 82 |
'description' => 'Place your bet on a bet offer',
|
| 83 |
'page callback' => 'bookmaker_userbet_place_bet',
|
| 84 |
'page arguments' => array(2),
|
| 85 |
'access arguments' => array('place a bet'),
|
| 86 |
);
|
| 87 |
return $items;
|
| 88 |
}
|
| 89 |
|
| 90 |
|
| 91 |
|
| 92 |
/**
|
| 93 |
* Implementation of hook_perm().
|
| 94 |
*/
|
| 95 |
function bookmaker_perm() {
|
| 96 |
return array(
|
| 97 |
'create bet offers',
|
| 98 |
'edit own bet offers',
|
| 99 |
'place a bet',
|
| 100 |
);
|
| 101 |
}
|
| 102 |
|
| 103 |
|
| 104 |
|
| 105 |
/**
|
| 106 |
* Implementation of hook_access().
|
| 107 |
*/
|
| 108 |
function bookmaker_betoffer_access($op, $node, $account) {
|
| 109 |
if ($op == 'create') {
|
| 110 |
return user_access('create bet offers', $account);
|
| 111 |
}
|
| 112 |
|
| 113 |
if ($op == 'update' || $op == 'delete') {
|
| 114 |
if (user_access('edit own bet offers', $account) && ($account->uid == $node->uid)) {
|
| 115 |
return TRUE;
|
| 116 |
}
|
| 117 |
}
|
| 118 |
}
|
| 119 |
|
| 120 |
|
| 121 |
|
| 122 |
/*********************************************************************
|
| 123 |
* Drupal hooks for providing blocks
|
| 124 |
********************************************************************/
|
| 125 |
|
| 126 |
|
| 127 |
|
| 128 |
/**
|
| 129 |
* Implementation of hook_block().
|
| 130 |
*/
|
| 131 |
function bookmaker_block($op = 'list', $delta = 0, $edit = array()) {
|
| 132 |
switch ($op) {
|
| 133 |
case 'list':
|
| 134 |
// return a list of block descriptions to the administrator
|
| 135 |
$blocks[0]['info'] = t('Shortly closing bet offers');
|
| 136 |
$blocks[1]['info'] = t('Recently added bet offers');
|
| 137 |
return $blocks;
|
| 138 |
case 'configure':
|
| 139 |
// create a form for configuring the blocks
|
| 140 |
$form = array();
|
| 141 |
if ($delta == 0) {
|
| 142 |
$form['bookmaker_number_of_shortly_closing_bet_offers'] = array(
|
| 143 |
'#type' => 'textfield',
|
| 144 |
'#title' => t('Number of shortly closing bet offers'),
|
| 145 |
'#size' => 4,
|
| 146 |
'#description' => t('This sets the number of shortly closing bet offers that will be shown in the block.'),
|
| 147 |
'#default_value' =>
|
| 148 |
variable_get('bookmaker_number_of_shortly_closing_bet_offers', 5),
|
| 149 |
);
|
| 150 |
}
|
| 151 |
if ($delta == 1) {
|
| 152 |
$form['bookmaker_number_of_recently_added_bet_offers'] = array(
|
| 153 |
'#type' => 'textfield',
|
| 154 |
'#title' => t('Number of recently added bet offers'),
|
| 155 |
'#size' => 4,
|
| 156 |
'#description' => t('This sets the number of recently added bet offers that will be shown in the block.'),
|
| 157 |
'#default_value' =>
|
| 158 |
variable_get('bookmaker_number_of_recently_added_bet_offers', 5),
|
| 159 |
);
|
| 160 |
}
|
| 161 |
return $form;
|
| 162 |
case 'save':
|
| 163 |
// save settings from the configuration form
|
| 164 |
if ($delta == 0) {
|
| 165 |
// ensure that we save a number greater than 0
|
| 166 |
$number = (int) $edit['bookmaker_number_of_shortly_closing_bet_offers'];
|
| 167 |
$number = max(1, $number);
|
| 168 |
variable_set('bookmaker_number_of_shortly_closing_bet_offers', $number);
|
| 169 |
}
|
| 170 |
if ($delta == 1) {
|
| 171 |
// ensure that we save a number greater than 0
|
| 172 |
$number = (int) $edit['bookmaker_number_of_recently_added_bet_offers'];
|
| 173 |
$number = max(1, $number);
|
| 174 |
variable_set('bookmaker_number_of_recently_added_bet_offers', $number);
|
| 175 |
}
|
| 176 |
return;
|
| 177 |
case 'view':
|
| 178 |
default:
|
| 179 |
// prepare the block for display
|
| 180 |
if (user_access('access content')) {
|
| 181 |
switch ($delta) {
|
| 182 |
case 0:
|
| 183 |
default:
|
| 184 |
$block['subject'] = t('Shortly closing bet offers');
|
| 185 |
$block['content'] = _bookmaker_block_content(0);
|
| 186 |
break;
|
| 187 |
case 1:
|
| 188 |
$block['subject'] = t('Recently added bet offers');
|
| 189 |
$block['content'] = _bookmaker_block_content(1);
|
| 190 |
break;
|
| 191 |
}
|
| 192 |
return $block;
|
| 193 |
}
|
| 194 |
}
|
| 195 |
}
|
| 196 |
|
| 197 |
|
| 198 |
|
| 199 |
/**
|
| 200 |
* Returns different block contents
|
| 201 |
*/
|
| 202 |
function _bookmaker_block_content($delta = 0) {
|
| 203 |
switch ($delta) {
|
| 204 |
case 0:
|
| 205 |
default:
|
| 206 |
$sql = "SELECT n.nid, n.title, bm.closes_on FROM {node} AS n\n";
|
| 207 |
$sql .= "LEFT JOIN {bookmaker} AS bm ON n.vid=bm.vid\n";
|
| 208 |
$sql .= "WHERE n.type='bet_offer' AND n.status=1 AND bm.closes_on>UNIX_TIMESTAMP()\n";
|
| 209 |
$sql .= "ORDER BY bm.closes_on ASC, n.title ASC";
|
| 210 |
$limit = variable_get('bookmaker_number_of_shortly_closing_bet_offers', 5);
|
| 211 |
break;
|
| 212 |
case 1:
|
| 213 |
$sql = "SELECT n.nid, n.title, bm.closes_on FROM {node} AS n\n";
|
| 214 |
$sql .= "LEFT JOIN {bookmaker} AS bm ON n.vid=bm.vid\n";
|
| 215 |
$sql .= "WHERE n.type='bet_offer' AND n.status=1 AND bm.closes_on>UNIX_TIMESTAMP()\n";
|
| 216 |
$sql .= "ORDER BY n.created DESC, n.title ASC";
|
| 217 |
$limit = variable_get('bookmaker_number_of_recently_added_bet_offers', 5);
|
| 218 |
break;
|
| 219 |
}
|
| 220 |
|
| 221 |
$result = db_query_range(db_rewrite_sql($sql), 0, $limit);
|
| 222 |
|
| 223 |
$output = '<ul>';
|
| 224 |
while ($node = db_fetch_object($result)) {
|
| 225 |
$output .= '<li>'. l($node->title, "node/$node->nid") .'<br />';
|
| 226 |
$output .= t('@time left',
|
| 227 |
array('@time' => format_interval($node->closes_on - gmmktime()))) .'</li>';
|
| 228 |
}
|
| 229 |
$output .= '</ul>';
|
| 230 |
return $output;
|
| 231 |
}
|
| 232 |
|
| 233 |
|
| 234 |
|
| 235 |
/*********************************************************************
|
| 236 |
* Drupal hooks for the extension of an own node type
|
| 237 |
********************************************************************/
|
| 238 |
|
| 239 |
|
| 240 |
|
| 241 |
/**
|
| 242 |
* Implementation of hook_form().
|
| 243 |
*/
|
| 244 |
function bookmaker_betoffer_form(&$node) {
|
| 245 |
// The site admin can decide if this node type has a title and body, and how
|
| 246 |
// the fields should be labeled. We need to load these settings so we can
|
| 247 |
// build the node form correctly.
|
| 248 |
$type = node_get_types('type', $node);
|
| 249 |
|
| 250 |
if ($type->has_title) {
|
| 251 |
$form['title'] = array(
|
| 252 |
'#type' => 'textfield',
|
| 253 |
'#title' => check_plain($type->title_label),
|
| 254 |
'#required' => TRUE,
|
| 255 |
'#default_value' => $node->title,
|
| 256 |
'#weight' => -5
|
| 257 |
);
|
| 258 |
}
|
| 259 |
|
| 260 |
if ($type->has_body) {
|
| 261 |
// In Drupal 6, we can use node_body_field() to get the body and filter
|
| 262 |
// elements. This replaces the old textarea + filter_form() method of
|
| 263 |
// setting this up. It will also ensure the teaser splitter gets set up
|
| 264 |
// properly.
|
| 265 |
$form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count);
|
| 266 |
}
|
| 267 |
|
| 268 |
// Now we define the form elements specific to a bet offer
|
| 269 |
if (isset($node->closes_on)) {
|
| 270 |
$default_value = format_date($node->closes_on, 'custom', 'Y-m-d H:i:s O');
|
| 271 |
}
|
| 272 |
else {
|
| 273 |
$default_value = '';
|
| 274 |
}
|
| 275 |
$form['closes_on'] = array(
|
| 276 |
'#type' => 'textfield',
|
| 277 |
'#title' => t('Closes on'),
|
| 278 |
'#description' => t('Format: @timeformat.',
|
| 279 |
array('@timeformat' => date('Y-m-d H:i:s O'))),
|
| 280 |
'#default_value' => $default_value,
|
| 281 |
'#required' => TRUE
|
| 282 |
);
|
| 283 |
$form['outcome'] = array(
|
| 284 |
'#type' => 'textfield',
|
| 285 |
'#title' => t('Outcome'),
|
| 286 |
'#default_value' => $node->outcome
|
| 287 |
);
|
| 288 |
$form['points'] = array(
|
| 289 |
'#type' => 'fieldset',
|
| 290 |
'#title' => t('Points'),
|
| 291 |
'#collapsible' => TRUE,
|
| 292 |
'#collapsed' => FALSE,
|
| 293 |
'#tree' => TRUE
|
| 294 |
);
|
| 295 |
// convert the points string into an array
|
| 296 |
$points = _bookmaker_betoffer_points_array($node->points);
|
| 297 |
$form['points']['exact'] = array(
|
| 298 |
'#type' => 'textfield',
|
| 299 |
'#title' => t('Exact match'),
|
| 300 |
'#default_value' => $points['exact'],
|
| 301 |
'#description' =>
|
| 302 |
t('The number of points for an exact match. Example: outcome = "5:2", user\'s bet = "5:2"')
|
| 303 |
);
|
| 304 |
$form['points']['tendency'] = array(
|
| 305 |
'#type' => 'textfield',
|
| 306 |
'#title' => t('Correct tendency'),
|
| 307 |
'#default_value' => $points['tendency'],
|
| 308 |
'#description' =>
|
| 309 |
t('The number of points for a correct tendency. Example: outcome = "2:3", user\'s bet = "0:4"')
|
| 310 |
);
|
| 311 |
$form['#submit'] = array('bookmaker_betoffer_node_form_submit');
|
| 312 |
|
| 313 |
return $form;
|
| 314 |
}
|
| 315 |
|
| 316 |
|
| 317 |
|
| 318 |
/**
|
| 319 |
* Implementation of hook_validate().
|
| 320 |
*/
|
| 321 |
function bookmaker_betoffer_validate(&$node) {
|
| 322 |
if (strtotime($node->closes_on) === FALSE) {
|
| 323 |
form_set_error('closes_on', t('Please enter a valid date for the closing time.'));
|
| 324 |
}
|
| 325 |
}
|
| 326 |
|
| 327 |
|
| 328 |
|
| 329 |
/**
|
| 330 |
* Implementation of hook_submit().
|
| 331 |
*/
|
| 332 |
function bookmaker_betoffer_node_form_submit($form, &$form_state) {
|
| 333 |
$form_state['values']['closes_on'] =
|
| 334 |
strtotime($form_state['values']['closes_on']);
|
| 335 |
$form_state['values']['points'] =
|
| 336 |
_bookmaker_betoffer_points_string($form_state['values']['points']);
|
| 337 |
}
|
| 338 |
|
| 339 |
|
| 340 |
|
| 341 |
/**
|
| 342 |
* Implementation of hook_insert().
|
| 343 |
*/
|
| 344 |
function bookmaker_betoffer_insert($node) {
|
| 345 |
$sql = "INSERT INTO {bookmaker}
|
| 346 |
(nid, vid, closes_on, outcome, points)
|
| 347 |
VALUES (%d, %d, %d, '%s', '%s')";
|
| 348 |
|
| 349 |
db_query($sql,
|
| 350 |
$node->nid,
|
| 351 |
$node->vid,
|
| 352 |
$node->closes_on,
|
| 353 |
$node->outcome,
|
| 354 |
$node->points
|
| 355 |
);
|
| 356 |
}
|
| 357 |
|
| 358 |
|
| 359 |
|
| 360 |
/**
|
| 361 |
* Implementation of hook_update().
|
| 362 |
*/
|
| 363 |
function bookmaker_betoffer_update($node) {
|
| 364 |
// if this is a new node or we're adding a new revision, insert it
|
| 365 |
if ($node->revision) {
|
| 366 |
bookmaker_betoffer_insert($node);
|
| 367 |
}
|
| 368 |
else {
|
| 369 |
$sql = "UPDATE {bookmaker} SET
|
| 370 |
closes_on = %d,
|
| 371 |
outcome = '%s',
|
| 372 |
points = '%s'
|
| 373 |
WHERE vid = %d";
|
| 374 |
|
| 375 |
db_query($sql,
|
| 376 |
$node->closes_on,
|
| 377 |
$node->outcome,
|
| 378 |
$node->points,
|
| 379 |
$node->vid
|
| 380 |
);
|
| 381 |
}
|
| 382 |
|
| 383 |
// extract user bets for this bet offer
|
| 384 |
$result = db_query("SELECT uid, bet FROM {bookmaker_bets} WHERE nid=%d",
|
| 385 |
$node->nid);
|
| 386 |
// turn the points string into an array for easier processing
|
| 387 |
$points = _bookmaker_betoffer_points_array($node->points);
|
| 388 |
// get all user's bets into an array for points calculation
|
| 389 |
$user_bets = array();
|
| 390 |
while ($bet = db_fetch_array($result)) {
|
| 391 |
$user_bets[$bet['uid']] = $bet['bet'];
|
| 392 |
}
|
| 393 |
|
| 394 |
// update user bets, if there are any
|
| 395 |
if (count($user_bets)) {
|
| 396 |
$user_points = bookmaker_calculate_user_points($node->outcome,
|
| 397 |
$user_bets, $points);
|
| 398 |
|
| 399 |
// update each user with the assigned points
|
| 400 |
foreach ($user_points as $uid => $points) {
|
| 401 |
$sql = "UPDATE {bookmaker_bets} SET user_points=%d WHERE nid=%d AND uid=%d";
|
| 402 |
db_query($sql, $points, $node->nid, $uid);
|
| 403 |
}
|
| 404 |
}
|
| 405 |
}
|
| 406 |
|
| 407 |
|
| 408 |
|
| 409 |
/**
|
| 410 |
* Implementation of hook_nodeapi().
|
| 411 |
*
|
| 412 |
* When a node revision is deleted, we need to remove the corresponding record
|
| 413 |
* from our table. The only way to handle revision deletion is by implementing
|
| 414 |
* hook_nodeapi().
|
| 415 |
*/
|
| 416 |
function bookmaker_nodeapi(&$node, $op, $teaser, $page) {
|
| 417 |
if ($op == 'delete revision') {
|
| 418 |
// Notice that we're matching a single revision based on the node's vid.
|
| 419 |
db_query('DELETE FROM {bookmaker} WHERE vid = %d', $node->vid);
|
| 420 |
}
|
| 421 |
}
|
| 422 |
|
| 423 |
|
| 424 |
|
| 425 |
/**
|
| 426 |
* Implementation of hook_delete().
|
| 427 |
*/
|
| 428 |
function bookmaker_betoffer_delete($node) {
|
| 429 |
// Notice that we're matching all revision, by using the node's nid.
|
| 430 |
db_query('DELETE FROM {bookmaker} WHERE nid = %d', $node->nid);
|
| 431 |
|
| 432 |
// Remove all user bets on this offer as well
|
| 433 |
db_query('DELETE FROM {bookmaker_bets} WHERE nid = %d', $node->nid);
|
| 434 |
}
|
| 435 |
|
| 436 |
|
| 437 |
|
| 438 |
/**
|
| 439 |
* Implementation of hook_load().
|
| 440 |
*/
|
| 441 |
function bookmaker_betoffer_load($node) {
|
| 442 |
$sql = "SELECT
|
| 443 |
closes_on,
|
| 444 |
outcome,
|
| 445 |
points
|
| 446 |
FROM {bookmaker} WHERE vid = %d";
|
| 447 |
|
| 448 |
$additions = db_fetch_object(db_query($sql, $node->vid));
|
| 449 |
return $additions;
|
| 450 |
}
|
| 451 |
|
| 452 |
|
| 453 |
|
| 454 |
/**
|
| 455 |
* Implementation of hook_view().
|
| 456 |
*/
|
| 457 |
function bookmaker_betoffer_view(&$node, $teaser = FALSE, $page = FALSE) {
|
| 458 |
$user_bets = array();
|
| 459 |
|
| 460 |
$node = node_prepare($node, $teaser);
|
| 461 |
|
| 462 |
// get the results of the bet offer
|
| 463 |
$sql = "SELECT * FROM {bookmaker_bets} WHERE nid=%d\n";
|
| 464 |
$sql .= "ORDER BY user_points DESC";
|
| 465 |
$result = db_query($sql, $node->nid);
|
| 466 |
while ($user_bet = db_fetch_array($result)) {
|
| 467 |
$user_bets[] = $user_bet;
|
| 468 |
}
|
| 469 |
|
| 470 |
$node->content['bookmaker_betoffer'] = array(
|
| 471 |
'#value' => theme('bookmaker_betoffer', $node, $user_bets),
|
| 472 |
'#weight' => 1,
|
| 473 |
);
|
| 474 |
|
| 475 |
return $node;
|
| 476 |
}
|
| 477 |
|
| 478 |
|
| 479 |
|
| 480 |
/**
|
| 481 |
* Implementation of hook_theme().
|
| 482 |
*/
|
| 483 |
function bookmaker_theme() {
|
| 484 |
return array(
|
| 485 |
// Custom theme function
|
| 486 |
'bookmaker_betoffer' => array(
|
| 487 |
'arguments' => array('node' => NULL, 'user_bets' => NULL),
|
| 488 |
)
|
| 489 |
);
|
| 490 |
}
|
| 491 |
|
| 492 |
|
| 493 |
|
| 494 |
/**
|
| 495 |
* Custom theme function
|
| 496 |
*/
|
| 497 |
function theme_bookmaker_betoffer($node, $user_bets) {
|
| 498 |
$points = _bookmaker_betoffer_points_array($node->points);
|
| 499 |
$output = '';
|
| 500 |
|
| 501 |
// show the results after the closing time
|
| 502 |
if ($node->closes_on <= gmmktime() && $node->outcome != '') {
|
| 503 |
$output .= '<p>'. t('Outcome: @outcome',
|
| 504 |
array('@outcome' => $node->outcome)) .'</p>';
|
| 505 |
if (count($user_bets) > 0) {
|
| 506 |
$output .= '<p>'. t('Results:') .'</p>';
|
| 507 |
$output .= '<ul>';
|
| 508 |
foreach ($user_bets as $user_bet) {
|
| 509 |
$output .= '<li>';
|
| 510 |
$user = user_load(array('uid' => $user_bet['uid']));
|
| 511 |
$user_points = format_plural($user_bet['user_points'],
|
| 512 |
'@count point', '@count points');
|
| 513 |
$output .= t('!username: @bet, @user_points',
|
| 514 |
array('!username' => theme('username', $user),
|
| 515 |
'@bet' => $user_bet['bet'],
|
| 516 |
'@user_points' => $user_points));
|
| 517 |
$output .= '</li>';
|
| 518 |
}
|
| 519 |
$output .= '</ul>';
|
| 520 |
}
|
| 521 |
}
|
| 522 |
|
| 523 |
// adjust the output based on the time
|
| 524 |
$output .= '<div class="messages status">';
|
| 525 |
if ($node->closes_on > gmmktime()) {
|
| 526 |
$output .= '<p>'. t('This bet offer closes on @date, time left: @time.',
|
| 527 |
array('@date' => format_date($node->closes_on),
|
| 528 |
'@time' => format_interval($node->closes_on - gmmktime()))) .'<br />';
|
| 529 |
}
|
| 530 |
else {
|
| 531 |
$output .= '<p>'. t('This bet offer has closed on @date.',
|
| 532 |
array('@date' => format_date($node->closes_on))) .'<br />';
|
| 533 |
}
|
| 534 |
|
| 535 |
$output .= format_plural(count($user_bets),
|
| 536 |
'@count user has placed a bet on this offer.',
|
| 537 |
'@count users have placed a bet on this offer.');
|
| 538 |
$output .= '<br />';
|
| 539 |
|
| 540 |
// show the available points for the bet offer
|
| 541 |
if (count($points) != 0) {
|
| 542 |
$output .= t('The following points are assigned:') .'</p>';
|
| 543 |
$output .= '<ul>';
|
| 544 |
if ($points['exact'] != 0) {
|
| 545 |
$output .= '<li>';
|
| 546 |
$output .= format_plural($points['exact'],
|
| 547 |
'Exact match: @count point', 'Exact match: @count points');
|
| 548 |
$output .= '</li>';
|
| 549 |
}
|
| 550 |
if ($points['tendency'] != 0) {
|
| 551 |
$output .= '<li>';
|
| 552 |
$output .= format_plural($points['tendency'],
|
| 553 |
'Correct tendency: @count point', 'Correct tendency: @count points');
|
| 554 |
$output .= '</li>';
|
| 555 |
}
|
| 556 |
$output .= '</ul>';
|
| 557 |
}
|
| 558 |
else {
|
| 559 |
$output .= t('No points have been assigned.') .'</p>';
|
| 560 |
}
|
| 561 |
|
| 562 |
$output .= '</div>';
|
| 563 |
return $output;
|
| 564 |
}
|
| 565 |
|
| 566 |
|
| 567 |
|
| 568 |
/*********************************************************************
|
| 569 |
* Management of bet offers
|
| 570 |
********************************************************************/
|
| 571 |
|
| 572 |
|
| 573 |
|
| 574 |
/**
|
| 575 |
* Provide a list of all open bet offers
|
| 576 |
*/
|
| 577 |
function bookmaker_show_betoffers() {
|
| 578 |
// get all open bet offers
|
| 579 |
$sql = "SELECT n.nid FROM {node} AS n\n";
|
| 580 |
$sql .= "LEFT JOIN {bookmaker} AS bm ON n.vid=bm.vid\n";
|
| 581 |
$sql .= "WHERE n.type='bet_offer' AND n.status=1 AND bm.closes_on>UNIX_TIMESTAMP()\n";
|
| 582 |
$sql .= "ORDER BY bm.closes_on ASC, n.title ASC";
|
| 583 |
|
| 584 |
$output = '';
|
| 585 |
$result = pager_query(db_rewrite_sql($sql), 10);
|
| 586 |
while ($node = db_fetch_object($result)) {
|
| 587 |
$output .= node_view(node_load($node->nid), 1);
|
| 588 |
}
|
| 589 |
$output .= theme('pager', NULL, 10);
|
| 590 |
return $output;
|
| 591 |
}
|
| 592 |
|
| 593 |
|
| 594 |
|
| 595 |
/*********************************************************************
|
| 596 |
* Drupal hooks and private functions for managing the user bets
|
| 597 |
********************************************************************/
|
| 598 |
|
| 599 |
|
| 600 |
|
| 601 |
/**
|
| 602 |
* Implementation of hook_link().
|
| 603 |
*/
|
| 604 |
function bookmaker_link($type, $node = NULL, $teaser = FALSE) {
|
| 605 |
global $user;
|
| 606 |
|
| 607 |
$links = array();
|
| 608 |
if ($type == 'node' and $node->type == 'bet_offer'
|
| 609 |
and user_access('place a bet') and $node->closes_on > gmmktime()) {
|
| 610 |
// change the link text if there is already a bet
|
| 611 |
$sql = "SELECT nid FROM {bookmaker_bets} WHERE nid=%d AND uid=%d";
|
| 612 |
if (db_result(db_query($sql, $node->nid, $user->uid))) {
|
| 613 |
$text = t('Edit bet');
|
| 614 |
}
|
| 615 |
else {
|
| 616 |
$text = t('Place a bet');
|
| 617 |
}
|
| 618 |
$links['bookmaker_betoffer'] = array(
|
| 619 |
'title' => $text,
|
| 620 |
'href' => "bookmaker/place_bet/$node->nid",
|
| 621 |
);
|
| 622 |
}
|
| 623 |
return $links;
|
| 624 |
}
|
| 625 |
|
| 626 |
|
| 627 |
|
| 628 |
/**
|
| 629 |
* Enable the user to place a bet
|
| 630 |
*/
|
| 631 |
function bookmaker_userbet_place_bet($node = NULL) {
|
| 632 |
global $user;
|
| 633 |
|
| 634 |
// perform security check
|
| 635 |
if ($node->type != 'bet_offer') {
|
| 636 |
drupal_set_message(t('The bet offer you specified does not exist.'), 'error');
|
| 637 |
drupal_goto();
|
| 638 |
}
|
| 639 |
|
| 640 |
// is the bet offer still accepting bets?
|
| 641 |
if ($node->closes_on < gmmktime()) {
|
| 642 |
drupal_set_message(t('This bet offer has closed, you can no longer place a bet on it.'), 'error');
|
| 643 |
drupal_goto("node/$node->nid");
|
| 644 |
}
|
| 645 |
|
| 646 |
// get the user's bet
|
| 647 |
$sql = 'SELECT * FROM {bookmaker_bets} ';
|
| 648 |
$sql .= "WHERE nid=%d AND uid=%d";
|
| 649 |
$result = db_query($sql, $node->nid, $user->uid);
|
| 650 |
$row = db_fetch_object($result);
|
| 651 |
|
| 652 |
$output = node_view($node);
|
| 653 |
$output .= theme('box', t('Place a bet'),
|
| 654 |
drupal_get_form('bookmaker_userbet_place_bet_form', $node->nid, $row));
|
| 655 |
return $output;
|
| 656 |
}
|
| 657 |
|
| 658 |
|
| 659 |
|
| 660 |
/**
|
| 661 |
* Create a form for entering user bets
|
| 662 |
*/
|
| 663 |
function bookmaker_userbet_place_bet_form($form_state, $nid, $row) {
|
| 664 |
// prepare a form for the entering of a user bet
|
| 665 |
$form['bet'] = array(
|
| 666 |
'#type' => 'textfield',
|
| 667 |
'#title' => t('Your bet'),
|
| 668 |
'#default_value' => $row->bet,
|
| 669 |
'#required' => TRUE,
|
| 670 |
);
|
| 671 |
$form['nid'] = array(
|
| 672 |
'#type' => 'value',
|
| 673 |
'#value' => $nid,
|
| 674 |
);
|
| 675 |
$form['submit'] = array(
|
| 676 |
'#type' => 'submit',
|
| 677 |
'#value' => t('Place this bet'),
|
| 678 |
);
|
| 679 |
// show a delete button if there's a user bet placed
|
| 680 |
if (isset($row->bet)) {
|
| 681 |
$form['delete'] = array(
|
| 682 |
'#type' => 'submit',
|
| 683 |
'#value' => t('Delete this bet'),
|
| 684 |
);
|
| 685 |
}
|
| 686 |
return $form;
|
| 687 |
}
|
| 688 |
|
| 689 |
|
| 690 |
|
| 691 |
/**
|
| 692 |
* Inserts, updates or deletes the user's bet
|
| 693 |
*
|
| 694 |
* This function explicitely set the points for the user back to 0.
|
| 695 |
*/
|
| 696 |
function bookmaker_userbet_place_bet_form_submit($form, &$form_state) {
|
| 697 |
global $user;
|
| 698 |
|
| 699 |
// first, delete the bet
|
| 700 |
$sql = "DELETE FROM {bookmaker_bets} WHERE nid=%d AND uid=%d";
|
| 701 |
db_query($sql, $form_state['values']['nid'], $user->uid);
|
| 702 |
|
| 703 |
// check if the user only wants to delete the bet
|
| 704 |
$op = $_POST['op'];
|
| 705 |
if ($op == t('Delete this bet')) {
|
| 706 |
drupal_set_message(t('Your bet has been deleted.'));
|
| 707 |
}
|
| 708 |
else {
|
| 709 |
// create a new bet
|
| 710 |
$sql = "INSERT INTO {bookmaker_bets}\n";
|
| 711 |
$sql .= "(nid, uid, bet, placed_on, user_points)\n";
|
| 712 |
$sql .= "VALUES (%d, %d, '%s', %d, 0)";
|
| 713 |
db_query($sql, $form_state['values']['nid'], $user->uid,
|
| 714 |
$form_state['values']['bet'], gmmktime());
|
| 715 |
drupal_set_message(t('Your bet has been saved.'));
|
| 716 |
}
|
| 717 |
drupal_goto('node/'. $form_state['values']['nid']);
|
| 718 |
}
|