| 1 |
<?php
|
| 2 |
|
| 3 |
// $Id$
|
| 4 |
|
| 5 |
/**
|
| 6 |
* @file
|
| 7 |
* Create promotions with redeemable promotional codes that users can redeem to
|
| 8 |
* perform special actions in your store.
|
| 9 |
*/
|
| 10 |
|
| 11 |
|
| 12 |
/**
|
| 13 |
* Implementation of hook_menu().
|
| 14 |
*/
|
| 15 |
function uc_promo_menu($may_cache) {
|
| 16 |
$items = array();
|
| 17 |
|
| 18 |
if ($may_cache) {
|
| 19 |
$items[] = array(
|
| 20 |
'path' => 'promo',
|
| 21 |
'title' => t('Redeem a promotion'),
|
| 22 |
'description' => t('Form to redeem a promotional code.'),
|
| 23 |
'callback' => 'uc_promo_redeem',
|
| 24 |
'callback arguments' => array(''),
|
| 25 |
'access' => TRUE,
|
| 26 |
'type' => MENU_CALLBACK,
|
| 27 |
);
|
| 28 |
$items[] = array(
|
| 29 |
'path' => 'admin/store/settings/promo',
|
| 30 |
'title' => t('Promotions'),
|
| 31 |
'description' => t('Setup and administer your promotions.'),
|
| 32 |
'callback' => 'uc_promo_admin',
|
| 33 |
'access' => user_access('administer uc promotions'),
|
| 34 |
'type' => MENU_NORMAL_ITEM,
|
| 35 |
);
|
| 36 |
$items[] = array(
|
| 37 |
'path' => 'admin/store/settings/promo/overview',
|
| 38 |
'title' => t('Overview'),
|
| 39 |
'description' => t('Setup and administer your promotions.'),
|
| 40 |
'type' => MENU_DEFAULT_LOCAL_TASK,
|
| 41 |
'weight' => -10,
|
| 42 |
);
|
| 43 |
$items[] = array(
|
| 44 |
'path' => 'admin/store/settings/promo/add',
|
| 45 |
'title' => t('Add a promotion'),
|
| 46 |
'description' => t('Setup and administer your promotions.'),
|
| 47 |
'callback' => 'drupal_get_form',
|
| 48 |
'callback arguments' => array('uc_promo_promotion_form', 0),
|
| 49 |
'access' => user_access('administer uc promotions'),
|
| 50 |
'type' => MENU_LOCAL_TASK,
|
| 51 |
'weight' => 0,
|
| 52 |
);
|
| 53 |
$items[] = array(
|
| 54 |
'path' => 'admin/store/settings/promo/settings',
|
| 55 |
'title' => t('Settings'),
|
| 56 |
'description' => t('Adjust the general promotions settings.'),
|
| 57 |
'callback' => 'drupal_get_form',
|
| 58 |
'callback arguments' => array('uc_promo_admin_form'),
|
| 59 |
'access' => user_access('administer uc promotions'),
|
| 60 |
'type' => MENU_LOCAL_TASK,
|
| 61 |
'weight' => 10,
|
| 62 |
);
|
| 63 |
}
|
| 64 |
else {
|
| 65 |
if (arg(3) === 'promo' && intval(arg(4)) > 0) {
|
| 66 |
$items[] = array(
|
| 67 |
'path' => 'admin/store/settings/promo/'. arg(4) .'/edit',
|
| 68 |
'title' => t('Edit promotion'),
|
| 69 |
'description' => t('Delete an existing promotion.'),
|
| 70 |
'callback' => 'drupal_get_form',
|
| 71 |
'callback arguments' => array('uc_promo_promotion_form', arg(4)),
|
| 72 |
'access' => user_access('administer uc promotions'),
|
| 73 |
'type' => MENU_CALLBACK,
|
| 74 |
);
|
| 75 |
$items[] = array(
|
| 76 |
'path' => 'admin/store/settings/promo/'. arg(4) .'/delete',
|
| 77 |
'title' => t('Delete promotion'),
|
| 78 |
'description' => t('Delete a promotion.'),
|
| 79 |
'callback' => 'drupal_get_form',
|
| 80 |
'callback arguments' => array('uc_promo_delete_promotion_form', arg(4)),
|
| 81 |
'access' => user_access('administer uc promotions'),
|
| 82 |
'type' => MENU_CALLBACK,
|
| 83 |
);
|
| 84 |
|
| 85 |
if (arg(5) === 'codes') {
|
| 86 |
$items[] = array(
|
| 87 |
'path' => 'admin/store/settings/promo/'. arg(4) .'/codes',
|
| 88 |
'title' => t('Promotional codes'),
|
| 89 |
'description' => t('Administer promotional codes for a given promotion.'),
|
| 90 |
'callback' => 'uc_promo_codes',
|
| 91 |
'callback arguments' => array(arg(4)),
|
| 92 |
'access' => user_access('administer uc promotions'),
|
| 93 |
'type' => MENU_CALLBACK,
|
| 94 |
);
|
| 95 |
$items[] = array(
|
| 96 |
'path' => 'admin/store/settings/promo/'. arg(4) .'/codes/overview',
|
| 97 |
'title' => t('Overview'),
|
| 98 |
'description' => t('Administer promotional codes for a given promotion.'),
|
| 99 |
'type' => MENU_DEFAULT_LOCAL_TASK,
|
| 100 |
'weight' => -10,
|
| 101 |
);
|
| 102 |
$items[] = array(
|
| 103 |
'path' => 'admin/store/settings/promo/'. arg(4) .'/codes/add',
|
| 104 |
'title' => t('Add code'),
|
| 105 |
'description' => t('Add a promotional code for the promotion.'),
|
| 106 |
'callback' => 'drupal_get_form',
|
| 107 |
'callback arguments' => array('uc_promo_codes_form', arg(4), 0),
|
| 108 |
'access' => user_access('administer uc promotions'),
|
| 109 |
'type' => MENU_LOCAL_TASK,
|
| 110 |
'weight' => 0,
|
| 111 |
);
|
| 112 |
$items[] = array(
|
| 113 |
'path' => 'admin/store/settings/promo/'. arg(4) .'/codes/'. arg(6) .'/download',
|
| 114 |
'title' => t('Download bulk generated codes'),
|
| 115 |
'callback' => 'uc_promo_code_bulkgen',
|
| 116 |
'callback arguments' => array(arg(4), arg(6)),
|
| 117 |
'access' => user_access('administer uc promotions'),
|
| 118 |
'type' => MENU_CALLBACK,
|
| 119 |
);
|
| 120 |
$items[] = array(
|
| 121 |
'path' => 'admin/store/settings/promo/'. arg(4) .'/codes/'. arg(6) .'/edit',
|
| 122 |
'title' => t('Edit code'),
|
| 123 |
'description' => t('Edit a promotional code.'),
|
| 124 |
'callback' => 'drupal_get_form',
|
| 125 |
'callback arguments' => array('uc_promo_codes_form', arg(4), arg(6)),
|
| 126 |
'access' => user_access('administer uc promotions'),
|
| 127 |
'type' => MENU_CALLBACK,
|
| 128 |
);
|
| 129 |
$items[] = array(
|
| 130 |
'path' => 'admin/store/settings/promo/'. arg(4) .'/codes/'. arg(6) .'/delete',
|
| 131 |
'title' => t('Delete code'),
|
| 132 |
'description' => t('Delete a promotional code.'),
|
| 133 |
'callback' => 'drupal_get_form',
|
| 134 |
'callback arguments' => array('uc_promo_delete_code_form', arg(4), arg(6)),
|
| 135 |
'access' => user_access('administer uc promotions'),
|
| 136 |
'type' => MENU_CALLBACK,
|
| 137 |
);
|
| 138 |
$items[] = array(
|
| 139 |
'path' => 'admin/store/settings/promo/'. arg(4) .'/codes/'. arg(6) .'/redemptions',
|
| 140 |
'title' => t('Promotional code redemptions'),
|
| 141 |
'description' => t('A table of redemptions for a promotional code.'),
|
| 142 |
'callback' => 'uc_promo_redemptions',
|
| 143 |
'callback arguments' => array(arg(4), arg(6)),
|
| 144 |
'access' => user_access('administer uc promotions'),
|
| 145 |
'type' => MENU_CALLBACK,
|
| 146 |
);
|
| 147 |
$items[] = array(
|
| 148 |
'path' => 'admin/store/settings/promo/'. arg(4) .'/codes/back',
|
| 149 |
'title' => t('Back to promotions'),
|
| 150 |
'callback' => 'drupal_goto',
|
| 151 |
'callback arguments' => array('admin/store/settings/promo'),
|
| 152 |
'access' => user_access('administer uc promotions'),
|
| 153 |
'type' => MENU_LOCAL_TASK,
|
| 154 |
'weight' => 10,
|
| 155 |
);
|
| 156 |
}
|
| 157 |
}
|
| 158 |
}
|
| 159 |
|
| 160 |
return $items;
|
| 161 |
}
|
| 162 |
|
| 163 |
/**
|
| 164 |
* Implementation of hook_perm().
|
| 165 |
*/
|
| 166 |
function uc_promo_perm() {
|
| 167 |
return array('administer uc promotions', 'redeem uc promotions');
|
| 168 |
}
|
| 169 |
|
| 170 |
/**
|
| 171 |
* Implementation of Workflow-ng hook_event_info().
|
| 172 |
*/
|
| 173 |
function uc_promo_event_info() {
|
| 174 |
$events = array();
|
| 175 |
|
| 176 |
$result = db_query("SELECT promo_id, promo_name FROM {uc_promos}");
|
| 177 |
while ($promo = db_fetch_object($result)) {
|
| 178 |
$events['uc_promo_'. $promo->promo_id] = array(
|
| 179 |
'#label' => t('@name', array('@name' => $promo->promo_name)),
|
| 180 |
'#module' => 'Promotions',
|
| 181 |
'#arguments' => array(
|
| 182 |
'user' => array('#entity' => 'user', '#label' => t('User')),
|
| 183 |
),
|
| 184 |
);
|
| 185 |
}
|
| 186 |
|
| 187 |
return $events;
|
| 188 |
}
|
| 189 |
|
| 190 |
/**
|
| 191 |
* Implementation of Workflow-ng hook_action_info().
|
| 192 |
*/
|
| 193 |
function uc_promo_action_info() {
|
| 194 |
$actions = array();
|
| 195 |
|
| 196 |
// Provide integration for File Downloads module.
|
| 197 |
if (module_exists('uc_file')) {
|
| 198 |
// Add a file download to a user's account.
|
| 199 |
$actions['uc_promo_user_add_download'] = array(
|
| 200 |
'#label' => t('Give a user a file download.'),
|
| 201 |
'#arguments' => array(
|
| 202 |
'user' => array('#entity' => 'user', '#label' => t('User account')),
|
| 203 |
),
|
| 204 |
'#module' => t('Promotions'),
|
| 205 |
);
|
| 206 |
}
|
| 207 |
|
| 208 |
return $actions;
|
| 209 |
}
|
| 210 |
|
| 211 |
// Displays a form for redeeming promotions.
|
| 212 |
function uc_promo_redeem() {
|
| 213 |
// Check for redemption access.
|
| 214 |
if (!user_access('redeem uc promotions')) {
|
| 215 |
if (variable_get('uc_promo_login_redirect', TRUE)) {
|
| 216 |
// Redirect if specified in the promotions settings.
|
| 217 |
drupal_set_message(t('You must login or create an account before you can redeem your promotional code.'));
|
| 218 |
drupal_goto('user/login', 'destination=promo');
|
| 219 |
}
|
| 220 |
else {
|
| 221 |
drupal_access_denied();
|
| 222 |
}
|
| 223 |
}
|
| 224 |
|
| 225 |
return drupal_get_form('uc_promo_redeem_form', $code);
|
| 226 |
}
|
| 227 |
|
| 228 |
// Form builder function for a promotional code redemption form.
|
| 229 |
function uc_promo_redeem_form() {
|
| 230 |
$form = array();
|
| 231 |
|
| 232 |
$form['promo_code'] = array(
|
| 233 |
'#type' => 'textfield',
|
| 234 |
'#title' => t('Promotional code'),
|
| 235 |
'#description' => t('Enter the code for the promotion you would like to redeem.'),
|
| 236 |
'#required' => TRUE,
|
| 237 |
);
|
| 238 |
|
| 239 |
$form['submit'] = array(
|
| 240 |
'#type' => 'submit',
|
| 241 |
'#value' => t('Submit'),
|
| 242 |
);
|
| 243 |
|
| 244 |
return $form;
|
| 245 |
}
|
| 246 |
|
| 247 |
function uc_promo_redeem_form_validate($form_id, $form_values) {
|
| 248 |
global $user;
|
| 249 |
|
| 250 |
// Check to make sure the code is valid.
|
| 251 |
if (!uc_promo_validate_code($form_values['promo_code'], $user)) {
|
| 252 |
form_set_error('promo_code', t('You have entered an invalid promotional code. Make sure you have entered code correctly and try again.'));
|
| 253 |
}
|
| 254 |
}
|
| 255 |
|
| 256 |
function uc_promo_redeem_form_submit($form_id, $form_values) {
|
| 257 |
global $user;
|
| 258 |
|
| 259 |
// Load the promo code data.
|
| 260 |
$code_data = uc_promo_load_code($form_values['promo_code']);
|
| 261 |
|
| 262 |
// Check if this is a bulk generated code; if so, we redeem it differently.
|
| 263 |
if ($code_data['promo_code'] !== $form_values['promo_code']) {
|
| 264 |
$bulk_code = $form_values['promo_code'];
|
| 265 |
}
|
| 266 |
else {
|
| 267 |
$bulk_code = NULL;
|
| 268 |
}
|
| 269 |
|
| 270 |
// Make the appropriate database updates for the redemption.
|
| 271 |
uc_promo_redeem_code($code_data['promo_code'], $user, $bulk_code);
|
| 272 |
|
| 273 |
$promo_data = uc_promo_load_promotion($code_data['promo_id']);
|
| 274 |
|
| 275 |
// Trigger any configurations assigned to this promotion's trigger.
|
| 276 |
workflow_ng_invoke_event('uc_promo_'. $code_data['promo_id'], $user);
|
| 277 |
|
| 278 |
// Send the user to the promotion's landing page.
|
| 279 |
$path = token_replace($promo_data['landing_page'], 'global');
|
| 280 |
|
| 281 |
return $path;
|
| 282 |
}
|
| 283 |
|
| 284 |
// Displays an admin table for existing promotions and a settings form.
|
| 285 |
function uc_promo_admin() {
|
| 286 |
$header = array(
|
| 287 |
array('data' => t('ID'), 'field' => 'promo_id'),
|
| 288 |
array('data' => t('Created'), 'field' => 'created', 'sort' => 'desc'),
|
| 289 |
array('data' => t('Name'), 'field' => 'promo_name'),
|
| 290 |
array('data' => t('Status'), 'field' => 'promo_status'),
|
| 291 |
t('Operations'),
|
| 292 |
);
|
| 293 |
|
| 294 |
$rows = array();
|
| 295 |
|
| 296 |
// Get all the promotions from the database.
|
| 297 |
$result = pager_query("SELECT * FROM {uc_promos}". tablesort_sql($header), 30);
|
| 298 |
while ($data = db_fetch_array($result)) {
|
| 299 |
$ops = array(
|
| 300 |
l(t('codes'), 'admin/store/settings/promo/'. $data['promo_id'] .'/codes'),
|
| 301 |
l(t('edit'), 'admin/store/settings/promo/'. $data['promo_id'] .'/edit'),
|
| 302 |
l(t('delete'), 'admin/store/settings/promo/'. $data['promo_id'] .'/delete'),
|
| 303 |
);
|
| 304 |
|
| 305 |
$row = array(
|
| 306 |
check_plain($data['promo_id']),
|
| 307 |
array('data' => format_date($data['created'], 'short'), 'style' => 'white-space: nowrap'),
|
| 308 |
check_plain($data['promo_name']),
|
| 309 |
$data['promo_status'] ? t('Active') : t('Disabled'),
|
| 310 |
array('data' => implode(' ', $ops), 'style' => 'white-space: nowrap;'),
|
| 311 |
);
|
| 312 |
|
| 313 |
$rows[] = $row;
|
| 314 |
}
|
| 315 |
|
| 316 |
if (count($rows) == 0) {
|
| 317 |
$rows[] = array(
|
| 318 |
array('data' => t('No promotions created yet.'), 'colspan' => 4),
|
| 319 |
);
|
| 320 |
}
|
| 321 |
|
| 322 |
return theme('table', $header, $rows) . theme('pager') . l(t('Add a promotion.'), 'admin/store/settings/promo/add');
|
| 323 |
}
|
| 324 |
|
| 325 |
// Form builder for the promo admin settings form.
|
| 326 |
function uc_promo_admin_form() {
|
| 327 |
$form = array();
|
| 328 |
|
| 329 |
$form['uc_promo_login_redirect'] = array(
|
| 330 |
'#type' => 'checkbox',
|
| 331 |
'#title' => t('Redirect users without access to redeem promotions to the login page.'),
|
| 332 |
'#description' => t('Check this setting if authenticated users has access but anonymous users do not.'),
|
| 333 |
'#default_value' => variable_get('uc_promo_login_redirect', TRUE),
|
| 334 |
);
|
| 335 |
$form['uc_promo_delete_behavior'] = array(
|
| 336 |
'#type' => 'radios',
|
| 337 |
'#title' => t('Promotion delete behavior'),
|
| 338 |
'#options' => array(
|
| 339 |
0 => t('Delete the promotion and any related promotional codes.'),
|
| 340 |
1 => t('Delete the promotion and any related unredeemed promotional codes.'),
|
| 341 |
2 => t('Delete the promotion.'),
|
| 342 |
),
|
| 343 |
'#default_value' => variable_get('uc_promo_delete_behavior', 0),
|
| 344 |
);
|
| 345 |
|
| 346 |
return system_settings_form($form);
|
| 347 |
}
|
| 348 |
|
| 349 |
// Form builder for adding or editing a promotion.
|
| 350 |
function uc_promo_promotion_form($promo_id) {
|
| 351 |
$form = array();
|
| 352 |
|
| 353 |
// Load the specified promotion; will be FALSE if $promo_id == 0.
|
| 354 |
$data = uc_promo_load_promotion($promo_id);
|
| 355 |
|
| 356 |
$form['promo_id'] = array(
|
| 357 |
'#type' => 'value',
|
| 358 |
'#value' => $data === FALSE ? 0 : $promo_id,
|
| 359 |
);
|
| 360 |
|
| 361 |
$form['promo_name'] = array(
|
| 362 |
'#type' => 'textfield',
|
| 363 |
'#title' => t('Name'),
|
| 364 |
'#description' => t('Displayed on the admin overview and to the user when they redeem a code for this promotion.'),
|
| 365 |
'#max_length' => 255,
|
| 366 |
'#default_value' => $data['promo_name'],
|
| 367 |
'#required' => TRUE,
|
| 368 |
);
|
| 369 |
|
| 370 |
$form['landing_page'] = array(
|
| 371 |
'#type' => 'textfield',
|
| 372 |
'#title' => t('Landing page'),
|
| 373 |
'#description' => t('Specify the path to which users who redeem this promotion should be redirected.<br /><a href="!url">Uses global tokens.</a>', array('!url' => url('admin/store/help/tokens'))),
|
| 374 |
'#default_value' => $data['landing_page'],
|
| 375 |
'#size' => 32,
|
| 376 |
'#field_prefix' => url(NULL, NULL, NULL, TRUE) . (variable_get('clean_url', 0) ? '' : '?q='),
|
| 377 |
);
|
| 378 |
|
| 379 |
$form['redeem_once'] = array(
|
| 380 |
'#type' => 'checkbox',
|
| 381 |
'#title' => t('Users can only redeem this promotion once with any code.'),
|
| 382 |
'#description' => t('Use this to prevent users from taking advantage of unlimited use promotion codes.'),
|
| 383 |
'#default_value' => $data['redeem_once'],
|
| 384 |
);
|
| 385 |
|
| 386 |
$form['promo_status'] = array(
|
| 387 |
'#type' => 'radios',
|
| 388 |
'#title' => t('Status'),
|
| 389 |
'#options' => array(
|
| 390 |
0 => t('Disabled'),
|
| 391 |
1 => t('Active'),
|
| 392 |
),
|
| 393 |
'#default_value' => $data === FALSE ? 1 : $data['promo_status'],
|
| 394 |
'#required' => TRUE,
|
| 395 |
);
|
| 396 |
|
| 397 |
$form['save'] = array(
|
| 398 |
'#type' => 'submit',
|
| 399 |
'#value' => t('Save'),
|
| 400 |
'#suffix' => l(t('Cancel'), 'admin/store/settings/promo'),
|
| 401 |
);
|
| 402 |
|
| 403 |
return $form;
|
| 404 |
}
|
| 405 |
|
| 406 |
function uc_promo_promotion_form_submit($form_id, $form_values) {
|
| 407 |
uc_promo_save_promotion($form_values);
|
| 408 |
|
| 409 |
drupal_set_message(t('Promotion saved.'));
|
| 410 |
|
| 411 |
return 'admin/store/settings/promo';
|
| 412 |
}
|
| 413 |
|
| 414 |
// Form buider for deleting a promotion.
|
| 415 |
function uc_promo_delete_promotion_form($promo_id) {
|
| 416 |
$data = uc_promo_load_promotion($promo_id);
|
| 417 |
$form = array();
|
| 418 |
|
| 419 |
// Fail if the promotion doesn't exist.
|
| 420 |
if (!$data) {
|
| 421 |
drupal_set_message(t("The specified promotion doesn't exist."), 'error');
|
| 422 |
drupal_goto('admin/store/settings/promo');
|
| 423 |
}
|
| 424 |
|
| 425 |
$form['promo_id'] = array(
|
| 426 |
'#type' => 'value',
|
| 427 |
'#value' => $promo_id,
|
| 428 |
);
|
| 429 |
|
| 430 |
return confirm_form($form, t('Delete promotion'), 'admin/store/settings/promo', t('Are you sure you want to delete %name?', array('%name' => $data['promo_name'])), t('Delete'));
|
| 431 |
}
|
| 432 |
|
| 433 |
function uc_promo_delete_promotion_form_submit($form_id, $form_values) {
|
| 434 |
uc_promo_delete_promotion($form_values['promo_id']);
|
| 435 |
|
| 436 |
drupal_set_message(t('The promotion has been deleted.'));
|
| 437 |
|
| 438 |
return 'admin/store/settings/promo';
|
| 439 |
}
|
| 440 |
|
| 441 |
/**
|
| 442 |
* Loads a promotion from the database.
|
| 443 |
*
|
| 444 |
* @param $promo_id
|
| 445 |
* The ID of the promotion to load.
|
| 446 |
* @return
|
| 447 |
* An array of data for the promotion.
|
| 448 |
*/
|
| 449 |
function uc_promo_load_promotion($promo_id) {
|
| 450 |
$result = db_query("SELECT * FROM {uc_promos} WHERE promo_id = %d", $promo_id);
|
| 451 |
|
| 452 |
return db_fetch_array($result);
|
| 453 |
}
|
| 454 |
|
| 455 |
/**
|
| 456 |
* Saves or inserts a new promotion.
|
| 457 |
*
|
| 458 |
* @param $data
|
| 459 |
* An array of data representing the promotion.
|
| 460 |
*/
|
| 461 |
function uc_promo_save_promotion($data) {
|
| 462 |
// First try to update an existing promotion.
|
| 463 |
if ($data['promo_id'] > 0) {
|
| 464 |
db_query("UPDATE {uc_promos} SET promo_name = '%s', landing_page = '%s', redeem_once = %d, promo_status = %d WHERE promo_id = %d",
|
| 465 |
$data['promo_name'], $data['landing_page'], $data['redeem_once'],
|
| 466 |
$data['promo_status'], $data['promo_id']);
|
| 467 |
}
|
| 468 |
|
| 469 |
// Otherwise insert a new promotion.
|
| 470 |
if ($data['promo_id'] === 0 || db_affected_rows() == 0) {
|
| 471 |
db_query("INSERT INTO {uc_promos} (promo_id, promo_name, landing_page, redeem_once, promo_status, created) VALUES (%d, '%s', '%s', %d, %d, %d)",
|
| 472 |
$data['promo_id'] == 0 ? db_next_id('{uc_promos}_promo_id') : $data['promo_id'],
|
| 473 |
$data['promo_name'], $data['landing_page'], $data['redeem_once'],
|
| 474 |
$data['promo_status'], time());
|
| 475 |
}
|
| 476 |
}
|
| 477 |
|
| 478 |
/**
|
| 479 |
* Delete a promotion from the database.
|
| 480 |
*
|
| 481 |
* @param $promo_id
|
| 482 |
* The ID of the promotion to delete.
|
| 483 |
*/
|
| 484 |
function uc_promo_delete_promotion($promo_id) {
|
| 485 |
// Delete related codes per the user settings.
|
| 486 |
switch (variable_get('uc_promo_delete_behavior', 0)) {
|
| 487 |
case 0:
|
| 488 |
// Delete any related promotional codes.
|
| 489 |
db_query("DELETE FROM {uc_promo_code_redemptions} WHERE promo_id = %d", $promo_id);
|
| 490 |
db_query("DELETE FROM {uc_promo_codes} WHERE promo_id = %d", $promo_id);
|
| 491 |
break;
|
| 492 |
|
| 493 |
case 1:
|
| 494 |
// Delete related promotional codes that haven't been redeemed.
|
| 495 |
db_query("DELETE FROM {uc_promo_codes} WHERE promo_id = %d AND redemptions > 0", $promo_id);
|
| 496 |
break;
|
| 497 |
}
|
| 498 |
|
| 499 |
// Get the name for use in the log entry.
|
| 500 |
$name = db_result(db_query("SELECT promo_name FROM {uc_promos} WHERE promo_id = %d", $promo_id));
|
| 501 |
|
| 502 |
// Delete the promotion itself.
|
| 503 |
db_query("DELETE FROM {uc_promos} WHERE promo_id = %d", $promo_id);
|
| 504 |
|
| 505 |
watchdog('uc_promo', t('Promotion %name deleted.', array('%name' => !empty($name) ? $name : $promo_id)));
|
| 506 |
}
|
| 507 |
|
| 508 |
function uc_promo_codes($promo_id) {
|
| 509 |
// Load the specified promo code; will be FALSE if $code == 0.
|
| 510 |
$data = uc_promo_load_promotion($promo_id);
|
| 511 |
|
| 512 |
if ($data === FALSE) {
|
| 513 |
drupal_set_message(t('Specified promotion does not exist.'), 'error');
|
| 514 |
drupal_goto('admin/store/settings/promo');
|
| 515 |
}
|
| 516 |
|
| 517 |
$output = t('Promotion: %name', array('%name' => check_plain($data['promo_name'])));
|
| 518 |
|
| 519 |
$header = array(
|
| 520 |
array('data' => t('Code'), 'field' => 'promo_code'),
|
| 521 |
array('data' => t('Type'), 'field' => 'promo_code_type'),
|
| 522 |
array('data' => t('Redemptions'), 'field' => 'redemptions'),
|
| 523 |
array('data' => t('Last redemption'), 'field' => 'last_redemption', 'sort' => 'desc'),
|
| 524 |
t('Operations'),
|
| 525 |
);
|
| 526 |
|
| 527 |
$rows = array();
|
| 528 |
|
| 529 |
// Get all the promotions from the database.
|
| 530 |
$result = pager_query("SELECT * FROM {uc_promo_codes} WHERE promo_id = %d". tablesort_sql($header), 30, 0, NULL, $promo_id);
|
| 531 |
while ($data = db_fetch_array($result)) {
|
| 532 |
// Create a download link for bulk generated codes.
|
| 533 |
if (!empty($data['bulkgen_seed'])) {
|
| 534 |
$download = '<br />'. l(t('Download codes.'), 'admin/store/settings/promo/'. $data['promo_id'] .'/codes/'. $data['promo_code'] .'/download');
|
| 535 |
}
|
| 536 |
else {
|
| 537 |
$download = '';
|
| 538 |
}
|
| 539 |
|
| 540 |
// Create an array of operations for the code.
|
| 541 |
$ops = array(
|
| 542 |
l(t('redemptions'), 'admin/store/settings/promo/'. $data['promo_id'] .'/codes/'. $data['promo_code'] .'/redemptions'),
|
| 543 |
l(t('edit'), 'admin/store/settings/promo/'. $data['promo_id'] .'/codes/'. $data['promo_code'] .'/edit'),
|
| 544 |
l(t('delete'), 'admin/store/settings/promo/'. $data['promo_id'] .'/codes/'. $data['promo_code'] .'/delete'),
|
| 545 |
);
|
| 546 |
|
| 547 |
switch ($data['promo_code_type']) {
|
| 548 |
case 1:
|
| 549 |
$type = t('Unlimited');
|
| 550 |
break;
|
| 551 |
case 2:
|
| 552 |
$type = t('Limited: @number', array('@number' => $data['max_redemptions']));
|
| 553 |
break;
|
| 554 |
case 3:
|
| 555 |
$type = t('Expires @date', array('@date' => format_date($data['expiration'], 'short')));
|
| 556 |
break;
|
| 557 |
}
|
| 558 |
|
| 559 |
$row = array(
|
| 560 |
'data' => array(
|
| 561 |
check_plain($data['promo_code']) . $download,
|
| 562 |
array('data' => $type, 'style' => 'white-space: nowrap;'),
|
| 563 |
$data['redemptions'],
|
| 564 |
array('data' => $data['last_redemption'] > 0 ? format_date($data['last_redemption'], 'short') : '-', 'style' => 'white-space: nowrap;'),
|
| 565 |
array('data' => implode(' ', $ops), 'style' => 'white-space: nowrap;'),
|
| 566 |
),
|
| 567 |
'valign' => 'top',
|
| 568 |
);
|
| 569 |
|
| 570 |
$rows[] = $row;
|
| 571 |
}
|
| 572 |
|
| 573 |
if (count($rows) == 0) {
|
| 574 |
$rows[] = array(
|
| 575 |
array('data' => t('No promotional codes created yet.'), 'colspan' => 5),
|
| 576 |
);
|
| 577 |
}
|
| 578 |
|
| 579 |
$output .= theme('table', $header, $rows) . theme('pager') . l(t('Add promotional codes.'), 'admin/store/settings/promo/'. $promo_id .'/codes/add');
|
| 580 |
|
| 581 |
return $output;
|
| 582 |
}
|
| 583 |
|
| 584 |
function uc_promo_codes_form($promo_id, $code) {
|
| 585 |
$form = array();
|
| 586 |
|
| 587 |
// Load the specified promotion; will be FALSE if $code == 0.
|
| 588 |
$data = uc_promo_load_promotion($promo_id);
|
| 589 |
|
| 590 |
if ($data === FALSE) {
|
| 591 |
drupal_set_message(t('Specified promotion does not exist.'), 'error');
|
| 592 |
drupal_goto('admin/store/settings/promo');
|
| 593 |
}
|
| 594 |
|
| 595 |
$form['promo_name'] = array(
|
| 596 |
'#value' => t('Promotion: %name', array('%name' => check_plain($data['promo_name']))),
|
| 597 |
);
|
| 598 |
|
| 599 |
$form['promo_id'] = array(
|
| 600 |
'#type' => 'value',
|
| 601 |
'#value' => $promo_id,
|
| 602 |
);
|
| 603 |
|
| 604 |
// Load the specified promo code; will be FALSE if $code == 0.
|
| 605 |
$data = uc_promo_load_code($code);
|
| 606 |
|
| 607 |
$code_disabled = FALSE;
|
| 608 |
|
| 609 |
if ($data !== FALSE) {
|
| 610 |
$form['promo_code_orig'] = array(
|
| 611 |
'#type' => 'value',
|
| 612 |
'#value' => $code,
|
| 613 |
);
|
| 614 |
|
| 615 |
// Disable editing the code if we're dealing with a bulkgen code.
|
| 616 |
if (!empty($data['bulkgen_seed'])) {
|
| 617 |
$code_disabled = TRUE;
|
| 618 |
}
|
| 619 |
else {
|
| 620 |
// Otherwise disable it if it's already been redeemed.
|
| 621 |
$count = db_result(db_query("SELECT COUNT(*) FROM {uc_promo_code_redemptions} WHERE promo_code = '%s'", $code));
|
| 622 |
if ($count > 0) {
|
| 623 |
$code_disabled = TRUE;
|
| 624 |
}
|
| 625 |
}
|
| 626 |
}
|
| 627 |
|
| 628 |
|
| 629 |
$form['promo_code'] = array(
|
| 630 |
'#type' => 'textfield',
|
| 631 |
'#title' => t('Promotional code'),
|
| 632 |
'#description' => t('Promotional codes may only contain letters, numbers, underscores, and dashes.<br />Codes may not be changed once they have been redeemed.<br/>Do NOT manually set a code to start with "BULKGEN".'),
|
| 633 |
'#default_value' => $data === FALSE ? '' : $data['promo_code'],
|
| 634 |
'#required' => $data === FALSE ? FALSE : TRUE,
|
| 635 |
'#disabled' => $code_disabled,
|
| 636 |
);
|
| 637 |
|
| 638 |
if ($code === 0) {
|
| 639 |
$form['bulk'] = array(
|
| 640 |
'#type' => 'fieldset',
|
| 641 |
'#title' => t('Bulk code generation'),
|
| 642 |
'#description' => t('You may choose to bulk generate alphanumeric promotional codes based on the settings below.<br />If so, the promotional code entered above will be ignored.'),
|
| 643 |
'#collapsible' => TRUE,
|
| 644 |
'#collapsed' => TRUE,
|
| 645 |
);
|
| 646 |
$form['bulk']['bulk_generate'] = array(
|
| 647 |
'#type' => 'checkbox',
|
| 648 |
'#title' => t('Bulk generate codes for this promotion.'),
|
| 649 |
);
|
| 650 |
/*$form['bulk']['code_rule'] = array(
|
| 651 |
'#type' => 'radios',
|
| 652 |
'#title' => t('Code generation rule'),
|
| 653 |
'#options' => array(
|
| 654 |
'numeric' => t('Random numeric promotional codes.'),
|
| 655 |
'alpha_numeric' => t('Random alpha-numeric promotional codes.'),
|
| 656 |
),
|
| 657 |
);*/
|
| 658 |
$form['bulk']['number_codes'] = array(
|
| 659 |
'#type' => 'textfield',
|
| 660 |
'#title' => t('Number of codes'),
|
| 661 |
'#description' => t('Enter in the number of codes you want to generate.'),
|
| 662 |
);
|
| 663 |
$form['bulk']['code_length'] = array(
|
| 664 |
'#type' => 'select',
|
| 665 |
'#title' => t('Code length'),
|
| 666 |
'#options' => drupal_map_assoc(range(10, 30)),
|
| 667 |
);
|
| 668 |
}
|
| 669 |
|
| 670 |
$form['promo_code_type'] = array(
|
| 671 |
'#type' => 'radios',
|
| 672 |
'#title' => t('Promotional code type'),
|
| 673 |
'#description' => t('Limited or expirable promotional codes should specify their settings below.'),
|
| 674 |
'#options' => array(
|
| 675 |
1 => t('Unlimited number of redemptions'),
|
| 676 |
2 => t('Limited number of redemptions'),
|
| 677 |
3 => t('Expires on a certain date'),
|
| 678 |
),
|
| 679 |
'#default_value' => $data['promo_code_type'],
|
| 680 |
'#required' => TRUE,
|
| 681 |
);
|
| 682 |
|
| 683 |
$form['max_redemptions'] = array(
|
| 684 |
'#type' => 'textfield',
|
| 685 |
'#title' => t('Maximum number of redemptions'),
|
| 686 |
'#description' => t('Only applicable to limited promotional codes.'),
|
| 687 |
'#default_value' => $data['max_redemptions'],
|
| 688 |
);
|
| 689 |
|
| 690 |
$form['expiration'] = array(
|
| 691 |
'#type' => 'date',
|
| 692 |
'#title' => t('Expiration date'),
|
| 693 |
'#description' => t('The code will fail after 23:59 of the specified date.<br />Only applicable to expirable promotional codes.'),
|
| 694 |
'#default_value' => array(
|
| 695 |
'year' => date('Y', $data === FALSE ? time() : $data['expiration']),
|
| 696 |
'month' => date('n', $data === FALSE ? time() : $data['expiration']),
|
| 697 |
'day' => date('j', $data === FALSE ? time() : $data['expiration']),
|
| 698 |
),
|
| 699 |
);
|
| 700 |
|
| 701 |
$form['save'] = array(
|
| 702 |
'#type' => 'submit',
|
| 703 |
'#value' => t('Save'),
|
| 704 |
);
|
| 705 |
|
| 706 |
$form['save_add'] = array(
|
| 707 |
'#type' => 'submit',
|
| 708 |
'#value' => t('Save and add another'),
|
| 709 |
'#suffix' => l(t('Cancel'), 'admin/store/settings/promo/'. $promo_id .'/codes'),
|
| 710 |
);
|
| 711 |
|
| 712 |
return $form;
|
| 713 |
}
|
| 714 |
|
| 715 |
function uc_promo_codes_form_validate($form_id, $form_values) {
|
| 716 |
// Fail if no promo code was entered and bulk generation was not selected.
|
| 717 |
if (!$form_values['bulk_generate'] && empty($form_values['promo_code'])) {
|
| 718 |
form_set_error('promo_code', t('You must specify a promotional code.'));
|
| 719 |
}
|
| 720 |
|
| 721 |
// Fail if the user entered an invalid bulk generated code length.
|
| 722 |
if ($form_values['bulk_generate'] && (intval($form_values['code_length']) < 10 || intval($form_values['code_length']) > 30)) {
|
| 723 |
form_set_error('code_length', t('You must specify a code length between 10 and 30.'));
|
| 724 |
}
|
| 725 |
|
| 726 |
// Fail if the user entered an invalid number of bulk generated codes.
|
| 727 |
if ($form_values['bulk_generate'] && intval($form_values['number_codes']) <= 0) {
|
| 728 |
form_set_error('number_codes', t('You must specify a number of codes greater than 0.'));
|
| 729 |
}
|
| 730 |
|
| 731 |
// Fail if the promotional code has invalid characters.
|
| 732 |
if (!empty($form_values['promo_code']) && !preg_match('!^[a-zA-Z0-9_-]+$!', $form_values['promo_code'])) {
|
| 733 |
form_set_error('promo_code', t('The promotional code can only consist of letters, numbers, underscores, and dashes.'));
|
| 734 |
}
|
| 735 |
|
| 736 |
// Fail if the promotional code entered is non-unique.
|
| 737 |
if (!isset($form_values['promo_code_orig']) || $form_values['promo_code_orig'] != $form_values['promo_code']) {
|
| 738 |
$exists = db_result(db_query("SELECT COUNT(*) FROM {uc_promo_codes} WHERE UPPER(promo_code) = '%s'", strtoupper($form_values['promo_code'])));
|
| 739 |
if ($exists > 0) {
|
| 740 |
form_set_error('promo_code', t('That promotional code has already been used.'));
|
| 741 |
}
|
| 742 |
}
|
| 743 |
|
| 744 |
// Fail if the user entered an invalid value for redemptions.
|
| 745 |
if ($form_values['promo_code_type'] == 2 && intval($form_values['max_redemptions']) <= 0) {
|
| 746 |
form_set_error('max_redemptions', t('You must specify a number of redemptions greater than 0.'));
|
| 747 |
}
|
| 748 |
}
|
| 749 |
|
| 750 |
function uc_promo_codes_form_submit($form_id, $form_values) {
|
| 751 |
// Convert the expiration date to a timestamp.
|
| 752 |
$form_values['expiration'] = gmmktime(23, 59, 59, $form_values['expiration']['month'], $form_values['expiration']['day'], $form_values['expiration']['year']);
|
| 753 |
|
| 754 |
// Special handling for bulk generated codes.
|
| 755 |
if ($form_values['bulk_generate']) {
|
| 756 |
$bulkgen_id = variable_get('uc_promo_bulkgen_id', 1);
|
| 757 |
variable_set('uc_promo_bulkgen_id', $bulkgen_id + 1);
|
| 758 |
|
| 759 |
// Manually set the promo code name.
|
| 760 |
$form_values['promo_code'] = 'BULKGEN'. $bulkgen_id .'-'. $form_values['code_length'] .'-'. $form_values['number_codes'];
|
| 761 |
|
| 762 |
// Setup the bulk generator seed.
|
| 763 |
$form_values['bulkgen_seed'] = sha1(mktime() . rand());
|
| 764 |
}
|
| 765 |
|
| 766 |
uc_promo_save_code($form_values);
|
| 767 |
|
| 768 |
drupal_set_message(t('Promotional code saved.'));
|
| 769 |
|
| 770 |
if ($form_values['op'] == t('Save')) {
|
| 771 |
return 'admin/store/settings/promo/'. $form_values['promo_id'] .'/codes';
|
| 772 |
}
|
| 773 |
}
|
| 774 |
|
| 775 |
// Form buider for deleting a promotional code.
|
| 776 |
function uc_promo_delete_code_form($promo_id, $code) {
|
| 777 |
$data = uc_promo_load_code($code);
|
| 778 |
$form = array();
|
| 779 |
|
| 780 |
// Fail if the promotional code doesn't exist.
|
| 781 |
if (!$data) {
|
| 782 |
drupal_set_message(t("The specified promotional code doesn't exist."), 'error');
|
| 783 |
drupal_goto('admin/store/settings/promo/'. $promo_id .'/codes');
|
| 784 |
}
|
| 785 |
|
| 786 |
$form['promo_id'] = array(
|
| 787 |
'#type' => 'value',
|
| 788 |
'#value' => $promo_id,
|
| 789 |
);
|
| 790 |
|
| 791 |
$form['promo_code'] = array(
|
| 792 |
'#type' => 'value',
|
| 793 |
'#value' => $code,
|
| 794 |
);
|
| 795 |
|
| 796 |
return confirm_form($form, t('Delete promotional code'), 'admin/store/settings/promo/'. $promo_id .'/codes', t('Are you sure you want to delete %code?', array('%code' => $data['promo_code'])), t('Delete'));
|
| 797 |
}
|
| 798 |
|
| 799 |
function uc_promo_delete_code_form_submit($form_id, $form_values) {
|
| 800 |
uc_promo_delete_code($form_values['promo_code']);
|
| 801 |
|
| 802 |
drupal_set_message(t('The promotional code has been deleted.'));
|
| 803 |
|
| 804 |
return 'admin/store/settings/promo/'. $form_values['promo_id'] .'/codes';
|
| 805 |
}
|
| 806 |
|
| 807 |
/**
|
| 808 |
* Loads a promotional code's data from the database.
|
| 809 |
*
|
| 810 |
* @param $code
|
| 811 |
* The promotional code to load.
|
| 812 |
* @return
|
| 813 |
* An array of data for the promotional code; FALSE if the code isn't found.
|
| 814 |
*/
|
| 815 |
function uc_promo_load_code($code) {
|
| 816 |
if (empty($code)) {
|
| 817 |
return FALSE;
|
| 818 |
}
|
| 819 |
|
| 820 |
// Check to make sure non-priveleged users don't match directly on the bulk
|
| 821 |
// generated special string.
|
| 822 |
if (substr($code, 0, 7) === 'BULKGEN' && !user_access('administer uc promotions')) {
|
| 823 |
return FALSE;
|
| 824 |
}
|
| 825 |
|
| 826 |
// Look for an exact match in the database.
|
| 827 |
$result = db_query("SELECT * FROM {uc_promo_codes} WHERE UPPER(promo_code) = '%s'", strtoupper($code));
|
| 828 |
|
| 829 |
// Return the data if an exact match was found.
|
| 830 |
if ($data = db_fetch_array($result)) {
|
| 831 |
return $data;
|
| 832 |
}
|
| 833 |
|
| 834 |
// Otherwise look for a bulk generated match in codes for active promotions
|
| 835 |
// that haven't passed their expiration date.
|
| 836 |
$result = db_query("SELECT pc.* FROM {uc_promo_codes} AS pc LEFT JOIN {uc_promos} AS p ON pc.promo_id = p.promo_id WHERE p.promo_status = 1 AND pc.expiration > %d AND pc.bulkgen_seed <> ''", time());
|
| 837 |
while ($data = db_fetch_array($result)) {
|
| 838 |
// Parse the promotion code
|
| 839 |
$parts = explode('-', $data['promo_code']);
|
| 840 |
|
| 841 |
// First check that the code is the correct length.
|
| 842 |
if (strlen($code) != $parts[1]) {
|
| 843 |
continue;
|
| 844 |
}
|
| 845 |
|
| 846 |
// Second check that the sequence part of the code is in the valid range.
|
| 847 |
// The code sequence is encoded in the first 5 characters of the code.
|
| 848 |
$sequence = explode("U", substr(strtoupper($code), 0, 5));
|
| 849 |
if (preg_match("/^[0-9ABCDEF]{1,5}$/", $sequence[0])) {
|
| 850 |
$sequence = hexdec($sequence[0]);
|
| 851 |
if ($sequence >= $parts[2]) {
|
| 852 |
continue;
|
| 853 |
}
|
| 854 |
}
|
| 855 |
else {
|
| 856 |
continue;
|
| 857 |
}
|
| 858 |
|
| 859 |
// Last, check that the MD5 hash part of code is valid.
|
| 860 |
$hash = substr(md5($sequence . $data['promo_id'] . $data['bulkgen_seed']), 0, ($parts[1] - 5));
|
| 861 |
|
| 862 |
if (strcasecmp($hash, substr($code, 5)) == 0) {
|
| 863 |
return $data;
|
| 864 |
}
|
| 865 |
}
|
| 866 |
|
| 867 |
return FALSE;
|
| 868 |
}
|
| 869 |
|
| 870 |
/**
|
| 871 |
* Saves or inserts a new promotional code.
|
| 872 |
*
|
| 873 |
* @param $data
|
| 874 |
* An array of data representing the promotional code.
|
| 875 |
*/
|
| 876 |
function uc_promo_save_code($data) {
|
| 877 |
// First try to update an existing promotional code.
|
| 878 |
db_query("UPDATE {uc_promo_codes} SET promo_code_type = %d, max_redemptions = %d, expiration = %d WHERE UPPER(promo_code) = '%s'",
|
| 879 |
$data['promo_code_type'], $data['max_redemptions'], $data['expiration'], strtoupper($data['promo_code']));
|
| 880 |
|
| 881 |
// Otherwise insert a new promotional code.
|
| 882 |
if (db_affected_rows() == 0) {
|
| 883 |
db_query("INSERT INTO {uc_promo_codes} (promo_code, promo_id, promo_code_type, bulkgen_seed, redemptions, max_redemptions, expiration, created, last_redemption) VALUES ('%s', %d, %d, '%s', %d, %d, %d, %d, %d)",
|
| 884 |
strtoupper($data['promo_code']), $data['promo_id'], $data['promo_code_type'],
|
| 885 |
$data['bulkgen_seed'], 0, $data['max_redemptions'], $data['expiration'],
|
| 886 |
time(), 0);
|
| 887 |
}
|
| 888 |
}
|
| 889 |
|
| 890 |
/**
|
| 891 |
* Delete a promotional code from the database.
|
| 892 |
*
|
| 893 |
* @param $promo_code
|
| 894 |
* The ID of the promotional code to delete.
|
| 895 |
*/
|
| 896 |
function uc_promo_delete_code($code) {
|
| 897 |
// Delete any related promotional code redemptions.
|
| 898 |
db_query("DELETE FROM {uc_promo_code_redemptions} WHERE promo_code = '%s'", $code);
|
| 899 |
|
| 900 |
// Delete the code itself.
|
| 901 |
db_query("DELETE FROM {uc_promo_codes} WHERE promo_code = '%s'", $code);
|
| 902 |
|
| 903 |
watchdog('uc_promo', t('Promotional code %code deleted.', array('%code' => $code)));
|
| 904 |
}
|
| 905 |
|
| 906 |
// Displays a table of redemptions for the specified promotional code.
|
| 907 |
function uc_promo_redemptions($promo_id, $code) {
|
| 908 |
// Load the specified promotion; will be FALSE if $code == 0.
|
| 909 |
$data = uc_promo_load_promotion($promo_id);
|
| 910 |
|
| 911 |
if ($data === FALSE) {
|
| 912 |
drupal_set_message(t('Specified promotion does not exist.'), 'error');
|
| 913 |
drupal_goto('admin/store/settings/promo');
|
| 914 |
}
|
| 915 |
|
| 916 |
$output = '<div>'. t('<strong>Promotion:</strong> @name', array('@name' => check_plain($data['promo_name']))) .'<br />';
|
| 917 |
|
| 918 |
// Load the specified promotional code; will be FALSE if $code == 0.
|
| 919 |
$data = uc_promo_load_code($code);
|
| 920 |
|
| 921 |
if ($data === FALSE) {
|
| 922 |
drupal_set_message(t('Specified promotional code does not exist.'), 'error');
|
| 923 |
drupal_goto('admin/store/settings/promo/'. $promo_id .'/codes');
|
| 924 |
}
|
| 925 |
|
| 926 |
$output .= t('<strong>Code:</strong> @code', array('@code' => check_plain($code))) .'</div>';
|
| 927 |
|
| 928 |
$output .= '<div>'. l(t('Return to promotional codes listing.'), 'admin/store/settings/promo/'. $promo_id .'/codes') .'</div>';
|
| 929 |
|
| 930 |
$header = array(
|
| 931 |
array('data' => t('Redeemed on'), 'field' => 'redeemed', 'sort' => 'desc'),
|
| 932 |
array('data' => t('User'), 'field' => 'uid'),
|
| 933 |
);
|
| 934 |
|
| 935 |
if (substr($code, 0, 7) === 'BULKGEN') {
|
| 936 |
$header[] = array('data' => t('Bulk code'), 'field' => 'bulk_code');
|
| 937 |
}
|
| 938 |
|
| 939 |
$rows = array();
|
| 940 |
|
| 941 |
$result = pager_query("SELECT * FROM {uc_promo_code_redemptions} WHERE promo_code = '%s'". tablesort_sql($header), 30, 0, NULL, $code);
|
| 942 |
while ($data = db_fetch_array($result)) {
|
| 943 |
$row = array(
|
| 944 |
array('data' => format_date($data['redeemed'], 'short'), 'style' => 'white-space: nowrap'),
|
| 945 |
array('data' => $data['uid'] > 0 ? l($data['uid'], 'user/'. $data['uid']) : '0', 'width' => substr($code, 0, 7) === 'BULKGEN' ? '33%' : '50%'),
|
| 946 |
);
|
| 947 |
|
| 948 |
if (substr($code, 0, 7) === 'BULKGEN') {
|
| 949 |
$row[] = $data['bulk_code'];
|
| 950 |
}
|
| 951 |
|
| 952 |
$rows[] = $row;
|
| 953 |
}
|
| 954 |
|
| 955 |
if (count($rows) == 0) {
|
| 956 |
$rows[] = array(
|
| 957 |
array('data' => t('This promotional code has not been redeemed.'), 'colspan' => 5),
|
| 958 |
);
|
| 959 |
}
|
| 960 |
|
| 961 |
$output .= theme('table', $header, $rows) . theme('pager');
|
| 962 |
|
| 963 |
return $output;
|
| 964 |
}
|
| 965 |
|
| 966 |
/**
|
| 967 |
* Checks the database to see if a code is valid.
|
| 968 |
*
|
| 969 |
* @param $code
|
| 970 |
* The promotional code to validate.
|
| 971 |
* @return
|
| 972 |
* TRUE or FALSE depending on whether the code is valid or not.
|
| 973 |
*/
|
| 974 |
function uc_promo_validate_code($code, $user) {
|
| 975 |
// Return FALSE if the code is not found.
|
| 976 |
if (!$data = uc_promo_load_code($code)) {
|
| 977 |
return FALSE;
|
| 978 |
}
|
| 979 |
|
| 980 |
// Validate the code based on its type.
|
| 981 |
switch ($data['promo_code_type']) {
|
| 982 |
// Unlimited use promotional code.
|
| 983 |
case 1:
|
| 984 |
// Nothing should cause these to fail.
|
| 985 |
break;
|
| 986 |
|
| 987 |
// Specified number of uses.
|
| 988 |
case 2:
|
| 989 |
// Return FALSE if the code has been used up; handle bulk codes in a way
|
| 990 |
// that accounts for redemptions of individual bulk generated codes.
|
| 991 |
if (substr($data['promo_code'], 0, 7) === 'BULKGEN') {
|
| 992 |
$count = db_result(db_query("SELECT COUNT(*) FROM {uc_promo_code_redemptions} WHERE promo_code = '%s' AND bulk_code = '%s'", $data['promo_code'], $code));
|
| 993 |
if ($count >= $data['max_redemptions']) {
|
| 994 |
return FALSE;
|
| 995 |
}
|
| 996 |
}
|
| 997 |
else {
|
| 998 |
if ($data['redemptions'] >= $data['max_redemptions']) {
|
| 999 |
return FALSE;
|
| 1000 |
}
|
| 1001 |
}
|
| 1002 |
break;
|
| 1003 |
|
| 1004 |
// Expiration date.
|
| 1005 |
case 3:
|
| 1006 |
// Return FALSE if the code has expired.
|
| 1007 |
if (time() >= $data['expiration']) {
|
| 1008 |
return FALSE;
|
| 1009 |
}
|
| 1010 |
break;
|
| 1011 |
}
|
| 1012 |
|
| 1013 |
// Return FALSE if the promotion is no longer available or is disabled.
|
| 1014 |
$active = db_result(db_query("SELECT promo_id FROM {uc_promos} WHERE promo_id = %d AND promo_status = 1", $data['promo_id']));
|
| 1015 |
if (!$active) {
|
| 1016 |
return FALSE;
|
| 1017 |
}
|
| 1018 |
|
| 1019 |
$redeem_once = db_result(db_query("SELECT redeem_once FROM {uc_promos} WHERE promo_id = %d", $data['promo_id']));
|
| 1020 |
if ($redeem_once == 1) {
|
| 1021 |
$redeemed = db_result(db_query("SELECT COUNT(redemption_id) FROM {uc_promo_code_redemptions} WHERE promo_id = %d AND uid = %d", $data['promo_id'], $user->uid));
|
| 1022 |
if ($redeemed > 0) {
|
| 1023 |
return FALSE;
|
| 1024 |
}
|
| 1025 |
}
|
| 1026 |
|
| 1027 |
return TRUE;
|
| 1028 |
}
|
| 1029 |
|
| 1030 |
/**
|
| 1031 |
* Redeems a promotional code for a user by adding a redemption in the database
|
| 1032 |
* and updating the promotional code's data as needed.
|
| 1033 |
*
|
| 1034 |
* @param $code
|
| 1035 |
* The promotional code to redeem.
|
| 1036 |
* @param $user
|
| 1037 |
* The user account for which the code is being redeemed.
|
| 1038 |
* @param $bulk_id
|
| 1039 |
* If the code is a special BULKGEN code, $bulk_code should contain the actual
|
| 1040 |
* unique code used to redeem the promotion.
|
| 1041 |
*/
|
| 1042 |
function uc_promo_redeem_code($code, $user, $bulk_code = NULL) {
|
| 1043 |
// Load the appropriate promotion ID.
|
| 1044 |
$promo_id = db_result(db_query("SELECT promo_id FROM {uc_promo_codes} WHERE promo_code = '%s'", $code));
|
| 1045 |
|
| 1046 |
// Insert the redemption into the database.
|
| 1047 |
db_query("INSERT INTO {uc_promo_code_redemptions} (redemption_id, promo_code, bulk_code, promo_id, uid, redeemed) VALUES (%d, '%s', '%s', %d, %d, %d)",
|
| 1048 |
db_next_id('{uc_promo_code_redemptions}_redemption_id'), $code, $bulk_code,
|
| 1049 |
$promo_id, $user->uid, time());
|
| 1050 |
|
| 1051 |
// Update the promotion to reflect the redemption.
|
| 1052 |
db_query("UPDATE {uc_promo_codes} SET redemptions = redemptions + 1, last_redemption = %d WHERE promo_code = '%s'", time(), $code);
|
| 1053 |
}
|
| 1054 |
|
| 1055 |
// Downloads a file containing a bulk generated set of promotional codes.
|
| 1056 |
function uc_promo_code_bulkgen($promo_id, $code) {
|
| 1057 |
// Load the data directly from the database.
|
| 1058 |
$result = db_query("SELECT * FROM {uc_promo_codes} WHERE UPPER(promo_code) = '%s'", strtoupper($code));
|
| 1059 |
|
| 1060 |
if ($data = db_fetch_array($result)) {
|
| 1061 |
$filename = $code .'.csv';
|
| 1062 |
|
| 1063 |
header('Content-Type: application/octet-stream');
|
| 1064 |
header('Content-Disposition: attachment; filename="' . $filename . '";');
|
| 1065 |
|
| 1066 |
$parts = explode('-', $code);
|
| 1067 |
|
| 1068 |
$codes = '';
|
| 1069 |
for ($i = 0; $i < $parts[2]; $i++) {
|
| 1070 |
$codes .= strtoupper(str_pad(dechex($i), 5, 'U' . md5($data['bulkgen_seed'] . $i)) . substr(md5($i . $promo_id . $data['bulkgen_seed']), 0, $parts[1] - 5)) .",\n";
|
| 1071 |
}
|
| 1072 |
|
| 1073 |
echo rtrim($codes, ",\n");
|
| 1074 |
|
| 1075 |
exit();
|
| 1076 |
}
|
| 1077 |
else {
|
| 1078 |
return drupal_not_found();
|
| 1079 |
}
|
| 1080 |
}
|
| 1081 |
|
| 1082 |
// Workflow-ng action callback and form functions.
|
| 1083 |
function uc_promo_user_add_download($account, $settings) {
|
| 1084 |
_user_table_action('allow', $settings['fid'], $account->uid, NULL);
|
| 1085 |
}
|
| 1086 |
|
| 1087 |
function uc_promo_user_add_download_form($settings = array()) {
|
| 1088 |
if (!is_dir(variable_get('uc_file_base_dir', NULL))) {
|
| 1089 |
drupal_set_message(t('A file directory needs to be configured in <a href="!url">product feature settings</a> before a file can be selected.', array('!url' => url('admin/store/settings/products/edit/features'))), 'error');
|
| 1090 |
}
|
| 1091 |
$form['uc_file_filename'] = array(
|
| 1092 |
'#type' => 'textfield',
|
| 1093 |
'#title' => t('File download'),
|
| 1094 |
'#default_value' => $default_filename,
|
| 1095 |
'#autocomplete_path' => '_autocomplete_file',
|
| 1096 |
'#description' => t('The file that can be downloaded when product is purchased (enter a path relative to the %dir directory).', array('%dir' => variable_get('uc_file_base_dir', NULL))),
|
| 1097 |
);
|
| 1098 |
|
| 1099 |
return $form;
|
| 1100 |
}
|
| 1101 |
|
| 1102 |
function uc_promo_user_add_download_validate($form_id, $form_values) {
|
| 1103 |
if (!db_result(db_query("SELECT fid FROM {uc_files} WHERE filename = '%s'", $form_values['uc_file_filename']))) {
|
| 1104 |
form_set_error('uc_file_filename', t('%file is not a valid file or directory inside file download directory.', array('%file' => $form_values['uc_file_filename'])));
|
| 1105 |
}
|
| 1106 |
}
|
| 1107 |
|
| 1108 |
function uc_promo_user_add_download_submit($form_id, $form_values) {
|
| 1109 |
return array('fid' => db_result(db_query("SELECT fid FROM {uc_files} WHERE filename = '%s'", $form_values['uc_file_filename'])));
|
| 1110 |
}
|
| 1111 |
|