uc_auction.module

Tracking 6.x-1.x branch
  1. drupal
    1. 6 contributions/uc_auction/uc_auction.module

The main module file. Has all hooks and most basic callbacks.

Functions & methods

NameDescription
alter_price_if_european_price_formatting
theme_uc_auction_bid_tableTheme the bid table.
uc_auction_add_to_cartImplementation of hook_add_to_cart() (an Ubercart hook).
uc_auction_bid_del_confConfirm bid deletion.
uc_auction_bid_del_conf_submitDelete bids.
uc_auction_bid_historyList bids.
uc_auction_bid_history_permSee if the user can view the bid history on a node.
uc_auction_bid_table_formDescribe the bid form table.
uc_auction_bid_table_form_submitSubmit placed bids.
uc_auction_bid_table_form_validateValidate placed bids.
uc_auction_cart_itemImplementation of hook_cart_item() (an Ubercart hook).
uc_auction_field_settings_submitSave or delete the field settings per the user's request.
uc_auction_form_alterImplementation of hook_form_alter().
uc_auction_form_validate
uc_auction_insert_bidProperly inserts bids into the database.
uc_auction_mailImplementation of hook_mail().
uc_auction_menuImplementation of hook_menu().
uc_auction_nodeapiImplementation of hook_nodeapi().
uc_auction_orderImplementation of hook_order() (an Ubercart hook).
uc_auction_permImplementation of hook_perm().
uc_auction_themeImplementation of hook_theme().
uc_auction_token_listImplementation of hook_token_list() (a Token hook).
uc_auction_token_valuesImplementation of hook_token_values (a Token hook).
uc_auction_uc_messageImplementation of hook_uc_message() (an Ubercart hook).
uc_auction_user_auctions_permSee if the user can view a particular user's auction activity.
uc_auction_views_apiImplementation of hook_views_api().
_uc_auction_is_uc_typeCheck if a node's type is an Ubercart product type.
_uc_auction_mod_zeroCheck if the remainder of two divisors is zero.
_uc_auction_uncurrencyConverts a string which should contain a currency value into a float.

File

View source
  1. <?php
  2. /**
  3. * @defgroup uc_auction Ubercart Auction: Allows Ubercart products to be
  4. * auctioned.
  5. *
  6. * This module allows sites which are using the Ubercart system of modules for
  7. * Drupal to offer products up for auction. Users may bid on the auctions, and
  8. * only the user with the highest bid at the expiry of the auction may purchase
  9. * it. Please visit the site at the address below for more information on this
  10. * module, and especially how to configure and use it.
  11. * http://example.com/uc_auction
  12. */
  13. /**
  14. * @file
  15. * The main module file. Has all hooks and most basic callbacks.
  16. *
  17. * @ingroup uc_auction
  18. */
  19. /* Hooks ******************************************************************** */
  20. /**
  21. * Implementation of hook_menu().
  22. */
  23. function uc_auction_menu() {
  24. return array(
  25. 'admin/store/settings/store/auction' => array(
  26. 'title' => 'Auction settings',
  27. 'description' => 'Settings relevant to product auctions.',
  28. 'page callback' => 'drupal_get_form',
  29. 'page arguments' => array('uc_auction_settings_form'),
  30. 'access arguments' => array('administer store'),
  31. 'file' => 'uc_auction.admin.inc',
  32. 'type' => MENU_NORMAL_ITEM,
  33. ),
  34. 'node/%node/bids' => array(
  35. 'title' => 'Bids',
  36. 'type' => MENU_LOCAL_TASK,
  37. 'description' => 'The bid history for this product.',
  38. 'page callback' => 'uc_auction_bid_history',
  39. 'page arguments' => array(1),
  40. // We're using a custom callback for this so that we can say the user
  41. // doesn't have permission to view bids on an item which is not being
  42. // auctioned; that is, we only want this tab to appear if the node is a
  43. // product which is being auctioned. Using the permissions system might
  44. // not be the best way to go about this, actually.
  45. 'access callback' => 'uc_auction_bid_history_perm',
  46. 'access arguments' => array(1),
  47. ),
  48. 'node/%node/bids/delete/%' => array(
  49. 'title' => 'Delete bids',
  50. 'description' => 'Delete bids for this item.',
  51. 'page callback' => 'drupal_get_form',
  52. 'page arguments' => array('uc_auction_bid_del_conf', 1, 4),
  53. 'access arguments' => array('delete bids'),
  54. ),
  55. 'user/%user/auctions' => array(
  56. 'title' => 'Auctions',
  57. 'type' => MENU_LOCAL_TASK,
  58. 'description' => 'Auctions the user has bid upon',
  59. 'page callback' => 'uc_auction_user_auctions',
  60. 'page arguments' => array(1, 'active'),
  61. 'access callback' => 'uc_auction_user_auctions_perm',
  62. 'access arguments' => array(1),
  63. 'file' => 'uc_auction.user.inc',
  64. 'weight' => 8,
  65. ),
  66. 'user/%user/auctions/active' => array(
  67. 'title' => 'Active auctions',
  68. 'type' => MENU_DEFAULT_LOCAL_TASK,
  69. 'description' => 'Active auctions bid upon',
  70. 'weight' => 0,
  71. ),
  72. 'user/%user/auctions/own' => array(
  73. 'title' => 'Own auctions',
  74. 'type' => MENU_LOCAL_TASK,
  75. 'description' => 'Own auctions',
  76. 'page callback' => 'uc_auction_user_auctions',
  77. 'page arguments' => array(1, 'own'),
  78. 'access callback' => 'uc_auction_user_auctions_perm',
  79. 'access arguments' => array(1),
  80. 'file' => 'uc_auction.user.inc',
  81. 'weight' => 0,
  82. ),
  83. 'user/%user/auctions/won' => array(
  84. 'title' => 'Auctions won',
  85. 'type' => MENU_LOCAL_TASK,
  86. 'description' => 'Expired auctions bid upon and won',
  87. 'page callback' => 'uc_auction_user_auctions',
  88. 'page arguments' => array(1, 3),
  89. 'access callback' => 'uc_auction_user_auctions_perm',
  90. 'access arguments' => array(1),
  91. 'file' => 'uc_auction.user.inc',
  92. 'weight' => 2,
  93. ),
  94. 'user/%user/auctions/lost' => array(
  95. 'title' => 'Auctions lost',
  96. 'type' => MENU_LOCAL_TASK,
  97. 'description' => 'Expired auctions bid upon but lost',
  98. 'page callback' => 'uc_auction_user_auctions',
  99. 'page arguments' => array(1, 3),
  100. 'access callback' => 'uc_auction_user_auctions_perm',
  101. 'access arguments' => array(1),
  102. 'file' => 'uc_auction.user.inc',
  103. 'weight' => 4,
  104. ),
  105. );
  106. }
  107. /**
  108. * Implementation of hook_perm().
  109. */
  110. function uc_auction_perm() {
  111. return array('place bid', 'view bids', 'view full bid info', 'delete bids', 'create auctions', 'set expiration time and date');
  112. }
  113. /**
  114. * Implementation of hook_form_alter().
  115. */
  116. function uc_auction_form_alter(&$form, $form_state, $form_id) {
  117. if (user_access('create auctions')) {
  118. // We want to alter the form if it is of the form "foo_node_form" and foo is
  119. // an Ubercart product type.
  120. if (preg_match('/^(.+)_node_form$/', $form_id, $matches) && in_array($matches[1], module_invoke_all('product_types'))) {
  121. // This is the node editing form for an Ubercart product type. Add options
  122. // to auction-ize this item.
  123. $is_curr_auction = isset($form['#node']->uc_auction);
  124. $is_new_auction = !isset($form['#node']->nid) && !$is_curr_auction && variable_get('uc_auction_new_default', FALSE);
  125. if (variable_get('uc_sign_after_amount', FALSE)) {
  126. $prefix = '';
  127. $suffix = variable_get('uc_currency_sign', '$');
  128. }
  129. else {
  130. $prefix = variable_get('uc_currency_sign', '$');
  131. $suffix = '';
  132. }
  133. $elapse_time_in_hours = variable_get('uc_auction_elapse_time_in_hours', FALSE);
  134. if (isset($form['#node']->uc_auction) && empty($elapse_time_in_hours)) {
  135. $expiry = /*format_date(*/intval($form['#node']->uc_auction['expiry'])/*, 'custom', 'r')*/;
  136. } elseif(!empty($elapse_time_in_hours)){
  137. // only add time, if auction already created
  138. if(!empty($form['nid']['#value']) && !empty($form['#node']->uc_auction)){
  139. $expiry = $form['#node']->uc_auction['expiry'];
  140. } else {
  141. $expiry = time() + variable_get('uc_auction_elapse_time_in_hours', FALSE) * 60 * 60;
  142. }
  143. }
  144. else {
  145. variable_get('uc_currency_sign', '$');
  146. // 60s * 60m * 24h * 7d = 604800
  147. if(empty($elapse_time_in_hours)){
  148. $expiry = time() + 604800;
  149. } else {
  150. $expiry = time() + variable_get('uc_auction_elapse_time_in_hours', FALSE) * 60 * 60;
  151. }
  152. }
  153. $form['#validate'][] = 'uc_auction_form_validate';
  154. $form['base']['auction'] = array(
  155. '#type' => 'fieldset',
  156. '#title' => t('Auction settings'),
  157. '#collapsible' => TRUE,
  158. '#collapsed' => FALSE,
  159. '#weight'=> 8,
  160. 'is_auction' => array(
  161. '#type' => 'checkbox',
  162. '#title' => t('This is an auctioned product.'),
  163. '#description' => $is_curr_auction ? t('Warning: Unchecking this box will stop this product from being auctioned and its <a href="!blink">bid history</a> will be erased.', array('!blink' => url("node/{$form['#node']->nid}/bids"))) : '',
  164. '#default_value' => TRUE,
  165. '#weight' => 0,
  166. ),
  167. 'start_price' => array(
  168. // This weird #type thing is explained below.
  169. '#type' => $is_curr_auction ? 'value' : 'textfield',
  170. '#title' => t('Starting price'),
  171. '#description' => t('The first bidder will be required to place a valid bid above this initial amount. You cannot change this value while a product is being auctioned.'),
  172. '#disabled' => $is_curr_auction,
  173. '#default_value' => $is_curr_auction ? uc_currency_format($form['#node']->uc_auction['start_price'], FALSE) : '',
  174. '#field_prefix' => $perfix,
  175. '#field_suffix' => $suffix,
  176. '#size' => 12,
  177. '#weight' => 5,
  178. '#required' => TRUE,
  179. ),
  180. 'expiry' => array(
  181. '#type' => 'hidden',
  182. '#title' => t('Expiration date &amp; time'),
  183. '#description' => t('Select a date and time when this auction will expire (relative to the server&rsquo;s local time).'),
  184. '#default_value' => format_date($expiry, 'custom', 'Y-m-d H:i:s'),
  185. '#weight' => 10,
  186. ),
  187. );
  188. if(user_access('set expiration time and date')){
  189. $form['base']['auction']['expiry']['#type'] = 'date_popup';
  190. }
  191. // The user can only change the start_price when a product is not currently
  192. // being auctioned. The other times, we display it as a disabled textfield.
  193. // However, since disabled fields are not submitted by browsers, we need
  194. // to submit a value of the start_price when that is the case. If it is,
  195. // then we've already given start_price a #type of 'value' above, along with
  196. // other attributes which are used for textfields but not for values. Let's
  197. // duplicate that to make the visible (but disabled) textfield.
  198. if ($is_curr_auction) {
  199. $form['base']['auction']['start_price_disp'] = $form['base']['auction']['start_price'];
  200. $form['base']['auction']['start_price_disp']['#type'] = 'textfield';
  201. }
  202. if (user_access('administer store')) {
  203. $incr = variable_get('uc_auction_max_increase', 1000);
  204. $pctg = variable_get('uc_auction_max_increase_pctg', 100);
  205. $form['base']['auction']['bid_overrides'] = array(
  206. '#type' => 'fieldset',
  207. '#title' => t('Bid increment and increase overrides'),
  208. '#collapsible' => TRUE,
  209. '#collapsed' => $is_curr_auction && $form['#node']->uc_auction['bid_increment'] === NULL && $form['#node']->uc_auction['min_increase'] === NULL && $form['#node']->uc_auction['max_increase'] === NULL && $form['#node']->uc_auction['max_increase_pctg'] === NULL,
  210. '#weight' => 15,
  211. 'bid_overrides_desc' => array(
  212. '#type' => 'markup',
  213. '#weight' => 0,
  214. '#value' => t('<p>Leave these fields blank to use the site-wide values as set on the the <a href="../../admin/store/settings/store/auction">Ubercart Auction settings page</a>, or enter values into the fields to overwrite them on a per-product basis.</p>'),
  215. ),
  216. 'bid_increment' => array(
  217. '#type' => 'textfield',
  218. '#title' => t('Bid increment'),
  219. '#description' => t('Site-wide configuration value: %val<br />Bids must be a multiple of this increment to be accepted. If your site is using a currency which does not have subunits in circulation (JPY, KRW), this should be an integer.', array('%val' => uc_currency_format(variable_get('uc_auction_bid_increment', .25)))),
  220. '#size' => 20,
  221. '#default_value' => !$is_curr_auction || $form['#node']->uc_auction['bid_increment'] === NULL ? '' : uc_currency_format($form['#node']->uc_auction['bid_increment'], FALSE, FALSE),
  222. '#field_prefix' => $prefix,
  223. '#field_suffix' => $suffix,
  224. '#weight' => 10,
  225. ),
  226. 'min_increase' => array(
  227. '#type' => 'textfield',
  228. '#title' => t('Minimum bid increase'),
  229. '#description' => t('Site-wide configuration value: %val<br />New bids must be at least this much higher than the current high bid to be accepted. This value should be a multiple of the <em>Bid increment</em> value.', array('%val' => uc_currency_format(variable_get('uc_auction_min_increase', .5)))),
  230. '#size' => 20,
  231. '#default_value' => !$is_curr_auction || $form['#node']->uc_auction['min_increase'] === NULL ? '' : uc_currency_format($form['#node']->uc_auction['min_increase'], FALSE, FALSE),
  232. '#field_prefix' => $prefix,
  233. '#field_suffix' => $suffix,
  234. '#weight' => 15,
  235. ),
  236. 'max_increase' => array(
  237. '#type' => 'textfield',
  238. '#title' => t('Maximum bid increase'),
  239. '#description' => t('Site-wide configuration value: %val<br />New bids which are this much higher than the current high bid will not be accepted. Setting a maximum bid increase stops users from placing a ridiculously high bid, either accidentally or otherwise. Enter zero to not enforce this limit. In the case that both the <em>Maximum bid increase</em> and <em>Maximum bid increase percentage</em> values are set, both limits will be enforced.', array('%val' => $incr ? uc_currency_format($incr) : t('(none)'))),
  240. '#size' => 20,
  241. '#default_value' => !$is_curr_auction || $form['#node']->uc_auction['max_increase'] === NULL ? '' : uc_currency_format($form['#node']->uc_auction['max_increase'], FALSE, FALSE),
  242. '#field_prefix' => $prefix,
  243. '#field_suffix' => $suffix,
  244. '#weight' => 20,
  245. ),
  246. 'max_increase_pctg' => array(
  247. '#type' => 'textfield',
  248. '#title' => t('Maximum bid increase percentage'),
  249. '#description' => t('Site-wide configuration value: %val<br />Bids which increase the high bid value by this percentage will not be accepted. For example, if this value is set to 50% and an item&rsquo;s current high bid is &curren;1000, bids larger than &curren;1500 will not be accepted (as &curren;500 is 50% of &curren;1000). Setting a maximum bid increase stops users from placing a ridiculously high bid, either accidentally or otherwise. Enter zero to not enforce this limit. In the case that both the <em>Maximum bid increase</em> and <em>Maximum bid increase percentage</em> values are set, both limits will be enforced.', array('%val' => $pctg ? $pctg . '%' : t('(none)'))),
  250. '#field_suffix' => t('%'),
  251. '#size' => 6,
  252. '#default_value' => !$is_curr_auction || $form['#node']->uc_auction['max_increase_pctg'] === NULL ? '' : $form['#node']->uc_auction['max_increase_pctg'],
  253. '#weight' => 25,
  254. ),
  255. );
  256. }
  257. }
  258. elseif (strpos($form_id, 'uc_product_add_to_cart_form') === 0) {
  259. // The "Add to Cart" button.
  260. if (isset($form['#parameters'][2]->uc_auction)) {
  261. // This is an auction.
  262. global $user;
  263. if ($form['#parameters'][2]->uc_auction['high_bid_uid'] != $user->uid || time() <= $form['#parameters'][2]->uc_auction['expiry'] || $form['#parameters'][2]->uc_auction['purchased']) {
  264. // That ugly if clause is basically saying "if the current user is not
  265. // the high bidder, OR if the auction has not expired, OR if the item
  266. // has already been purchased…"
  267. $form = array();
  268. }
  269. }
  270. }
  271. // For these forms whose IDs aren't going to change, we could use stand-alone
  272. // hook_form_[form_id]_alter() functions, but since we already have to declare
  273. // a generic hook_form_alter(), we'll just include them here.
  274. elseif ($form_id === 'uc_cart_view_form' && variable_get('uc_auction_force_one', TRUE)) {
  275. foreach ($form['#parameters'][2] as $key => $item) {
  276. if ($item->is_auc) {
  277. // This is a sneaky tricky dirty hack. It's waeome that it works though.
  278. $form['items'][$key]['qty']['qty'] = $form['items'][$key]['qty'];
  279. $form['items'][$key]['qty']['qty']['#type'] = 'value';
  280. $form['items'][$key]['qty']['qty']['#value'] = $form['items'][$key]['qty']['qty']['#default_value'];
  281. $form['items'][$key]['qty']['#tree'] = TRUE;
  282. if (isset($form['items'][$key]['qty']['#attributes'])) {
  283. $form['items'][$key]['qty']['#attributes']['disabled'] = 'disabled';
  284. }
  285. else {
  286. $form['items'][$key]['qty']['#attributes'] = array('disabled' => 'disabled');
  287. }
  288. }
  289. }
  290. }
  291. elseif ($form_id === 'uc_product_field_settings_form') {
  292. // Add our own field settings to this form. If/when this form is updated to
  293. // support D6 drag-and-drop reordering, this will have to be updated.
  294. // Keep defaults in synch with the variable_get() in hook_nodeapi()
  295. $fields = variable_get('uc_auction_field_settings', array(
  296. 'uc_auction_box' => array(
  297. 'enabled' => TRUE,
  298. 'weight' => -3,
  299. ),
  300. ));
  301. $form['fields']['uc_auction_box'] = array(
  302. 'enabled' => array(
  303. '#type' => 'checkbox',
  304. '#default_value' => $fields['uc_auction_box']['enabled'],
  305. ),
  306. 'title' => array(
  307. '#type' => 'markup',
  308. '#value' => t('Auction box'),
  309. ),
  310. 'weight' => array(
  311. '#type' => 'weight',
  312. '#delta' => 10,
  313. '#default_value' => $fields['uc_auction_box']['weight'],
  314. ),
  315. );
  316. // Resort the list, without #properties
  317. $props = array();
  318. $children = array();
  319. foreach ($form['fields'] as $key => $val) {
  320. if (strpos($key, '#') === 0) {
  321. $props[$key] = $val;
  322. }
  323. else {
  324. $children[$key] = $val;
  325. }
  326. }
  327. uasort($children, 'uc_weight_sort');
  328. $form['fields'] = $props + $children;
  329. $form['#submit'][] = 'uc_auction_field_settings_submit';
  330. $form['buttons']['reset']['#submit'][] = 'uc_auction_field_settings_submit';
  331. }
  332. }
  333. /* SHOW ADD CART BUTTON */
  334. if($form_id == 'uc_auction_bid_table_form'){
  335. $res = db_fetch_object(db_query("SELECT uid, expiry, amount FROM uc_auction ua LEFT JOIN uc_auction_bids uab ON uab.nid = ua.nid WHERE ua.nid = '%s' ORDER BY amount DESC LIMIT 1", $form['nid']['#value']));
  336. global $user;
  337. if(!empty($res->uid)){
  338. if($res->uid !== $user->uid && $res->expiry < time()){
  339. $buyer_isnt_on_it = TRUE;
  340. }
  341. if(variable_get('uc_auction_disable_add_to_cart_button', FALSE) == 1 OR $buyer_isnt_on_it === TRUE){
  342. unset($form['#node']->content['add_to_cart']);
  343. }
  344. } else {
  345. unset($form['#node']->content['add_to_cart']);
  346. }
  347. }
  348. //unset($form['#node']->content['add_to_cart']);
  349. }
  350. /**
  351. * Validate new auction creation.
  352. */
  353. function uc_auction_form_validate($form, &$form_state) {
  354. if(variable_get('enable_european_price_formatting', FALSE) == 1){
  355. $form_state['values'] = alter_price_if_european_price_formatting($form_state['values']);
  356. }
  357. if ($form_state['values']['list_price']) {
  358. if(variable_get('uc_auction_no_changes_after_first_bid', FALSE) == 1){
  359. $bids_already = db_query("SELECT bid FROM {uc_auction_bids} WHERE nid = %d", $form_state['values']['nid']);
  360. $bids_already = db_fetch_object($bids_already);
  361. if(!empty($bids_already->bid)){
  362. form_set_error('title', t('You cannot change the auction, because there are already bids placed.'));
  363. }
  364. }
  365. }
  366. if(module_exists('uc_auction_time_controlled_publish')){
  367. unpublish_if_publish_date_in_front(&$form_state);
  368. }
  369. if ($form_state['values']['is_auction']) {
  370. // Check the overriden increase/increment values, if any; otherwise, load
  371. // the defaults.
  372. // This variable allow us to avoid possibly dividing by zero later…
  373. $calc_div = FALSE;
  374. if (isset($form_state['values']['bid_increment']) && $form_state['values']['bid_increment'] !== '') {
  375. $bid_increment = _uc_auction_uncurrency($form_state['values']['bid_increment']);
  376. if ($bid_increment <= 0) {
  377. form_set_error('bid_increment', t('The <em>Bid increment</em> value must be a positive, non-zero number.'));
  378. }
  379. else {
  380. $calc_div = TRUE;
  381. }
  382. }
  383. else {
  384. $bid_increment = variable_get('uc_auction_bid_increment', .25);
  385. }
  386. if(!empty($form_state['values']['list_price'])){
  387. if(_uc_auction_uncurrency($form_state['values']['start_price']) > _uc_auction_uncurrency($form_state['values']['list_price']) && variable_get('uc_auction_starting_price_lower_than_sell_price', FALSE) == 1){
  388. form_set_error('start_price', t('Starting price must be lower than sell price.'));
  389. }
  390. } elseif(!empty($form_state['values']['sell_price'])){
  391. if(_uc_auction_uncurrency($form_state['values']['start_price']) > _uc_auction_uncurrency($form_state['values']['sell_price']) && variable_get('uc_auction_starting_price_lower_than_sell_price', FALSE) == 1){
  392. form_set_error('start_price', t('Starting price must be lower than sell price.'));
  393. }
  394. }
  395. if (isset($form_state['values']['min_increase']) && $form_state['values']['min_increase'] !== '') {
  396. $min_increase = _uc_auction_uncurrency($form_state['values']['min_increase']);
  397. if ($min_increase <= 0) {
  398. form_set_error('min_increase', t('The <em>Minimum bid increase</em> value must be a positive, non-zero number.'));
  399. $calc_div = FALSE;
  400. }
  401. else {
  402. $calc_div = TRUE;
  403. }
  404. }
  405. else {
  406. $min_increase = variable_get('uc_auction_min_increase', .5);
  407. }
  408. if ($calc_div && !_uc_auction_mod_zero($min_increase, $bid_increment)) {
  409. if ($form_state['values']['bid_increment'] !== '' && $form_state['values']['min_increase'] !== '') {
  410. form_set_error('bid_increment', t('The overriden <em>Minimum bid increase</em> value is not a multiple of the overriden <em>Bid increment</em> value.'));
  411. }
  412. elseif ($form_state['values']['bid_increment'] !== '') {
  413. form_set_error('bid_increment', t('The site-wide <em>Minimum bid increase</em> value is not a multiple of the overriden <em>Bid increment</em> value.'));
  414. }
  415. else {
  416. form_set_error('min_increase', t('The overridden <em>Minimum bid increase</em> value is not a multiple of the site-wide <em>Bid increment</em> value.'));
  417. }
  418. }
  419. if (isset($form_state['values']['max_increase']) && $form_state['values']['max_increase'] !== '') {
  420. $max_increase = _uc_auction_uncurrency($form_state['values']['max_increase']);
  421. if ($max_increase < $min_increase) {
  422. form_set_error('max_increase', t('The <em>Maximum bid increase</em> value cannot be smaller than the <em>Minimum bid increase</em> value.'));
  423. }
  424. }
  425. else {
  426. $max_increase = variable_get('uc_auction_max_increase', 1000);
  427. }
  428. if (isset($form_state['values']['max_increase_pctg']) && $form_state['values']['max_increase_pctg'] !== '') {
  429. $max_increase_pctg = floatval($form_state['values']['max_increase_pctg']);
  430. if ($max_increase_pctg < 0) {
  431. form_set_error('max_increase_pctg', t('The <em>Maximum bid increase percentage</em> value must be a positive number.'));
  432. }
  433. }
  434. else {
  435. $max_increase_pctg = variable_get('uc_auction_max_increase_pctg', 100);
  436. }
  437. //Now verify all the normal stuff.
  438. // Check auction expiry time.
  439. $end_time = getdate(strtotime($form_state['values']['expiry']));
  440. $endtime = mktime($end_time['hours'],
  441. $end_time['minutes'],
  442. $end_time['seconds'],
  443. $end_time['mon'],
  444. $end_time['mday'],
  445. $end_time['year']);
  446. if (!$end_time) {
  447. form_set_error('expiry', t('The auction expiration date &amp; time is invalid.'));
  448. }
  449. elseif ($end_time < time()) {
  450. $form_state['values']['expiry'] = format_date($end_time, 'short');
  451. form_set_error('expiry', t('The auction expiration date &amp; time should be in the future.'));
  452. }
  453. else {
  454. $form_state['values']['expiry_ts'] = $end_time;
  455. }
  456. $start = _uc_auction_uncurrency($form_state['values']['start_price']);
  457. if ($form_state['values']['start_price'] === '') {
  458. form_set_error('start_price', t('If you are going to create an auction, you must specify a start price.'));
  459. }
  460. elseif ($start !== 0) {
  461. // We're allowing a start price of 0 to be automatically considered sane.
  462. // That way people can make it so the value of the first bid will be equal
  463. // to the bid increment value.
  464. // Check that the starting value is sane otherwise.
  465. // Is it a multiple of the bid increment value?
  466. if($form_state['submit_handlers']['0'] !== 'node_form_delete_submit'){
  467. if (!_uc_auction_mod_zero($start)) {
  468. /*
  469. form_set_error('start_price', t('The start price for this auctioned item should be a multiple of the <em>Bid increment</em> value, which is @inc. Try using @price instead. You may change the <em>Bid increment</em> value on the <em><a href="@aucset">Auction settings</a></em> page.', array('@inc' => uc_currency_format($bid_increment), '@price' => uc_currency_format(ceil($start / $bid_increment) * $bid_increment), '@aucset' => url('admin/store/settings/auction'))));
  470. */
  471. }
  472. }
  473. // Are things configured such that, with this price, the minimum bid will be
  474. // higher than the maximum bid? In testing, a case occurred where the
  475. // minimum bid value was larger than the maximum bid value; the minimum bid
  476. // increase was $0.50 and the maximum bid increase was 100% or $1000, but
  477. // the starting price of the product was $0.20. The result was a minimum bid
  478. // value of $0.70 but a maximum bid value of $0.40.
  479. $min_bid = $start + $min_increase;
  480. if ($max_increase_pctg) {
  481. // Ignore this if the percentage is 0 anyway
  482. $max_bid_pctg = $start * (($max_increase_pctg / 100) + 1);
  483. // I don't think this is possible to be higher - but we'll check it anyway
  484. $max_bid_flat = $start + $max_increase;
  485. $max_bid = min($max_bid_pctg, $max_bid_flat);
  486. if ($min_bid > $max_bid) {
  487. form_set_error('start_price', t('The start price for this auctioned item is low enough that the minimum bid price (@min) is higher than the maximum bid price (@max). You may need to adjust the site-wide or per-product <em><a href="@aucset">Auction settings</a></em>, if you have permission to do so, so that this problem does not occur.', array('@min' => uc_currency_format($min_bid), '@max' => uc_currency_format($max_bid), '@aucset' => url('admin/store/settings/auction'))));
  488. }
  489. }
  490. }
  491. }
  492. }
  493. function alter_price_if_european_price_formatting($form_values) {
  494. /*** CHANGE PRICE OF AUCTIONS FIX ***/
  495. if(empty($form_values["start_price_disp"])){
  496. $form_values['start_price'] = $_POST["start_price"];
  497. } else {
  498. $form_values['start_price'] = $form_values["start_price_disp"];
  499. }
  500. if(!empty($form_values['start_price']) OR !empty($form_values["start_price_disp"])){
  501. if($form['#post']["is_auction"] == NULL){
  502. $type = array(
  503. '0' => array('field_product_type' => 'Sofortkauf')
  504. );
  505. }
  506. /******* PRICE CHECK BEGIN *******/
  507. $priceTest = str_replace(',', '.', $form_values['start_price']);
  508. $priceTestNumberCount = explode('.', $priceTest);
  509. $priceTestNumberCount = strlen($priceTestNumberCount['1']);
  510. if(is_numeric($priceTest)){
  511. if(is_numeric(strpos($form_values['start_price'], '.'))){
  512. $error = true;
  513. form_set_error('start_price', 'Bitte trennen Sie beim Preis Euro und Cent mit einem Komma.');
  514. }
  515. if($priceTestNumberCount == 2){
  516. // no price fix
  517. $form_values['sell_price'] = str_replace(',', '.', $form_values['start_price']).'000';
  518. } elseif($priceTestNumberCount == 0) {
  519. $form_values['sell_price'] = $form_values['start_price'].'.00000';
  520. } elseif($priceTestNumberCount == 1) {
  521. $form_values['sell_price'] = $form_values['start_price'].'0000';
  522. } elseif($priceTestNumberCount > 2) {
  523. $error = true;
  524. form_set_error('start_price', 'Bitte geben Sie einen gültigen Preis ein.');
  525. }
  526. /**** AUCTION STARTPRICE EDITING FIX ****/
  527. if($form_values["is_auction"] == '1'){
  528. $form_values['sell_price'] = substr($form_values['sell_price'], 0, -2);
  529. $form_values['sell_price'] = str_replace(',', '.', $form_values['sell_price']);
  530. $query = db_query("UPDATE `uc_auction` SET `start_price` = '%s' WHERE `uc_auction`.`nid` ='%s'", $form_values['sell_price'], $form_values['nid']);
  531. } else {
  532. $form_values['sell_price'] = str_replace(',', '.', $form_values['sell_price']);
  533. $query = db_query("UPDATE `uc_products` SET `sell_price` = '%s' WHERE `nid` ='%s'", $form_values['sell_price'], $form_values['nid']);
  534. }
  535. } elseif(!is_numeric($priceTest) && $form['#post']['field_shots_min_price']['value'] !== '1') {
  536. $error = true;
  537. form_set_error('start_price', 'Bitte geben Sie einen gültigen Preis ein.');
  538. }
  539. /******* PRICE CHECK END *******/
  540. }
  541. return $form_values;
  542. }
  543. /**
  544. * Save or delete the field settings per the user's request.
  545. */
  546. function uc_auction_field_settings_submit($form, &$form_state) {
  547. if ($form_state['values']['op'] === t('Reset to defaults')) {
  548. variable_del('uc_auction_field_settings');
  549. }
  550. else {
  551. variable_set('uc_auction_field_settings', array(
  552. 'uc_auction_box' => $form_state['values']['fields']['uc_auction_box'],
  553. ));
  554. }
  555. }
  556. /**
  557. * Implementation of hook_nodeapi().
  558. */
  559. function uc_auction_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  560. //member_billing();
  561. static $expiry = NULL;
  562. static $sell = NULL;
  563. if (_uc_auction_is_uc_type($node)) {
  564. if(module_exists('uc_auction_min_price')){
  565. notify_if_min_price_not_reached();
  566. }
  567. if(module_exists('uc_auction_member_billing')){
  568. member_billing();
  569. }
  570. if ($op === 'validate') {
  571. if ($node->is_auction) {
  572. // This will be an auction. Save the expiry info for later.
  573. $expiry = strtotime($node->expiry);
  574. $sell = _uc_auction_uncurrency($node->start_price);
  575. }
  576. else {
  577. $expiry = NULL;
  578. $sell = FALSE;
  579. }
  580. }
  581. elseif ($op === 'insert' && $node->is_auction) {
  582. // This is an auction. Write the info to uc_auctions.
  583. $record = array(
  584. 'nid' => $node->nid,
  585. 'expiry' => $expiry,
  586. 'start_price' => $sell,
  587. 'bid_increment' => isset($node->bid_increment) && $node->bid_increment !== '' ? _uc_auction_uncurrency($node->bid_increment) : NULL,
  588. 'min_increase' => isset($node->min_increase) && $node->min_increase !== '' ? _uc_auction_uncurrency($node->min_increase) : NULL,
  589. 'max_increase' => isset($node->max_increase) && $node->max_increase !== '' ? _uc_auction_uncurrency($node->max_increase) : NULL,
  590. 'max_increase_pctg' => isset($node->max_increase_pctg) && $node->max_increase_pctg !== '' ? floatval($node->max_increase_pctg) : NULL,
  591. );
  592. // Invoke hook_auc_create(&$node, &$record, $new)
  593. module_invoke_all('auc_create', $node, $record, TRUE);
  594. drupal_write_record('uc_auction', $record);
  595. }
  596. elseif ($op === 'update' && $sell !== NULL) {
  597. // Did we do the validation above?
  598. if ($prev_expiry = db_result(db_query('SELECT expiry FROM {uc_auction} WHERE nid = %d', $node->nid))) {
  599. // This is a previously-existing auction. Are we baleeting it?
  600. if ($expiry !== NULL) {
  601. // This is a previously-existing auction with an updating expiry
  602. // time.
  603. $record = array(
  604. 'nid' => $node->nid,
  605. 'expiry' => $expiry,
  606. 'bid_increment' => isset($node->bid_increment) && $node->bid_increment !== '' ? _uc_auction_uncurrency($node->bid_increment) : NULL,
  607. 'min_increase' => isset($node->min_increase) && $node->min_increase !== '' ? _uc_auction_uncurrency($node->min_increase) : NULL,
  608. 'max_increase' => isset($node->max_increase) && $node->max_increase !== '' ? _uc_auction_uncurrency($node->max_increase) : NULL,
  609. 'max_increase_pctg' => isset($node->max_increase_pctg) && $node->max_increase_pctg !== '' ? floatval($node->max_increase_pctg) : NULL,
  610. );
  611. // Invoke hook_auc_update(&$node, &$record).
  612. module_invoke_all('auc_update', $node, $record);
  613. // drupal_write_record('uc_auction', $record, 'nid');
  614. // We can't use drupal_write_record() here because it doesn't support
  615. // NULL values: http://drupal.org/node/227677 - Damn!
  616. $qparts = array();
  617. foreach ($record as $key => $val) {
  618. if ($key !== 'nid') {
  619. $qparts[] = $key . ' = ' . ($val === NULL ? 'NULL' : $val);
  620. }
  621. }
  622. db_query('UPDATE {uc_auction} SET ' . implode(', ', $qparts) . ' WHERE nid = %d', array($record['nid']));
  623. }
  624. elseif ($expiry === NULL) {
  625. // This is no longer an auction, so delete auction info.
  626. db_query('DELETE FROM {uc_auction} WHERE nid = %d', $node->nid);
  627. db_query('DELETE FROM {uc_auction_bids} WHERE nid = %d', $node->nid);
  628. // Invoke hook_auc_remove($node, $deletion).
  629. module_invoke_all('auc_remove', $node, FALSE);
  630. }
  631. }
  632. elseif ($expiry !== NULL) {
  633. // This is a previously-existing product which is becoming an auction.
  634. $record = array(
  635. 'nid' => $node->nid,
  636. 'expiry' => $expiry,
  637. 'start_price' => $sell,
  638. 'bid_increment' => isset($node->bid_increment) && $node->bid_increment !== '' ? _uc_auction_uncurrency($node->bid_increment) : NULL,
  639. 'min_increase' => isset($node->min_increase) && $node->min_increase !== '' ? _uc_auction_uncurrency($node->min_increase) : NULL,
  640. 'max_increase' => isset($node->max_increase) && $node->max_increase !== '' ? _uc_auction_uncurrency($node->max_increase) : NULL,
  641. 'max_increase_pctg' => isset($node->max_increase_pctg) && $node->max_increase_pctg !== '' ? floatval($node->max_increase_pctg) : NULL,
  642. );
  643. // Invoke hook_auc_create(&$node, &$record, $new)
  644. module_invoke_all('auc_create', $node, $record, FALSE);
  645. drupal_write_record('uc_auction', $record);
  646. }
  647. }
  648. elseif ($op === 'delete') {
  649. // We won't bother checking to see if this was an auction - we'll just
  650. // delete anything that might be there.
  651. db_query('DELETE FROM {uc_auction} WHERE nid = %d', $node->nid);
  652. db_query('DELETE FROM {uc_auction_bids} WHERE nid = %d', $node->nid);
  653. module_invoke_all('auc_remove', $node, TRUE);
  654. }
  655. elseif ($op === 'load') {
  656. // Okay. It would be awesome to do this in a single query, like:
  657. // SELECT ua.*, uab.uid AS high_bid_uid, uab.amount AS high_bid_amt,
  658. // COUNT(uab.bid) AS bid_count FROM {uc_auction} ua LEFT JOIN
  659. // {uc_auction_bids} uab ON ua.nid = uab.nid GROUP BY uab.nid ORDER BY
  660. // uab.time DESC
  661. // …and this ALMOST works, but inexplicably the high_bid_uid and
  662. // high_bid_amt values are set to the FIRST bid, not the most recent or
  663. // highest (the ORDER BY clause is seemingly being ignored), in MySQL
  664. // anyway (lowest common denominator, I know). If anyone smarter than me
  665. // can figure out how to do this without a subquery, enlighten me. For
  666. // now;
  667. if ($auc = db_fetch_array(db_query('SELECT ua.*, uab.uid AS high_bid_uid, uab.amount AS high_bid_amt, (SELECT COUNT(*) FROM {uc_auction_bids} WHERE nid = %d) as bid_count FROM {uc_auction} ua LEFT JOIN {uc_auction_bids} uab ON ua.high_bid = uab.bid WHERE ua.nid = %d', $node->nid, $node->nid))) {
  668. foreach (array('start_price', 'bid_increment', 'min_increase', 'max_increase', 'max_increase_pctg') as $key) {
  669. if ($auc[$key] !== NULL) {
  670. $auc[$key] = floatval($auc[$key]);
  671. }
  672. }
  673. if (!$auc['high_bid']) {
  674. $auc['high_bid_amt'] = $auc['start_price'];
  675. } else {
  676. /* workaround for fixing false
  677. * bid display
  678. */
  679. $highest_bid_data = db_query("SELECT MAX(amount) AS amount, bid, uid FROM {uc_auction_bids} WHERE nid = '%s'" , $node->nid);
  680. $highest_bid_data = db_fetch_object($highest_bid_data);
  681. $auc['high_bid_amt'] = $highest_bid_data->amount;
  682. }
  683. // We're calculating these bid limits here so that other modules can
  684. // override them in their on hook_nodeapi()s later.
  685. $auc['min_bid'] = $auc['high_bid_amt'] + ($auc['min_increase'] !== NULL ? $auc['min_increase'] : variable_get('uc_auction_min_increase', .5));
  686. if ($auc['max_inc'] === NULL) {
  687. $auc['max_inc'] = variable_get('uc_auction_max_increase', 1000);
  688. }
  689. if ($auc['max_inc_pctg'] === NULL) {
  690. $auc['max_inc_pctg'] = variable_get('uc_auction_max_increase_pctg', 100);
  691. }
  692. // A max_bid of 0 means no limit
  693. $auc['max_bid'] = 0;
  694. if ($auc['max_increase']) {
  695. $auc['max_bid'] = $auc['high_bid_amt'] + $auc['max_increase'];
  696. }
  697. if ($auc['max_increase_pctg'] && $auc['high_bid_amt'] > 0) {
  698. // Percentage math. Funky. On zero, it will always equal zero, so skip it
  699. // in that case.
  700. $max_inc_pctg_appl = $auc['high_bid_amt'] * (($auc['max_increase_pctg'] / 100) + 1);
  701. // If $max_bid is still 0 OR this value is less than the current $max_bid…
  702. if (!$auc['max_bid'] || $max_inc_pctg_appl < $auc['max_bid']) {
  703. $auc['max_bid'] = $max_inc_pctg_appl;
  704. }
  705. }
  706. $node->uc_auction = $auc;
  707. }
  708. }
  709. elseif ($op === 'view' && isset($node->uc_auction)) {
  710. // Keep defaults in synch with the variable_get() in hook_form_alter()
  711. $fields = variable_get('uc_auction_field_settings', array(
  712. 'uc_auction_box' => array(
  713. 'enabled' => TRUE,
  714. 'weight' => -3,
  715. ),
  716. ));
  717. if ($fields['uc_auction_box']['enabled']) {
  718. $node->content['uc_auction'] = array(
  719. '#value' => drupal_get_form('uc_auction_bid_table_form', $node, $a3),
  720. '#weight' => $fields['uc_auction_box']['weight'],
  721. );
  722. }
  723. if (variable_get('uc_auction_hide_prices', TRUE)) {
  724. unset($node->content['display_price']);
  725. unset($node->content['list_price']);
  726. unset($node->content['sell_price']);
  727. }
  728. if ($a4) {
  729. // Check to see if the user has bid on this in the past
  730. global $user;
  731. if (db_result(db_query('SELECT nid FROM {uc_auction_bids} WHERE nid = %d && uid = %d', $node->nid, $user->uid))) {
  732. $message = NULL;
  733. $type = 'status';
  734. $result = module_invoke_all('auc_message', $node);
  735. if (!in_array(FALSE, $result, TRUE)) {
  736. if ($node->uc_auction['bid_count'] && $node->uc_auction['high_bid_uid'] == $user->uid) {
  737. if (time() >= $node->uc_auction['expiry']) {
  738. if ($node->uc_auction['purchased']) {
  739. drupal_set_message(t('You have purchased this auction item.'));
  740. }
  741. else {
  742. if(module_exists('uc_auction_min_price')){
  743. message_on_auction_end($node->nid);
  744. } else {
  745. drupal_set_message(t('Congratulations! You have won the auction for this item.'));
  746. }
  747. }
  748. }
  749. else {
  750. drupal_set_message(t('Congratulations. You are currently the high bidder for this item.'));
  751. }
  752. }
  753. else {
  754. if (time() > $node->uc_auction['expiry']) {
  755. drupal_set_message(t('This auction has expired, and you were not the final bidder. Better luck next time!'), 'warning');
  756. }
  757. else {
  758. drupal_set_message(t('You are no longer the high bidder for the item. You must place a higher bid if you wish to win this auction.'), 'warning');
  759. }
  760. }
  761. }
  762. }
  763. }
  764. }
  765. }
  766. }
  767. /**
  768. * Implementation of hook_theme().
  769. */
  770. function uc_auction_theme($existing, $type, $theme, $path) {
  771. return array(
  772. 'uc_auction_bid_table' => array(
  773. 'arguments' => array('form' => NULL),
  774. ),
  775. );
  776. }
  777. // every user will be notified
  778. /**
  779. * Implementation of hook_user().
  780. */
  781. /*
  782. function uc_auction_user($op, &$edit, &$account, $category = NULL) {
  783. if ((($op === 'form' && $category === 'account') || $op === 'register') && variable_get('uc_auction_notify_outbid', TRUE)) {
  784. return array(
  785. 'uc_auction_settings' => array(
  786. '#type' => 'fieldset',
  787. '#title' => t('Auction settings'),
  788. '#weight' => 4,
  789. 'uc_auction_notify_outbid' => array(
  790. '#type' => 'checkbox',
  791. '#title' => t('Notify me by e-mail when I&rsquo;m outbid on an auction.'),
  792. '#default_value' => isset($account->uc_auction_notify_outbid) ? $account->uc_auction_notify_outbid : TRUE,
  793. ),
  794. ),
  795. );
  796. }
  797. }
  798. */
  799. /**
  800. * Implementation of hook_cron().
  801. */
  802. /*
  803. function uc_auction_cron() {
  804. $time = time();
  805. // Find all the auctions which have been won recently.
  806. $rez = db_query('SELECT nid FROM {uc_auction} WHERE notified = 0 && expiry < %d', $time);
  807. while ($nid = db_fetch_object($rez)) {
  808. // Invoke hook_auc_expired(). We're only going to pass the nid and
  809. // not the actual node because there's no use loading the node if there's
  810. // not actually any hooks implemented and notifications are turned off.
  811. module_invoke_all('auc_expired', $nid->nid);
  812. // On the other hand, if notifications *are* enabled…
  813. if (variable_get('uc_auction_notify_win', TRUE)) {
  814. member_billing();
  815. // …we need to do some loading.
  816. $node = node_load($nid->nid);
  817. $high_user = user_load($node->uc_auction['high_bid_uid']);
  818. if ($high_user->uid) {
  819. drupal_mail('uc_auction', 'uc_auction_notify_win', $high_user->mail, user_preferred_language($high_user), array('node' => $node, 'user' => $high_user));
  820. watchdog('uc auction', 'Auction won notification for !item sent to @user.', array('@user' => $high_user->name, '!item' => l($node->title, "node/{$node->nid}")));
  821. }
  822. else {
  823. watchdog('uc auction', 'Auction for !item expired; no or anonymous winner. No notification sent.', array('!item' => l($node->title, "node/{$node->nid}")));
  824. }
  825. }
  826. }
  827. // Set all as having been notified. Note that we're setting this value even if
  828. // won auction notifications are disabled. That way, if they're enabled in the
  829. // future, people who have won auctions in the past won't suddenly receive
  830. // notifications about it. Also, we'll know that we've already called the
  831. // expired hook on it.
  832. db_query('UPDATE {uc_auction} SET notified = 1 WHERE notified = 0 && expiry < %d', $time);
  833. }
  834. */
  835. /**
  836. * Implementation of hook_mail().
  837. */
  838. function uc_auction_mail($key, &$message, $params) {
  839. if ($key === 'uc_auction_notify_win') {
  840. // The "you've won an auction" notification
  841. $message['body'] = token_replace_multiple(
  842. variable_get('uc_auction_notify_win_msg', uc_get_message('uc_auction_notify_win_msg')),
  843. array('global' => NULL, 'node' => $params['node'], 'auction' => $params['node'])
  844. // Is this supposed to ^^^^ be 'product' instead of 'node' as it is
  845. // below?
  846. );
  847. $message['subject'] = token_replace_multiple(
  848. variable_get('uc_auction_notify_win_subj', uc_get_message('uc_auction_notify_win_subj')),
  849. array('global' => NULL, 'product' => $params['node'], 'auction' => $params['node'])
  850. );
  851. }
  852. elseif ($key === 'uc_auction_notify_outbid') {
  853. // The "you were outbid" notification
  854. $message['body'] = token_replace_multiple(
  855. variable_get('uc_auction_notify_outbid_msg', uc_get_message('uc_auction_notify_outbid_msg')),
  856. array('global' => NULL, 'node' => $params['node'], 'auction' => $params['node'])
  857. );
  858. $message['subject'] = token_replace_multiple(
  859. variable_get('uc_auction_notify_outbid_subj', uc_get_message('uc_auction_notify_outbid_subj')),
  860. array('global' => NULL, 'product' => $params['node'], 'auction' => $params['node'])
  861. );
  862. }
  863. }
  864. /* drupal_get_form() callbacks ********************************************** */
  865. /**
  866. * Describe the bid form table.
  867. *
  868. * This produces a table with basic information about the auctioned item
  869. * (current high bid, number of bids, time left before/after expiry). If the
  870. * node is not being viewed as a teaser, it also adds JavaScript to count down
  871. * the remaining time (if so configured) and adds controls users will use to
  872. * place a bid, if they have permission to do so.
  873. *
  874. * @param $form_state
  875. * The obligatory $form_state parameter.
  876. * @param $node
  877. * The node object to build a form for.
  878. * @param $teaser
  879. * Are we looking at a teaser?
  880. * @return
  881. * The form array.
  882. */
  883. function uc_auction_bid_table_form(&$form_state, $node, $teaser) {
  884. $form = array(
  885. '#node' => $node,
  886. '#teaser' => $teaser,
  887. '#theme' => 'uc_auction_bid_table',
  888. 'nid' => array(
  889. '#type' => 'value',
  890. '#value' => $node->nid,
  891. ),
  892. 'bid_count' => array(
  893. '#title' => t('Bids'),
  894. '#type' => 'item',
  895. '#value' => user_access('view bids') ? l($node->uc_auction['bid_count'], "node/{$node->nid}/bids", array('title' => t('See bid history for this item'))) : $node->uc_auction['bid_count'],
  896. '#weight' => 0,
  897. ),
  898. 'high_bid' => array(
  899. '#title' => t('High bid'),
  900. '#type' => 'item',
  901. '#value' => $node->uc_auction['bid_count'] ? uc_currency_format($node->uc_auction['high_bid_amt']) : uc_currency_format($node->uc_auction['start_price']),
  902. '#weight' => 2,
  903. ),
  904. );
  905. $time = time();
  906. if ($node->uc_auction['expiry'] >= $time) {
  907. $open = TRUE;
  908. $in = $node->uc_auction['expiry'] - $time;
  909. $form['expiry'] = array(
  910. '#title' => t('Expires in'),
  911. '#type' => 'item',
  912. '#value' => format_interval($in, variable_get('uc_auction_time_gran', 2)),
  913. '#weight' => 4,
  914. );
  915. if ($in < 60) {
  916. // This minute
  917. $form['expiry']['#attributes'] = array('class' => 'uc-auction-expiry-min');
  918. }
  919. elseif ($in < 3600) {
  920. // This hour
  921. $form['expiry']['#attributes'] = array('class' => 'uc-auction-expiry-hour');
  922. }
  923. elseif ($in < 86400) {
  924. // In 24 h
  925. $form['expiry']['#attributes'] = array('class' => 'uc-auction-expiry-day');
  926. }
  927. }
  928. /* TODO here is the expiry from. */
  929. else {
  930. $open = FALSE;
  931. $form['expiry'] = array(
  932. '#title' => t('Expired'),
  933. '#type' => 'item',
  934. '#value' => t('@time ago', array('@time' => format_interval($time - $node->uc_auction['expiry'], variable_get('uc_auction_time_gran', 2)))),
  935. '#attributes' => array('class' => 'uc-auction-expiry-expired'),
  936. '#weight' => 4,
  937. );
  938. }
  939. if ($open && !$teaser) {
  940. // The user can place a bid.
  941. $form['max_bid'] = array(
  942. '#type' => 'value',
  943. '#value' => $node->uc_auction['max_bid'],
  944. );
  945. $form['bid_increment'] = array(
  946. '#type' => 'value',
  947. '#value' => $node->uc_auction['bid_increment'] === NULL ? variable_get('uc_auction_bid_increment', .25) : $node->uc_auction['bid_increment'],
  948. );
  949. drupal_add_js(array(
  950. 'ucAuction' => array(
  951. 'minBid' => $node->uc_auction['min_bid'],
  952. 'minBidF' => uc_currency_format($node->uc_auction['min_bid']),
  953. 'maxBid' => $node->uc_auction['max_bid'],
  954. 'maxBidF' => uc_currency_format($node->uc_auction['max_bid']),
  955. // The NoSign values will be filled in to the bid value field if the
  956. // user tries to surpass one of those limits.
  957. 'minBidFNoSign' => uc_currency_format($node->uc_auction['min_bid'], FALSE),
  958. 'maxBidFNoSign' => uc_currency_format($node->uc_auction['max_bid'], FALSE),
  959. 'bidIncrement' => $form['bid_increment']['#value'],
  960. 'bidIncrementF' => uc_currency_format($form['bid_increment']['#value']),
  961. // JavaScript wants to use milliseconds for its time functions, but if
  962. // we try to just set the expiry as $node->uc_auction['expiry'] * 1000,
  963. // the time comes out on the JS end in exponential notation, which is
  964. // not what we want. (Or, at least, that's what's happening on my local
  965. // machine at work.) So we're going to pass it as a normal Unix
  966. // timestamp in seconds and do the conversion to milliseconds on the JS
  967. // side.
  968. // Oh yeah… let's try to convert it to UTC too.
  969. 'expiry' => $node->uc_auction['expiry'] + variable_get('date_default_timezone', 0),
  970. 'timeGran' => intval(variable_get('uc_auction_time_gran', 2)),
  971. 'doCountdown' => variable_get('uc_auction_countdown', TRUE),
  972. 'currencyDec' => variable_get('uc_currency_dec', '.'),
  973. 'currencyThou' => variable_get('uc_currency_thou', ','),
  974. ),
  975. ), 'setting');
  976. drupal_add_js(drupal_get_path('module', 'uc_auction') . '/uc_auction.timers.js', 'module', 'footer');
  977. drupal_add_js(drupal_get_path('module', 'uc_auction') . '/uc_auction.js', 'module', 'footer');
  978. // @TODO: The below is important and deserves review
  979. global $user;
  980. if (user_access('place bid')) {
  981. if ($node->uc_auction['bid_count'] && $user->uid == $node->uc_auction['high_bid_uid']) {
  982. $form['cant_bid'] = array(
  983. '#type' => 'item',
  984. '#description' => t('You are the current high bidder on this item. You may not place a bid against yourself.'),
  985. '#weight' => 6,
  986. );
  987. }
  988. elseif ($user->uid == $node->uid) {
  989. $form['cant_bid'] = array(
  990. '#type' => 'item',
  991. '#description' => t('You may not bid on your own items.'),
  992. '#weight' => 6,
  993. );
  994. }
  995. else {
  996. $form['user_bid'] = array(
  997. '#title' => t('Bid value'),
  998. '#type' => 'textfield',
  999. '#size' => 12,
  1000. '#weight' => 6,
  1001. );
  1002. if (variable_get('uc_sign_after_amount', FALSE)) {
  1003. $form['user_bid']['#field_suffix'] = variable_get('uc_currency_sign', '$');
  1004. }
  1005. else {
  1006. $form['user_bid']['#field_prefix'] = variable_get('uc_currency_sign', '$');
  1007. }
  1008. $form['submit'] = array(
  1009. '#type' => 'submit',
  1010. '#value' => t('Place bid'),
  1011. '#description' => t('You must bid at least @minbid<br />in increments of @inc', array('@minbid' => uc_currency_format($node->uc_auction['min_bid']), '@inc' => uc_currency_format($form['bid_increment']['#value']))),
  1012. '#weight' => 8,
  1013. );
  1014. }
  1015. }
  1016. elseif (!$user->uid) {
  1017. // User doesn't have 'place bid' permission. The below message isn't
  1018. // entirely accurate since it's not guaranteed they will be given this
  1019. // permission if they log in, but whatcha gonna do?
  1020. $form['cant_bid'] = array(
  1021. '#type' => 'item',
  1022. '#description' => t('<a href="@log-in">Log in</a> or <a href="@reg">register</a> to place a bid.', array('@log-in' => url('user/login', array('query' => array('destination' => 'node/' . $node->nid))), '@reg' => url('user/register', array('query' => array('destination' => 'node/' . $node->nid))))),
  1023. );
  1024. }
  1025. }
  1026. //if(module_exists('uc_auction_time_controlled_publish')){
  1027. //}
  1028. return $form;
  1029. }
  1030. /**
  1031. * Theme the bid table.
  1032. *
  1033. * @param $form
  1034. * The form to theme.
  1035. * @returr
  1036. * The themed form.
  1037. */
  1038. function theme_uc_auction_bid_table($form) {
  1039. drupal_add_css(drupal_get_path('module', 'uc_auction') . '/uc_auction.css');
  1040. // This will all make sense in a minute.
  1041. $sp_t = $form['start_price']['#title'];
  1042. unset($form['start_price']['#title']);
  1043. $bc_t = $form['bid_count']['#title'];
  1044. unset($form['bid_count']['#title']);
  1045. $hb_t = $form['high_bid']['#title'];
  1046. unset($form['high_bid']['#title']);
  1047. $ex_t = $form['expiry']['#title'];
  1048. unset($form['expiry']['#title']);
  1049. if (isset($form['user_bid'])) {
  1050. $ub_t = $form['user_bid']['#title'];
  1051. unset($form['user_bid']['#title']);
  1052. }
  1053. $rows = array(
  1054. array( // tr
  1055. array( // th
  1056. 'header' => TRUE,
  1057. 'data' => $hb_t,
  1058. 'class' => 'uc-auction-high-bid-hdr',
  1059. ),
  1060. array( // td
  1061. 'data' => drupal_render($form['high_bid']),
  1062. 'class' => 'uc-auction-high-bid display_price',
  1063. ),
  1064. ),
  1065. array( // tr
  1066. array( // th
  1067. 'header' => TRUE,
  1068. 'data' => $bc_t,
  1069. 'class' => 'uc-auction-bid-count-hdr',
  1070. ),
  1071. array( // td
  1072. 'data' => drupal_render($form['bid_count']),
  1073. 'class' => 'uc-auction-bid-count',
  1074. ),
  1075. ),
  1076. array( // tr
  1077. array( // th
  1078. 'header' => TRUE,
  1079. 'data' => $ex_t,
  1080. 'class' => 'uc-auction-expiry-hdr',
  1081. ),
  1082. array( // td
  1083. 'data' => drupal_render($form['expiry']),
  1084. 'class' => count($form['expiry']['#attributes']) ? 'uc-auction-expiry ' . implode(' ', $form['expiry']['#attributes']) : 'uc-auction-expiry',
  1085. ),
  1086. ),
  1087. );
  1088. if (isset($form['user_bid'])) {
  1089. $rows[] = array( // tr
  1090. array( // th
  1091. 'header' => TRUE,
  1092. 'data' => $ub_t,
  1093. 'class' => 'uc-auction-user-bid-hdr',
  1094. ),
  1095. array( // td
  1096. 'data' => drupal_render($form['user_bid']),
  1097. 'class' => 'uc-auction-user-bid',
  1098. ),
  1099. );
  1100. $rows[] = array( // tr
  1101. array( // td
  1102. 'data' => drupal_render($form['submit']) . drupal_render($form['form_build_id']) . drupal_render($form['form_token']) . drupal_render($form['form_id']) . '<div class="description">' . $form['submit']['#description'] . '</div>',
  1103. 'class' => 'uc-auction-user-bid-submit',
  1104. 'colspan' => 2,
  1105. ),
  1106. );
  1107. }
  1108. elseif (isset($form['cant_bid'])) {
  1109. $rows[] = array( // tr
  1110. array( // td
  1111. 'data' => drupal_render($form['cant_bid']),
  1112. 'class' => 'uc-auction-user-bid-submit',
  1113. 'colspan' => 2,
  1114. ),
  1115. );
  1116. }
  1117. return theme('table', array(), $rows, array('class' => 'uc-auction-bid-table'));
  1118. }
  1119. /**
  1120. * Validate placed bids.
  1121. */
  1122. function uc_auction_bid_table_form_validate($form, &$form_state) {
  1123. // fetch min-bid
  1124. $db_data = db_query("SELECT MAX(amount) as amount FROM {uc_auction_bids} WHERE nid = '%s'" , $form_state['values']['nid']);
  1125. $db_data = db_fetch_object($db_data);
  1126. // TODO: Check that the submitted bid value will fit in the DB?
  1127. $form_state['values']['user_bid'] = _uc_auction_uncurrency($form_state['values']['user_bid']);
  1128. $node = node_load($form_state['values']['nid']);
  1129. // Note that these checks were made client-side if the user has JavaScript
  1130. // enabled, but relying on client-side checks is dee-you-double-em dumb.
  1131. // Is the bid value above the minimum value?
  1132. if (time() > $node->uc_auction['expiry']) {
  1133. form_set_error('submit', t('Sorry, but this auction has expired. You may no longer place bids on this item.'));
  1134. }
  1135. // Is the bid value below the minimum bid value?
  1136. elseif ($form_state['values']['user_bid'] < $db_data->amount) {
  1137. form_set_error('user_bid', t('The current minimum bid value is %val.', array('%val' => uc_currency_format($node->uc_auction['min_bid']))));
  1138. }
  1139. // Is the bid value above the maximum bid value? Note that if max_bid is zero,
  1140. // we're ignoring this check.
  1141. elseif ($form_state['values']['max_bid'] && $form_state['values']['user_bid'] > $form_state['values']['max_bid']) {
  1142. form_set_error('user_bid', t('The current maximum bid value is %val.', array('%val' => uc_currency_format($form_state['values']['max_bid']))));
  1143. }
  1144. elseif((variable_get('uc_auction_max_increase', 1000) + intval($db_data->amount) + 1) < intval($form_state['values']['user_bid'])) {
  1145. form_set_error('user_bid', t('The current maximum bid increase is '. (variable_get('uc_auction_max_increase', 1000) + intval($db_data->amount)) .'.', array('%val' => uc_currency_format(variable_get('uc_auction_max_increase', 1000)))));
  1146. }
  1147. // Is the bid value a multiple of the bid increment value?
  1148. elseif (!_uc_auction_mod_zero($form_state['values']['user_bid'], $form_state['values']['bid_increment'])) {
  1149. form_set_error('user_bid', t('Your bid must be a a multiple of @inc to be accepted. Try bidding @bid instead.', array('@inc' => uc_currency_format($form_state['values']['bid_increment']), '@bid' => uc_currency_format(ceil($form_state['values']['user_bid'] / $form_state['values']['bid_increment']) * $form_state['values']['bid_increment']))));
  1150. }
  1151. }
  1152. /**
  1153. * Submit placed bids.
  1154. */
  1155. function uc_auction_bid_table_form_submit($form, &$form_state) {
  1156. global $user;
  1157. // Prepare stuff to be potentially altered, then saved
  1158. $node = node_load($form_state['values']['nid']);
  1159. $bid_record = array(
  1160. 'nid' => $form_state['values']['nid'],
  1161. 'uid' => $user->uid,
  1162. 'time' => time(),
  1163. 'amount' => $form_state['values']['user_bid'],
  1164. );
  1165. //check here, if the highest saved bid is outbid. then send mail.
  1166. $rez = db_query('SELECT amount FROM {uc_auction_highest_bids} WHERE nid = %d && amount > %d', $form_state['values']['nid'], $form_state['values']['user_bid']);
  1167. $bid = db_fetch_array($rez);
  1168. if(empty($bid['amount'])){
  1169. $outbid = $node->uc_auction['high_bid_uid'];
  1170. }
  1171. // Invoke hook_uc_auction_accept_bid(&$node, &$bid_record)
  1172. $response = module_invoke_all('bid_alter', $node, $bid_record);
  1173. // If any of the hook functions returned false, we're not going to save the
  1174. // data to the database OR send the outgoing mail notification.
  1175. // uncommented, because $response was always false..
  1176. //if (!in_array(FALSE, $response)) {
  1177. /*
  1178. * TODO THIS IS THE NORMAL INSERT BID FUNCTION, OF THE UC_AUCTION MODULE. DURING A WIRED BUG, THIS
  1179. * FUNCTION IS UNCOMMENTED, BECAUSE OF OVERWRITING THE BIDS FROM THE UC_AUCTION_AUTOMATED_BIDDING
  1180. * MODULE. TESTED IF THE WEIGHT IN THE SYSTEMS TABLE IS CAUSING THIS ERROR, BUT NOT. MAKE AUTOMATED
  1181. * BIDDING MODULE REQUIRED FOR UC-AUCTION!
  1182. */
  1183. //uc_auction_insert_bid($bid_record);
  1184. // Do we want to notify the outbid user?
  1185. if (variable_get('uc_auction_notify_outbid', TRUE) && $outbid != 0) {
  1186. $outbid_user = user_load($outbid);
  1187. if (!isset($outbid_user->uc_auction_notify_outbid) || $outbid_user->uc_auction_notify_outbid) {
  1188. $node->uc_auction['high_bid_amt'] = $form_state['values']['user_bid'];
  1189. drupal_mail('uc_auction', 'uc_auction_notify_outbid', $outbid_user->mail, user_preferred_language($outbid_user), array('node' => $node, 'user' => $outbid_user));
  1190. watchdog('uc auction', 'Outbid notification for !item sent to @user.', array('@user' => $outbid_user->name, '!item' => l($node->title, "node/{$node->nid}")));
  1191. }
  1192. }
  1193. //}
  1194. }
  1195. /**
  1196. * Properly inserts bids into the database.
  1197. *
  1198. * Note that this function does NOT do any validation. Data should be validated
  1199. * to assure that the user is capable of placing this bid before it is passed
  1200. * to this function.
  1201. *
  1202. * @param $bid_record
  1203. * An array primed to be inserted into the bid database via
  1204. * drupal_write_record().
  1205. * @param $auc_record
  1206. * An optional array of values to be updated on the auction record.
  1207. */
  1208. function uc_auction_insert_bid($bid_record, $auc_record = array()) {
  1209. drupal_write_record('uc_auction_bids', $bid_record);
  1210. $auc_record += array(
  1211. // had always 1 at the end of the number - this is a workaround
  1212. 'bid' => $bid_record['bid'] - 1,
  1213. 'nid' => $bid_record['nid'],
  1214. 'high_bid' => $bid_record['bid'],
  1215. );
  1216. drupal_write_record('uc_auction', $auc_record, 'nid');
  1217. }
  1218. /**
  1219. * Confirm bid deletion.
  1220. *
  1221. * Bids are identified by the nid of the node the bid is on, and the timestamp
  1222. * of the bid. Since it's entirely possible for two bids for the same product to
  1223. * have been accepted within the same second, this code fails it. We're going to
  1224. * have to add a serial number for bids.
  1225. *
  1226. * @param $node
  1227. * The node object whose bid(s) will be deleted.
  1228. * @param $ts
  1229. * The timestamp of the bid to be deleted.
  1230. * @return
  1231. * The confirmation form to delete the bids.
  1232. */
  1233. function uc_auction_bid_del_conf(&$form_state, $node, $bid) {
  1234. $form = array(
  1235. 'nid' => array(
  1236. '#type' => 'value',
  1237. '#value' => $node->nid,
  1238. ),
  1239. 'bid' => array(
  1240. '#type' => 'value',
  1241. '#value' => $bid,
  1242. ),
  1243. );
  1244. return confirm_form($form, t('Are you sure you want to delete those bids?'), "node/{$node->nid}/bids");
  1245. }
  1246. /**
  1247. * Delete bids.
  1248. */
  1249. function uc_auction_bid_del_conf_submit($form, &$form_state) {
  1250. // Find out the bid IDs of the bids to be baleeted.
  1251. $to_delete = array();
  1252. $rez = db_query('SELECT bid FROM {uc_auction_bids} WHERE nid = %d && bid >= %d', $form_state['values']['nid'], $form_state['values']['bid']);
  1253. while ($bid = db_fetch_array($rez)) {
  1254. $to_delete[] = intval($bid['bid']);
  1255. }
  1256. $node = node_load($form_state['values']['nid']);
  1257. // Call hook_delete_bids
  1258. $response = module_invoke_all('delete_bids', $node, $to_delete);
  1259. if (!in_array(FALSE, $response)) {
  1260. // This sucks, but if I try to do something like
  1261. // array($node->nid) + $to_delete values get overwritten and stuff.
  1262. $params = $to_delete;
  1263. array_unshift($params, $node->nid);
  1264. // Delete bids from the DB
  1265. db_query('DELETE FROM {uc_auction_bids} WHERE nid = %d && bid IN (' . db_placeholders($to_delete) . ')', $params);
  1266. // Are there any bids left?
  1267. $max = db_result(db_query('SELECT MAX(bid) AS bid FROM {uc_auction_bids} WHERE nid = %d', $node->nid));
  1268. // Update uc_auction
  1269. $auc_record = array(
  1270. 'nid' => $node->nid,
  1271. 'high_bid' => $max['bid'],
  1272. // $max['bid'] may be FALSE, which will be inserted as 0 (which is what we
  1273. // want).
  1274. );
  1275. drupal_write_record('uc_auction', $auc_record, 'nid');
  1276. drupal_set_message(t('The bids were deleted and the high bid price was reset to the latest undeleted bid (or the initial start price if all bids were deleted).'));
  1277. }
  1278. drupal_goto("node/{$form_state['values']['nid']}/bids");
  1279. }
  1280. /* Menu callbacks *********************************************************** */
  1281. /**
  1282. * More menu callbacks in uc_auction.admin.inc and uc_auction.user.inc!
  1283. */
  1284. /**
  1285. * List bids.
  1286. * @param $node
  1287. * The product to show bids for.
  1288. * @return
  1289. * A themed table of bids.
  1290. */
  1291. function uc_auction_bid_history($node) {
  1292. $rows = array();
  1293. $del = user_access('delete bids');
  1294. $full = user_access('view full bid info');
  1295. $rez = db_query('(SELECT * FROM {uc_auction_bid_log} WHERE nid = "%s" AND amount <= (SELECT amount FROM uc_auction_bids WHERE nid = "%s" ORDER BY amount DESC LIMIT 1)) UNION (SELECT DISTINCT * FROM uc_auction_bids WHERE nid = "%s") ORDER BY amount DESC', $node->nid, $node->nid, $node->nid);
  1296. global $user;
  1297. while ($bid = db_fetch_array($rez)) {
  1298. if(variable_get('uc_auction_annonomized_bidder_display', FALSE) !== 1){
  1299. if ($bid['uid'] == $user->uid && variable_get('uc_auction_annonomized_bidder_display', FALSE) !== '1') {
  1300. $row = array(theme('username', $user));
  1301. }
  1302. elseif (isset($full)) {
  1303. $row = array(theme('username', user_load($bid['uid'])));
  1304. }
  1305. } elseif (isset($full) && variable_get('uc_auction_annonomized_bidder_display', FALSE) == '1' && !in_array('Admin', $user->roles)){
  1306. $bid_user = user_load($bid['uid']);
  1307. $bid_user->name = substr($bid_user->name, 0, 2) . '...' . substr($bid_user->name, -1, 1);
  1308. $row = array($bid_user->name);
  1309. } elseif(variable_get('uc_auction_annonomized_bidder_display', FALSE) == 1 && in_array('Admin', $user->roles)) {
  1310. $row = array(theme('username', user_load($bid['uid'])));
  1311. }
  1312. $row[] = t('@time ago', array('@time' => format_interval(time() - $bid['time'], variable_get('uc_auction_time_gran', 2))));
  1313. $row[] = uc_currency_format($bid['amount']);
  1314. if ($del) {
  1315. $row[] = l(t('Delete this and later bids'), "node/{$node->nid}/bids/delete/{$bid['bid']}");
  1316. }
  1317. $rows[] = $row;
  1318. }
  1319. if (count($rows) === 0) {
  1320. $rows[] = array(
  1321. array(
  1322. 'data' => t('No bids have been placed on this product.'),
  1323. 'colspan' => $del ? 4 : 3,
  1324. ),
  1325. );
  1326. }
  1327. $header = array(t('User'), t('Time'), t('Bid'));
  1328. if ($del) {
  1329. $header[] = t('Delete bids');
  1330. }
  1331. return theme('table', $header, $rows);
  1332. }
  1333. /* Permission callbacks ***************************************************** */
  1334. /**
  1335. * See if the user can view the bid history on a node.
  1336. *
  1337. * As not all nodes will even have bid history, this also checks to see if the
  1338. * node is in fact a product which is up for auction.
  1339. *
  1340. * @param $node
  1341. * The node.
  1342. * @return
  1343. * Whether the current user can see the node's bid history or not.
  1344. */
  1345. function uc_auction_bid_history_perm($node) {
  1346. return isset($node->uc_auction) && user_access('view bids');
  1347. }
  1348. /**
  1349. * See if the user can view a particular user's auction activity.
  1350. *
  1351. * @param $see_user
  1352. * The user whose activity will be seen.
  1353. * @return
  1354. * Whether the current user can see the activity or not.
  1355. */
  1356. function uc_auction_user_auctions_perm($see_user) {
  1357. global $user;
  1358. return $user->uid == $see_user->uid || user_access('administer users');
  1359. }
  1360. /* Non-hook helper functions ************************************************ */
  1361. /**
  1362. * Check if the remainder of two divisors is zero.
  1363. *
  1364. * PHP's standard modulus operator converts the parameters to integers before
  1365. * operating - not convenient when dealing with currency. This function will
  1366. * check to see if the first parameter can be cleanly divided by the second
  1367. * regardless of number type.
  1368. *
  1369. * @param $big
  1370. * The larger number to be divided.
  1371. * @param $small
  1372. * The smaller number to divide the larger number by. If NULL is passed, the
  1373. * function will use the uc_auction_bid_increment variable value.
  1374. * @return
  1375. * Whether this division occurs with no remainder. TRUE if yes.
  1376. */
  1377. function _uc_auction_mod_zero($big, $small = NULL) {
  1378. if ($small === NULL) {
  1379. $small = variable_get('uc_auction_bid_increment', .25);
  1380. }
  1381. $div = $big / $small;
  1382. if(!is_numeric(strpos($div, '.')) === true){
  1383. return true;
  1384. } else {
  1385. return false;
  1386. }
  1387. }
  1388. /**
  1389. * Check if a node's type is an Ubercart product type.
  1390. *
  1391. * hook_nodeapi() is called a lot, and each time it is, we want to check to see
  1392. * if the node in question is of a UC product type. Here's a helper function to
  1393. * do that which caches the product types since module_invoke_all() is
  1394. * expensive (I'm guessing).
  1395. *
  1396. * @param $node
  1397. * The node.
  1398. * @return
  1399. * Whether the node's type is an UC product type.
  1400. */
  1401. function _uc_auction_is_uc_type($node) {
  1402. static $uc_types = NULL;
  1403. static $is_type = array();
  1404. // We're going to cache the product types since module_invoke_all() is
  1405. // probably pretty expensive. uc_auction_nodeapi() is going to be called
  1406. // several times per node and each one of those calls is going to call
  1407. // this function.
  1408. if ($uc_types === NULL) {
  1409. $uc_types = module_invoke_all('product_types');
  1410. }
  1411. // We're also going to cache which nodes are of a product type. This is good
  1412. // if the page is going to show a lot of nodes.
  1413. if (!isset($is_type[$node->nid])) {
  1414. $is_type[$node->nid] = in_array($node->type, $uc_types);
  1415. }
  1416. return $is_type[$node->nid];
  1417. }
  1418. /**
  1419. * Converts a string which should contain a currency value into a float.
  1420. *
  1421. * Remove the thousands character (in case it is a period), convert the current
  1422. * uc_currency_dec character to a period (decimal point), strip out characters
  1423. * which aren't digits, periods or negative signs, then floatval() it.
  1424. *
  1425. * @param $val
  1426. * The currency value.
  1427. * @return
  1428. * The currency value as a float.
  1429. */
  1430. function _uc_auction_uncurrency($val) {
  1431. return floatval(preg_replace('/[^\d\.\-]/', '', str_replace(array(variable_get('uc_currency_thou', ','), variable_get('uc_currency_dec', '.')), array('', '.'), $val)));
  1432. }
  1433. /* Ubercart hooks *********************************************************** */
  1434. /**
  1435. * Ubercart's API documentation can be found at:
  1436. * http://www.ubercart.org/docs/api/
  1437. */
  1438. /**
  1439. * Implementation of hook_uc_message() (an Ubercart hook).
  1440. */
  1441. function uc_auction_uc_message() {
  1442. return array(
  1443. 'uc_auction_notify_win_subj' => t('You won "[auction-product-name]" at [store-name]!'),
  1444. 'uc_auction_notify_win_msg' => t("Congratulations!\n\nYou've won an auction at [store-name].\n\nProduct: [auction-product-name]\nWinning bid price: [formatted-price]\n\nTo purchase the product you've won, please go to the product page at the address below and use the \"Add to cart\" button to add it to your shopping cart. Then check out as normal. The product page is:\n[auction-product-url]\n\nIf you don't see the \"Add to cart\" button, you may need to log in first:\n[site-login-url]\n\nPlease ignore this message if you have already purchased this item.\n\nThanks for bidding at [store-name]!\n\n-- [store-owner]"),
  1445. // vars are not reaching the message
  1446. //'uc_auction_notify_outbid_subj' => t('You were outbid on "[auction-product-name]" at [store-name]'),
  1447. 'uc_auction_notify_outbid_msg' => t("You've been outbid on a product up for auction at [store-name].\n\nProduct: [auction-product-name]\nCurrent high bid: [formatted-price]\n(Note that higher bids may have been placed since this message was sent.)\n\nIf you're still interested in winning the auction for this product, head to the product page at the address below and place another bid:\n[auction-product-url]\n\nIf you cannot place a bid, you may need to log in first:\n[site-login-url]\n\nThanks for bidding at [store-name]! Good luck!\n\n -- [store-owner]\n\nIf you would prefer not to receive these notifications, log in to your user account at [store-name] and click the \"Edit\" tab. Then uncheck the \"Notify me by e-mail when I'm outbid on an auction\" check box.\n[site-login-url]"),
  1448. );
  1449. }
  1450. /**
  1451. * Implementation of hook_order() (an Ubercart hook).
  1452. */
  1453. function uc_auction_order($op, &$arg1, $arg2) {
  1454. if ($op === 'submit') {
  1455. $nids = array();
  1456. foreach ($arg1->products as $prod) {
  1457. $nids[] = $prod->nid;
  1458. }
  1459. // We'll lazily go ahead and dumb-update all of these. No harm if they're
  1460. // not actually auctioned products (and therefore not in the table).
  1461. db_query('UPDATE {uc_auction} SET purchased = 1 WHERE nid IN (' . db_placeholders($nids) . ')', $nids);
  1462. }
  1463. }
  1464. /**
  1465. * Implementation of hook_add_to_cart() (an Ubercart hook).
  1466. */
  1467. function uc_auction_add_to_cart($nid, $qty, $data) {
  1468. if (variable_get('uc_auction_force_one', TRUE)) {
  1469. $node = node_load($nid);
  1470. if (isset($node->uc_auction)) {
  1471. if ($qty > 1) {
  1472. return array(
  1473. array(
  1474. 'success' => FALSE,
  1475. 'message' => t('You may not add more than one of an auctioned item to your cart.'),
  1476. ),
  1477. );
  1478. }
  1479. foreach (uc_cart_get_contents() as $cart_item) {
  1480. if ($cart_item->nid === $nid) {
  1481. return array(
  1482. array(
  1483. 'success' => FALSE,
  1484. 'message' => t('You may not add more than one of an auctioned item to your cart.'),
  1485. ),
  1486. );
  1487. }
  1488. }
  1489. }
  1490. }
  1491. }
  1492. /**
  1493. * Implementation of hook_cart_item() (an Ubercart hook).
  1494. */
  1495. function uc_auction_cart_item($op, &$item) {
  1496. if ($op === 'load') {
  1497. if ($info = db_fetch_array(db_query('SELECT ua.high_bid, uab.amount FROM {uc_auction} ua LEFT JOIN {uc_auction_bids} uab ON ua.high_bid = uab.bid WHERE ua.nid = %d', $item->nid))) {
  1498. $item->sell_price = $item->price;
  1499. if ($info['amount'] !== NULL) {
  1500. $item->price = floatval($info['amount']);
  1501. }
  1502. $item->is_auc = TRUE;
  1503. }
  1504. else {
  1505. $item->is_auc = FALSE;
  1506. }
  1507. }
  1508. }
  1509. /* Token hooks ************************************************************** */
  1510. /**
  1511. * Documentation for Token's API can be found at:
  1512. * http://api.freestylesystems.co.uk/api/file/contributions/token/token.module/6
  1513. */
  1514. /**
  1515. * Implementation of hook_token_list() (a Token hook).
  1516. */
  1517. function uc_auction_token_list($type = 'all') {
  1518. return array(
  1519. 'auction' => array(
  1520. 'auction-winner-name' => t('The username of the auction winner.'),
  1521. 'auction-winner-uid' => t('The UID of the auction winner.'),
  1522. 'auction-product-url' => t('The URL of the item that was won.'),
  1523. 'auction-product-name' => t('The name of the item that was won.'),
  1524. 'site-login-url' => t('The URL of the site&rsquo;s log in page. (Just the URL; not an HTML link.)'),
  1525. 'formatted-price' => t('The formatted price of the item.'),
  1526. ),
  1527. );
  1528. }
  1529. /**
  1530. * Implementation of hook_token_values (a Token hook).
  1531. */
  1532. function uc_auction_token_values($type, $object = NULL) {
  1533. if ($type === 'auction') {
  1534. $winner = user_load($object->uc_auction['high_bid_uid']);
  1535. return array(
  1536. 'auction-winner-name' => $winner->name,
  1537. 'auction-winner-uid' => $winner->uid,
  1538. 'auction-product-url' => url('node/' . $object->nid, array('absolute' => TRUE)),
  1539. 'auction-product-name' => $object->title,
  1540. 'site-login-url' => url('user', array('absolute' => TRUE)),
  1541. 'formatted-price' => uc_currency_format($object->uc_auction['high_bid_amt']),
  1542. );
  1543. }
  1544. }
  1545. /* Views hooks ************************************************************** */
  1546. /**
  1547. * Documentation for Views' API is pretty much impossible to find in a format
  1548. * legible to mere mortals.
  1549. */
  1550. /**
  1551. * Implementation of hook_views_api().
  1552. *
  1553. * Thanks to pndur for some initial help wrapping my head around Views:
  1554. * http://drupal.org/node/316201
  1555. */
  1556. function uc_auction_views_api() {
  1557. return array(
  1558. 'api' => 2,
  1559. 'path' => drupal_get_path('module', 'uc_auction') . '/views',
  1560. );
  1561. }

Related topics