Parent Directory
|
Revision Log
|
Revision Graph
Begin the Ubercart 6.x-2.x branch.
| 1 | <?php |
| 2 | // $Id$ |
| 3 | |
| 4 | /** |
| 5 | * @file |
| 6 | * Allows products to be associated with downloadable files. |
| 7 | * |
| 8 | * uc_file allows ubercart products to have associated downloadable files. |
| 9 | * Optionally, after a customer purchases such a product they will be sent a |
| 10 | * download link via email. Additionally, after logging on a customer can |
| 11 | * download files via their account page. Optionally, an admininstrator can set |
| 12 | * restrictions on how and when files are downloaded. |
| 13 | * |
| 14 | * Development sponsored by the Ubercart project. http://www.ubercart.org |
| 15 | */ |
| 16 | |
| 17 | define('UC_FILE_PAGER_SIZE', 50); |
| 18 | define('UC_FILE_REQUEST_LIMIT', 50); |
| 19 | define('UC_FILE_BYTE_SIZE', 1024); |
| 20 | |
| 21 | /* **************************************************************************** * |
| 22 | * Hook Functions (Drupal) * |
| 23 | * **************************************************************************** */ |
| 24 | |
| 25 | /** |
| 26 | * Implementation of hook_form_alter(). |
| 27 | */ |
| 28 | function uc_file_form_alter(&$form, &$form_state, $form_id) { |
| 29 | if ($form_id == "uc_product_feature_settings_form") { |
| 30 | $form['#submit'][] = 'uc_file_feature_settings_submit'; |
| 31 | $form['#validate'][] = 'uc_file_feature_settings_validate'; |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | /** |
| 36 | * Implementation of hook_menu(). |
| 37 | */ |
| 38 | function uc_file_menu() { |
| 39 | $items = array(); |
| 40 | |
| 41 | $items['_autocomplete_file'] = array( |
| 42 | 'page callback' => '_autocomplete_filename', |
| 43 | 'access arguments' => array('administer products'), |
| 44 | 'type' => MENU_CALLBACK, |
| 45 | ); |
| 46 | $items['admin/store/products/files'] = array( |
| 47 | 'title' => 'View file downloads', |
| 48 | 'description' => 'View all file download features on products.', |
| 49 | 'page callback' => 'uc_file_files_admin', |
| 50 | 'access arguments' => array('administer products'), |
| 51 | 'type' => MENU_NORMAL_ITEM, |
| 52 | ); |
| 53 | if (module_exists('uc_notify')) { |
| 54 | $items['admin/store/settings/notify/edit/file'] = array( |
| 55 | 'title' => 'File download', |
| 56 | 'description' => 'Edit the notification settings for purchased file downloads.', |
| 57 | 'page callback' => 'drupal_get_form', |
| 58 | 'page arguments' => array('uc_file_notify_settings'), |
| 59 | 'access arguments' => array('administer store'), |
| 60 | 'type' => MENU_LOCAL_TASK, |
| 61 | ); |
| 62 | } |
| 63 | $items['user/%user/files'] = array( |
| 64 | 'title' => 'Files', |
| 65 | 'description' => 'View your purchased files.', |
| 66 | 'page callback' => 'uc_file_user_downloads', |
| 67 | 'page arguments' => array(1), |
| 68 | 'access callback' => 'uc_file_user_access', |
| 69 | 'access arguments' => array(1), |
| 70 | 'type' => MENU_LOCAL_TASK, |
| 71 | ); |
| 72 | $items['download/%/%'] = array( |
| 73 | 'page callback' => '_file_download', |
| 74 | 'page arguments' => array(1, 2), |
| 75 | 'access arguments' => array('download file'), |
| 76 | 'type' => MENU_CALLBACK, |
| 77 | ); |
| 78 | |
| 79 | return $items; |
| 80 | } |
| 81 | |
| 82 | function uc_file_user_access($account) { |
| 83 | global $user; |
| 84 | return $user->uid && (user_access('view all downloads') || $user->uid == $account->uid); |
| 85 | } |
| 86 | |
| 87 | function uc_file_init() { |
| 88 | drupal_add_css(drupal_get_path('module', 'uc_file') .'/uc_file.css'); |
| 89 | } |
| 90 | |
| 91 | /** |
| 92 | * Implementation of hook_perm(). |
| 93 | */ |
| 94 | function uc_file_perm() { |
| 95 | return array('download file', 'view all downloads'); |
| 96 | } |
| 97 | |
| 98 | function uc_file_theme() { |
| 99 | return array( |
| 100 | 'uc_file_downloads_token' => array( |
| 101 | 'arguments' => array('file_downloads' => NULL), |
| 102 | ), |
| 103 | 'uc_file_files_form' => array( |
| 104 | 'arguments' => array('form' => NULL), |
| 105 | ), |
| 106 | ); |
| 107 | } |
| 108 | |
| 109 | /** |
| 110 | * Implementation of hook_user(). |
| 111 | */ |
| 112 | function uc_file_user($op, &$edit, &$account, $category = NULL) { |
| 113 | global $user; |
| 114 | switch ($op) { |
| 115 | case 'delete': |
| 116 | _user_table_action('remove', NULL, $account->uid); |
| 117 | break; |
| 118 | case 'form': |
| 119 | if (user_access('administer users') && (is_null($category) || $category == 'account')) { |
| 120 | $file_downloads = db_query("SELECT * FROM {uc_file_users} as u INNER JOIN {uc_files} as f ON u.fid = f.fid WHERE uid = %d", $account->uid); |
| 121 | $files = db_query("SELECT * FROM {uc_files} ORDER BY filename ASC"); |
| 122 | $available_downloads = array(); |
| 123 | $available_files = array(); |
| 124 | while ($file_download = db_fetch_object($file_downloads)) { |
| 125 | $available_downloads[$file_download->key] = $file_download->filename; |
| 126 | } |
| 127 | while ($file = db_fetch_object($files)) { |
| 128 | if (substr($file->filename, -1) != '/' && substr($file->filename, -1) != '\\') { |
| 129 | $available_files[$file->fid] = $file->filename; |
| 130 | } |
| 131 | } |
| 132 | $form['file'] = array( |
| 133 | '#type' => 'fieldset', |
| 134 | '#title' => t('File downloads'), |
| 135 | '#collapsible' => TRUE, |
| 136 | '#collapsed' => TRUE, |
| 137 | '#weight' => 10 |
| 138 | ); |
| 139 | $form['file']['remove_file'] = array( |
| 140 | '#type' => 'select', |
| 141 | '#title' => t('Remove file'), |
| 142 | '#multiple' => TRUE, |
| 143 | '#description' => t('Select a file to remove as a download. Hold Ctrl to select or unselect multiple files.'), |
| 144 | '#options' => $available_downloads, |
| 145 | ); |
| 146 | $form['file']['add_file'] = array( |
| 147 | '#type' => 'select', |
| 148 | '#title' => t('Add file'), |
| 149 | '#multiple' => TRUE, |
| 150 | '#description' => t('Select a file to add as a download. Hold Ctrl to select or unselect multiple files.'), |
| 151 | '#options' => $available_files, |
| 152 | ); |
| 153 | } |
| 154 | return $form; |
| 155 | break; |
| 156 | case 'submit': |
| 157 | if (!empty($edit['remove_file'])) { |
| 158 | foreach ($edit['remove_file'] as $hash_key) { |
| 159 | if (!is_null($hash_key)) { |
| 160 | _user_table_action('remove', NULL, $account->uid, $hash_key); |
| 161 | } |
| 162 | } |
| 163 | } |
| 164 | if (!empty($edit['add_file'])) { |
| 165 | foreach ($edit['add_file'] as $fid) { |
| 166 | $pfid = db_result(db_query("SELECT pfid FROM {uc_file_products} WHERE fid = %d", $fid)); |
| 167 | _user_table_action('allow', $fid, $account->uid, $pfid); |
| 168 | } |
| 169 | } |
| 170 | break; |
| 171 | case 'view': |
| 172 | $existing_download = db_result(db_query("SELECT fid FROM {uc_file_users} WHERE uid = %d", $account->uid)); |
| 173 | if ((user_access('view all downloads') || $user->uid == $account->uid) && $user->uid && $existing_download) { |
| 174 | $items['uc_file_download'] = array( |
| 175 | 'value' => l(t('Click here to view your file downloads.'), 'user/'. $account->uid .'/files'), |
| 176 | 'class' => 'member', |
| 177 | ); |
| 178 | return array(t('File downloads') => $items); |
| 179 | } |
| 180 | break; |
| 181 | default: |
| 182 | break; |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | /* **************************************************************************** * |
| 187 | * Übercart Hooks * |
| 188 | * **************************************************************************** */ |
| 189 | |
| 190 | /** |
| 191 | * Implementation of hook_cart_item(). |
| 192 | */ |
| 193 | function uc_file_cart_item($op, &$item) { |
| 194 | switch ($op) { |
| 195 | case 'can_ship': |
| 196 | $files = db_query("SELECT shippable, model FROM {uc_file_products} as fp INNER JOIN {uc_product_features} as pf ON pf.pfid = fp.pfid WHERE nid = %d", $item->nid); |
| 197 | while ($file = db_fetch_object($files)) { |
| 198 | $sku = (empty($item->data['model'])) ? $item->model : $item->data['model']; |
| 199 | if ($sku == $file->model || empty($file->model)) { |
| 200 | return ($file->shippable) ? TRUE : FALSE; |
| 201 | } |
| 202 | } |
| 203 | break; |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | /** |
| 208 | * Implementation of hook_order(). |
| 209 | */ |
| 210 | function uc_file_order($op, $order, $status) { |
| 211 | global $user; |
| 212 | |
| 213 | switch ($op) { |
| 214 | case 'update': |
| 215 | if (($order->uid > 0) && ($order_user = user_load(array('uid' => $order->uid))) !== FALSE) { |
| 216 | foreach ($order->products as $product) { |
| 217 | $files = db_query("SELECT fp.fid, fp.pfid, model, f.filename FROM {uc_file_products} AS fp INNER JOIN {uc_product_features} AS pf ON pf.pfid = fp.pfid INNER JOIN {uc_files} as f ON f.fid = fp.fid WHERE nid = %d", $product->nid); |
| 218 | while ($file = db_fetch_object($files)) { |
| 219 | if (($file->model == $product->model || empty($file->model)) && $status == variable_get('uc_file_default_order_status', 'completed')) { |
| 220 | $downloads = _user_table_action('allow', $file->fid, $order_user->uid, $file->pfid); |
| 221 | $user_downloads = (!empty($user_downloads)) ? array_merge($user_downloads, $downloads) : $downloads ; |
| 222 | if (_get_dir_file_ids($file->fid)) { |
| 223 | $comment = t('User can now download files in the directory %dir.', array('%dir' => $file->filename)); |
| 224 | } |
| 225 | else { |
| 226 | $comment = t('User can now download the file %file.', array('%file' => basename($file->filename))); |
| 227 | } |
| 228 | uc_order_comment_save($order->order_id, $user->uid, $comment); |
| 229 | } |
| 230 | } |
| 231 | } |
| 232 | if (!is_null($user_downloads)) { |
| 233 | _email_file_download($order_user, $order, $user_downloads); |
| 234 | } |
| 235 | } |
| 236 | break; |
| 237 | default: |
| 238 | break; |
| 239 | } |
| 240 | } |
| 241 | |
| 242 | /** |
| 243 | * Implementation of hook_product_feature(). |
| 244 | */ |
| 245 | function uc_file_product_feature() { |
| 246 | $features[] = array( |
| 247 | 'id' => 'file', |
| 248 | 'title' => t('File download'), |
| 249 | 'callback' => 'uc_file_feature_form', |
| 250 | 'delete' => 'uc_file_feature_delete', |
| 251 | 'settings' => 'uc_file_feature_settings', |
| 252 | ); |
| 253 | |
| 254 | return $features; |
| 255 | } |
| 256 | |
| 257 | /** |
| 258 | * Implementation of hook_store_status(). |
| 259 | */ |
| 260 | function uc_file_store_status() { |
| 261 | $message = array(); |
| 262 | if (!is_dir(variable_get('uc_file_base_dir', NULL))) { |
| 263 | $message[] = array( |
| 264 | 'status' => 'warning', |
| 265 | 'title' => t('File Downloads'), |
| 266 | 'desc' => t('The file downloads directory is not valid or set. Set a valid directory in the <a href="!url">product feature settings</a> under the file download settings fieldset.', array('!url' => url('admin/store/settings/products/edit/features'))), |
| 267 | ); |
| 268 | } |
| 269 | else { |
| 270 | $message[] = array( |
| 271 | 'status' => 'ok', |
| 272 | 'title' => t('File Downloads'), |
| 273 | 'desc' => t('The file downloads directory has been set and is working.'), |
| 274 | ); |
| 275 | } |
| 276 | return $message; |
| 277 | } |
| 278 | |
| 279 | /** |
| 280 | * Implementation of hook_token_list(). |
| 281 | */ |
| 282 | function uc_file_token_list($type = 'all') { |
| 283 | if ($type == 'uc_file' || $type == 'ubercart' || $type == 'all') { |
| 284 | $tokens['uc_file']['file-downloads'] = t('The list of file download links (if any) associated with an order'); |
| 285 | } |
| 286 | |
| 287 | return $tokens; |
| 288 | } |
| 289 | |
| 290 | /** |
| 291 | * Implementation of hook_token_values(). |
| 292 | */ |
| 293 | function uc_file_token_values($type, $object = NULL) { |
| 294 | switch ($type) { |
| 295 | case 'uc_file': |
| 296 | if (!empty($object)) { |
| 297 | $values['file-downloads'] = theme('uc_file_downloads_token', $object); |
| 298 | } |
| 299 | break; |
| 300 | } |
| 301 | |
| 302 | return $values; |
| 303 | } |
| 304 | |
| 305 | /** |
| 306 | * Implementation of hook_uc_message(). |
| 307 | */ |
| 308 | function uc_file_uc_message() { |
| 309 | $messages['uc_file_download_subject'] = t("File Downloads for Order# [order-id]"); |
| 310 | $messages['uc_file_download_message'] = t("Your order (order# [order-link]) at [store-name] included file download(s). You may access them with the following link(s):\n\n[file-downloads]\n\nAfter downloading these files these links will have expired. If you need to download the files again, you can login at [site-login] and visit the \"My Account\" section of the site.\n\nThanks again, \n\n[store-name]\n[site-slogan]"); |
| 311 | |
| 312 | return $messages; |
| 313 | } |
| 314 | |
| 315 | /* **************************************************************************** * |
| 316 | * Callback Functions, Forms, and Tables * |
| 317 | * **************************************************************************** */ |
| 318 | |
| 319 | /** |
| 320 | * Theme file download links token |
| 321 | */ |
| 322 | function theme_uc_file_downloads_token($file_downloads) { |
| 323 | $output = ''; |
| 324 | foreach ($file_downloads as $file_download) { |
| 325 | $filename = basename(db_result(db_query("SELECT filename FROM {uc_files} WHERE fid = %d", $file_download->fid))); |
| 326 | $download_url = url('download/'. $file_download->fid .'/'. $file_download->key, NULL, NULL, TRUE); |
| 327 | $output .= '<a href="'. $download_url .'">'. $download_url ."</a>\n"; |
| 328 | } |
| 329 | return $output; |
| 330 | } |
| 331 | |
| 332 | /** |
| 333 | * product_feature delete function |
| 334 | */ |
| 335 | function uc_file_feature_delete($feature) { |
| 336 | db_query("DELETE FROM {uc_file_products} WHERE pfid = %d", $feature['pfid']); |
| 337 | } |
| 338 | |
| 339 | /** |
| 340 | * Form builder for hook_product_feature |
| 341 | */ |
| 342 | function uc_file_feature_form($form_state, $node, $feature) { |
| 343 | if (!is_dir(variable_get('uc_file_base_dir', NULL))) { |
| 344 | 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'); |
| 345 | } |
| 346 | _file_table_action('insert'); |
| 347 | $models = (!_get_adjustment_models($node->nid)) ? array(NULL => t('Any'), $node->model => $node->model) : array(NULL => t('Any'), $node->model => $node->model) + _get_adjustment_models($node->nid); |
| 348 | |
| 349 | if (!empty($feature)) { |
| 350 | $file_product = db_fetch_object(db_query("SELECT * FROM {uc_file_products} as p LEFT JOIN {uc_files} as f ON p.fid = f.fid WHERE pfid = %d", $feature['pfid'])); |
| 351 | $default_feature = $feature['pfid']; |
| 352 | $default_model = $file_product->model; |
| 353 | $default_filename = $file_product->filename; |
| 354 | $default_description = $file_product->description; |
| 355 | $default_shippable = $file_product->shippable; |
| 356 | } |
| 357 | else { |
| 358 | $default_shippable = $node->shippable; |
| 359 | } |
| 360 | |
| 361 | $form['nid'] = array( |
| 362 | '#type' => 'value', |
| 363 | '#value' => $node->nid, |
| 364 | ); |
| 365 | $form['pfid'] = array( |
| 366 | '#type' => 'value', |
| 367 | '#value' => $default_feature, |
| 368 | ); |
| 369 | $form['uc_file_model'] = array( |
| 370 | '#type' => 'select', |
| 371 | '#title' => t('Model/SKU'), |
| 372 | '#default_value' => $default_model, |
| 373 | '#description' => t('This is the model/SKU that will need to be purchased to obtain the file download.'), |
| 374 | '#options' => $models, |
| 375 | ); |
| 376 | $form['uc_file_filename'] = array( |
| 377 | '#type' => 'textfield', |
| 378 | '#title' => t('File download'), |
| 379 | '#default_value' => $default_filename, |
| 380 | '#autocomplete_path' => '_autocomplete_file', |
| 381 | '#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))), |
| 382 | ); |
| 383 | $form['uc_file_description'] = array( |
| 384 | '#type' => 'textfield', |
| 385 | '#title' => t('Description'), |
| 386 | '#default_value' => $default_description, |
| 387 | '#maxlength' => 255, |
| 388 | '#description' => t('A description of the download associated with the product.'), |
| 389 | ); |
| 390 | $form['uc_file_shippable'] = array( |
| 391 | '#type' => 'checkbox', |
| 392 | '#title' => t('Shippable product'), |
| 393 | '#default_value' => $default_shippable, |
| 394 | '#description' => t('Check if this product model/SKU file download is also associated with a shippable product.'), |
| 395 | ); |
| 396 | |
| 397 | return uc_product_feature_form($form); |
| 398 | } |
| 399 | |
| 400 | function uc_file_feature_form_validate($form, &$form_state) { |
| 401 | if (!db_result(db_query("SELECT fid FROM {uc_files} WHERE filename = '%s'", $form_state['values']['uc_file_filename']))) { |
| 402 | form_set_error('uc_file_filename', t('%file is not a valid file or directory inside file download directory.', array('%file' => $form_state['values']['uc_file_filename']))); |
| 403 | } |
| 404 | } |
| 405 | |
| 406 | function uc_file_feature_form_submit($form, &$form_state) { |
| 407 | global $user; |
| 408 | $fid = db_result(db_query("SELECT fid FROM {uc_files} WHERE filename = '%s'", $form_state['values']['uc_file_filename'])); |
| 409 | //Build product feature descriptions |
| 410 | $description = (empty($form_state['values']['uc_file_model'])) ? t('<strong>SKU:</strong> Any<br/>') : t('<strong>SKU:</strong> !sku<br/>', array('!sku' => $form_state['values']['uc_file_model'])); |
| 411 | if (is_dir(variable_get('uc_file_base_dir', NULL) ."/". $form_state['values']['uc_file_filename'])) { |
| 412 | $description .= t('<strong>Directory:</strong> !dir<br/>', array('!dir' => $form_state['values']['uc_file_filename'])); |
| 413 | } |
| 414 | else { |
| 415 | $description .= t('<strong>File:</strong> !file<br/>', array('!file' => basename($form_state['values']['uc_file_filename'])));; |
| 416 | } |
| 417 | $shippable = ($form_state['values']['uc_file_shippable']) ? 1 : 0; |
| 418 | $description .= ($shippable) ? t('<strong>Shippable:</strong> Yes') : t('<strong>Shippable:</strong> No'); |
| 419 | |
| 420 | //Insert or update uc_file_product table |
| 421 | if (empty($form_state['values']['pfid'])) { |
| 422 | db_query("INSERT INTO {uc_file_products} (fid, model, description, shippable) VALUES (%d, '%s', '%s', %d)", $fid, $form_state['values']['uc_file_model'], $form_state['values']['uc_file_description'], $shippable); |
| 423 | $pfid = db_last_insert_id('uc_product_features', 'pfid'); |
| 424 | } |
| 425 | else { |
| 426 | $pfid = $form_state['values']['pfid']; |
| 427 | db_query("UPDATE {uc_file_products} SET fid = %d, model = '%s', description = '%s', shippable = %d WHERE pfid = %d", $fid, $form_state['values']['uc_file_model'], $form_state['values']['uc_file_description'], $shippable, $pfid); |
| 428 | } |
| 429 | |
| 430 | $data = array( |
| 431 | 'pfid' => $pfid, |
| 432 | 'nid' => $form_state['values']['nid'], |
| 433 | 'fid' => 'file', |
| 434 | 'description' => $description, |
| 435 | ); |
| 436 | |
| 437 | $form_state['redirect'] = uc_product_feature_save($data); |
| 438 | } |
| 439 | |
| 440 | /** |
| 441 | * Form builder for file settings |
| 442 | */ |
| 443 | function uc_file_feature_settings() { |
| 444 | uc_add_js('$(document).ready(function() { if ($("#edit-uc-file-download-limit-duration-granularity").val() == "never") {$("#edit-uc-file-download-limit-duration-qty").attr("disabled", "disabled").val("");} });', 'inline'); |
| 445 | $statuses = array(); |
| 446 | foreach (uc_order_status_list('general') as $status) { |
| 447 | $statuses[$status['id']] = $status['title']; |
| 448 | } |
| 449 | |
| 450 | $form['uc_file_default_order_status'] = array( |
| 451 | '#type' => 'select', |
| 452 | '#title' => t('Order status'), |
| 453 | '#default_value' => variable_get('uc_file_default_order_status', 'completed'), |
| 454 | '#description' => t('Where in the order status the user will be given the file download. Be aware that if payments are processed automatically, this happens before anonymous customers have an account created. This order status should not be reached before the user account exists.'), |
| 455 | '#options' => $statuses, |
| 456 | ); |
| 457 | $form['uc_file_base_dir'] = array( |
| 458 | '#type' => 'textfield', |
| 459 | '#title' => t('Files path'), |
| 460 | '#description' => t('The absolute path (or relative to Drupal root) where files used for file downloads are located. For security reasons, it is reccommended to choose a path outside the web root.'), |
| 461 | '#default_value' => variable_get('uc_file_base_dir', NULL), |
| 462 | ); |
| 463 | $form['uc_file_file_mask'] = array( |
| 464 | '#type' => 'textfield', |
| 465 | '#title' => t('Files mask'), |
| 466 | '#description' => t("The regular expression used for masking files in files directory. Don't change unless you know what you're doing."), |
| 467 | '#default_value' => variable_get('uc_file_file_mask', ".*"), |
| 468 | ); |
| 469 | $form['uc_file_download_limit'] = array( |
| 470 | '#type' => 'fieldset', |
| 471 | '#title' => t('Download limits'), |
| 472 | '#collapsible' => TRUE, |
| 473 | '#collapsed' => FALSE, |
| 474 | ); |
| 475 | $form['uc_file_download_limit']['uc_file_download_limit_number'] = array( |
| 476 | '#type' => 'textfield', |
| 477 | '#title' => t('Downloads'), |
| 478 | '#description' => t("The number of times a file can be downloaded. Leave empty to set no limit."), |
| 479 | '#default_value' => variable_get('uc_file_download_limit_number', NULL), |
| 480 | '#maxlength' => 4, |
| 481 | '#size' => 4, |
| 482 | ); |
| 483 | $form['uc_file_download_limit']['uc_file_download_limit_addresses'] = array( |
| 484 | '#type' => 'textfield', |
| 485 | '#title' => t('IP addresses'), |
| 486 | '#description' => t("The number of unique IPs that a file can be downloaded from. Leave empty to set no limit."), |
| 487 | '#default_value' => variable_get('uc_file_download_limit_addresses', NULL), |
| 488 | '#maxlength' => 4, |
| 489 | '#size' => 4, |
| 490 | ); |
| 491 | $form['uc_file_download_limit']['uc_file_download_limit_duration_qty'] = array( |
| 492 | '#type' => 'textfield', |
| 493 | '#title' => t('Time'), |
| 494 | '#default_value' => (variable_get('uc_file_download_limit_duration_granularity', 'never') == 'never') ? NULL : variable_get('uc_file_download_limit_duration_qty', NULL), |
| 495 | '#size' => 4, |
| 496 | '#maxlength' => 4, |
| 497 | '#prefix' => '<div class="duration">', |
| 498 | '#suffix' => '</div>', |
| 499 | ); |
| 500 | $form['uc_file_download_limit']['uc_file_download_limit_duration_granularity'] = array( |
| 501 | '#type' => 'select', |
| 502 | '#options' => array( |
| 503 | 'never' => t('never'), |
| 504 | 'day' => t('day(s)'), |
| 505 | 'week' => t('week(s)'), |
| 506 | 'month' => t('month(s)'), |
| 507 | 'year' => t('year(s)') |
| 508 | ), |
| 509 | '#default_value' => variable_get('uc_file_download_limit_duration_granularity', 'never'), |
| 510 | '#attributes' => array( |
| 511 | 'onchange' => 'if (this.value == "never") {$("#edit-uc-file-download-limit-duration-qty").attr("disabled", "disabled").val("");} else {$("#edit-uc-file-download-limit-duration-qty").removeAttr("disabled");}' |
| 512 | ), |
| 513 | '#description' => t('How long after a product has been purchased until its file download expires.'), |
| 514 | '#prefix' => '<div class="duration">', |
| 515 | '#suffix' => '</div>', |
| 516 | ); |
| 517 | return $form; |
| 518 | } |
| 519 | |
| 520 | function uc_file_feature_settings_validate($form, &$form_state) { |
| 521 | if (!empty($form_state['values']['uc_file_base_dir']) && $form_state['values']['op'] == t('Save configuration') && !is_dir($form_state['values']['uc_file_base_dir'])) { |
| 522 | form_set_error('uc_file_base_dir', t('%dir is not a valid file or directory', array('%dir' => $form_state['values']['uc_file_base_dir']))); |
| 523 | } |
| 524 | } |
| 525 | |
| 526 | function uc_file_feature_settings_submit($form, &$form_state) { |
| 527 | $action = (empty($form_state['values']['uc_file_base_dir'])) ? 'empty' : 'insert'; |
| 528 | _file_table_action($action); |
| 529 | _file_table_action('refresh'); |
| 530 | } |
| 531 | |
| 532 | /** |
| 533 | * Page builder for file products admin |
| 534 | */ |
| 535 | function uc_file_files_admin() { |
| 536 | _file_table_action('insert'); |
| 537 | return drupal_get_form('uc_file_files_form'); |
| 538 | } |
| 539 | |
| 540 | /** |
| 541 | * Implementation of theme_form($form) |
| 542 | */ |
| 543 | function theme_uc_file_files_form($form) { |
| 544 | $output = ''; |
| 545 | |
| 546 | //Only display files on 1st form step |
| 547 | if ($form['step']['#value'] == 1) { |
| 548 | $files = array(); |
| 549 | $args = array('form' => $form); |
| 550 | $header = tablesort_sql(tapir_get_header('uc_file_files_table', array())); |
| 551 | $order = (empty($header)) ? "ORDER BY f.filename ASC" : $header .", f.filename ASC"; |
| 552 | $count_query = "SELECT COUNT(*) FROM {uc_files}"; |
| 553 | $query = pager_query("SELECT n.nid, f.filename, n.title, fp.model, f.fid, pf.pfid FROM {uc_files} as f LEFT JOIN {uc_file_products} as fp ON (f.fid = fp.fid) LEFT JOIN {uc_product_features} as pf ON (fp.pfid = pf.pfid) LEFT JOIN {node} as n ON (pf.nid = n.nid) ". $order, UC_FILE_PAGER_SIZE, 0, $count_query); |
| 554 | while ($file = db_fetch_object($query)) { |
| 555 | $files[] = $file; |
| 556 | } |
| 557 | $args['files'] = $files; |
| 558 | |
| 559 | $output .= '<p>'. t('File downloads can be attached to any Ubercart product as a product feature. For security reasons the <a href="!download_url">file downloads directory</a> is separated from the Drupal <a href="!file_url">file system</a>. Here are the list of files (and their associated Ubercart products) that can be used for file downloads.', array('!download_url' => url('admin/store/settings/products/edit/features'), '!file_url' => url('admin/settings/file-system'))) .'</p>'; |
| 560 | $output .= drupal_render($form['uc_file_action']); |
| 561 | $output .= tapir_get_table('uc_file_files_table', $args); |
| 562 | $output .= theme('pager', NULL, UC_FILE_PAGER_SIZE, 0); |
| 563 | } |
| 564 | |
| 565 | //Checkboxes already rendered in uc_file_files_table |
| 566 | foreach ($form as $form_element => $form_data) { |
| 567 | if (strpos($form_element, 'file_select_') !== FALSE) { |
| 568 | unset($form[$form_element]); |
| 569 | } |
| 570 | } |
| 571 | $output .= drupal_render($form); |
| 572 | |
| 573 | return $output; |
| 574 | } |
| 575 | |
| 576 | /** |
| 577 | * Form builder for file products admin |
| 578 | */ |
| 579 | function uc_file_files_form($form_state) { |
| 580 | if (!isset($form_state['step']) || $form_state['step'] < 2) { |
| 581 | //Display File Options and File checkboxes |
| 582 | $files = db_query("SELECT * FROM {uc_files}"); |
| 583 | $file_actions = array( |
| 584 | 'uc_file_delete' => t('Delete file(s)'), |
| 585 | 'uc_file_upload' => t('Upload file') |
| 586 | ); |
| 587 | |
| 588 | //Check any if any hook_file_action('info', $args) are implemented |
| 589 | foreach (module_implements('file_action') as $module) { |
| 590 | $name = $module .'_file_action'; |
| 591 | $result = $name('info', NULL); |
| 592 | if (is_array($result)) { |
| 593 | foreach ($result as $key => $action) { |
| 594 | if ($key != 'uc_file_delete' && $key != 'uc_file_upload') { |
| 595 | $file_actions[$key] = $action; |
| 596 | } |
| 597 | } |
| 598 | } |
| 599 | } |
| 600 | |
| 601 | while ($file = db_fetch_object($files)) { |
| 602 | $form['file_select_'. $file->fid] = array('#type' => 'checkbox'); |
| 603 | } |
| 604 | $form['uc_file_action'] = array( |
| 605 | '#type' => 'fieldset', |
| 606 | '#title' => t('File options'), |
| 607 | '#collapsible' => FALSE, |
| 608 | '#collapsed' => FALSE, |
| 609 | ); |
| 610 | $form['uc_file_action']['action'] = array( |
| 611 | '#type' => 'select', |
| 612 | '#title' => t('Action'), |
| 613 | '#options' => $file_actions, |
| 614 | '#prefix' => '<div class="duration">', |
| 615 | '#suffix' => '</div>', |
| 616 | ); |
| 617 | $form['uc_file_action']['submit'] = array( |
| 618 | '#type' => 'submit', |
| 619 | '#value' => t('Perform action'), |
| 620 | '#prefix' => '<div class="duration">', |
| 621 | '#suffix' => '</div>', |
| 622 | ); |
| 623 | } |
| 624 | else { |
| 625 | //Perform File Action (Upload, Delete, hooked in actions) |
| 626 | $file_ids = array(); |
| 627 | foreach ($form_state['values'] as $name => $form_value) { |
| 628 | if (strpos($name, 'file_select_') !== FALSE) { |
| 629 | $file_ids[] = intval(str_replace('file_select_', '', $name)); |
| 630 | } |
| 631 | } |
| 632 | $form['file_ids'] = array('#type' => 'value', '#value' => $file_ids); |
| 633 | $form['action'] = array('#type' => 'value', '#value' => $form_state['values']['action']); |
| 634 | |
| 635 | //Switch to an action to perform |
| 636 | switch ($form_state['values']['action']) { |
| 637 | case 'uc_file_delete': //Delete selected files |
| 638 | foreach ($file_ids as $file_id) { |
| 639 | $filename = db_result(db_query("SELECT filename FROM {uc_files} WHERE fid = %d", $file_id)); |
| 640 | $filename = (substr($filename, -1) == "/") ? $filename .' ('. t('directory') .')' : $filename; |
| 641 | $file_list[] = $filename; |
| 642 | } |
| 643 | $form['files'] = array( |
| 644 | '#type' => 'markup', |
| 645 | '#value' => theme_item_list($file_list, NULL, 'ul', array('class' => 'file-name')), |
| 646 | ); |
| 647 | $form['recurse_directories'] = array( |
| 648 | '#type' => 'checkbox', |
| 649 | '#title' => t('Delete selected directories and their sub directories'), |
| 650 | ); |
| 651 | $form = confirm_form($form, t('Delete the following file(s)?'), 'admin/store/products/files', t('Deleting a file will remove all its associated file downloads and product features. Removing a directory will remove any files it contains and their associated file downloads and product features.'), t('Yes'), t('No')); |
| 652 | break; |
| 653 | case 'uc_file_upload': //Upload file |
| 654 | drupal_set_title(t('Upload File')); |
| 655 | $max_bytes = trim(ini_get('post_max_size')); |
| 656 | $directories = array('' => '/'); |
| 657 | |
| 658 | switch (strtolower($max_bytes{strlen($max_bytes)-1})) { |
| 659 | case 'g': |
| 660 | $max_bytes *= 1024; |
| 661 | case 'm': |
| 662 | $max_bytes *= 1024; |
| 663 | case 'k': |
| 664 | $max_bytes *= 1024; |
| 665 | } |
| 666 | |
| 667 | $files = db_query("SELECT * FROM {uc_files}"); |
| 668 | while ($file = db_fetch_object($files)) { |
| 669 | if (is_dir(variable_get('uc_file_base_dir', NULL) ."/". $file->filename)) { |
| 670 | $directories[$file->filename] = $file->filename; |
| 671 | } |
| 672 | } |
| 673 | |
| 674 | $form['#attributes']['enctype'] = 'multipart/form-data'; |
| 675 | $form['upload_dir'] = array( |
| 676 | '#type' => 'select', |
| 677 | '#title' => t('Directory'), |
| 678 | '#description' => t('The directory to upload the file to. The default directory is the root of the file downloads directory.'), |
| 679 | '#options' => $directories, |
| 680 | ); |
| 681 | $form['upload'] = array( |
| 682 | '#type' => 'file', |
| 683 | '#title' => t('File'), |
| 684 | '#description' => t('The maximum file size that can be uploaded is %size bytes. You will need to use a different method to upload the file to the directory (e.g. FTP, SSH) if your file exceeds this size.', array('%size' => number_format($max_bytes))), |
| 685 | ); |
| 686 | $form['submit'] = array( |
| 687 | '#type' => 'submit', |
| 688 | '#value' => t('Upload'), |
| 689 | ); |
| 690 | break; |
| 691 | default: |
| 692 | //Check any if any hook_file_action('form', $args) are implemented |
| 693 | foreach (module_implements('file_action') as $module) { |
| 694 | $name = $module .'_file_action'; |
| 695 | $result = $name('form', array('action' => $form_state['values']['action'], 'file_ids' => $file_ids)); |
| 696 | $form = (is_array($result)) ? array_merge($form, $result) : $form; |
| 697 | } |
| 698 | break; |
| 699 | } |
| 700 | } |
| 701 | |
| 702 | return $form; |
| 703 | } |
| 704 | |
| 705 | function uc_file_files_form_validate($form, &$form_state) { |
| 706 | switch ($form_state['step']) { |
| 707 | case 2: |
| 708 | switch ($form_state['values']['action']) { |
| 709 | case 'uc_file_delete': //Nothing to validate for file delete |
| 710 | break; |
| 711 | case 'uc_file_upload': |
| 712 | //Check any if any hook_file_action('validate', $args) are implemented |
| 713 | if ($temp_file = file_save_upload('upload', array())) { |
| 714 | foreach (module_implements('file_action') as $module) { |
| 715 | $name = $module .'_file_action'; |
| 716 | $result = $name('upload_validate', array('file_object' => $temp_file, 'form_id' => $form_id, 'form_state' => $form_state)); |
| 717 | } |
| 718 | $form_state['storage']['temp_file'] = $temp_file; |
| 719 | } |
| 720 | else { |
| 721 | form_set_error('', t('An error occurred while uploading the file')); |
| 722 | } |
| 723 | break; |
| 724 | default: |
| 725 | //Check any if any hook_file_action('validate', $args) are implemented |
| 726 | foreach (module_implements('file_action') as $module) { |
| 727 | $name = $module .'_file_action'; |
| 728 | $result = $name('validate', array('form_id' => $form_id, 'form_state' => $form_state)); |
| 729 | } |
| 730 | break; |
| 731 | } |
| 732 | break; |
| 733 | default: |
| 734 | break; |
| 735 | } |
| 736 | } |
| 737 | |
| 738 | function uc_file_files_form_submit($form, &$form_state) { |
| 739 | switch ($form_state['step']) { |
| 740 | case 2: |
| 741 | switch ($form_state['values']['action']) { |
| 742 | case 'uc_file_delete': |
| 743 | foreach ($form_state['values']['file_ids'] as $file_id) { |
| 744 | _file_table_action('remove', $file_id, $form_state['values']['recurse_directories'], TRUE); |
| 745 | } |
| 746 | drupal_set_message(t('The select file(s) have been deleted.')); |
| 747 | break; |
| 748 | case 'uc_file_upload': |
| 749 | $dir = variable_get('uc_file_base_dir', NULL) .'/'; |
| 750 | $dir = (is_null($form_state['values']['upload_dir'])) ? $dir : $dir . $form_state['values']['upload_dir']; |
| 751 | if (is_dir($dir)) { |
| 752 | $file_object = $form_state['storage']['temp_file']; |
| 753 | if (file_copy($file_object, $dir, FILE_EXISTS_REPLACE)) { |
| 754 | //Check any if any hook_file_action('upload', $args) are implemented |
| 755 | foreach (module_implements('file_action') as $module) { |
| 756 | $name = $module .'_file_action'; |
| 757 | $result = $name('upload', array('file_object' => $file_object, 'form_id' => $form_id, 'form_state' => $form_state)); |
| 758 | } |
| 759 | |
| 760 | _file_table_action('insert'); |
| 761 | drupal_set_message(t('The %file has been uploaded to %dir', array('%file' => basename($file_object->filepath), '%dir' => $dir))); |
| 762 | } |
| 763 | else { |
| 764 | drupal_set_message(t('An error occurred while copying the file to %dir', array('%dir' => $dir))); |
| 765 | } |
| 766 | } |
| 767 | else { |
| 768 | drupal_set_message(t('Can not move file to %dir', array('%dir' => $dir))); |
| 769 | } |
| 770 | break; |
| 771 | default: |
| 772 | //Check any if any hook_file_action('validate', $args) are implemented |
| 773 | foreach (module_implements('file_action') as $module) { |
| 774 | $name = $module .'_file_action'; |
| 775 | $result = $name('submit', array('form_id' => $form_id, 'form_state' => $form_state)); |
| 776 | } |
| 777 | break; |
| 778 | } |
| 779 | $form_state['rebuild'] = FALSE; |
| 780 | drupal_goto('admin/store/products/files'); |
| 781 | break; |
| 782 | default: |
| 783 | $form_state['step'] = 2; |
| 784 | $form_state['rebuild'] = TRUE; |
| 785 | break; |
| 786 | } |
| 787 | } |
| 788 | |
| 789 | /** |
| 790 | * Form builder for file download notification settings. |
| 791 | */ |
| 792 | function uc_file_notify_settings() { |
| 793 | $form['uc_file_download_notification'] = array( |
| 794 | '#type' => 'checkbox', |
| 795 | '#title' => t('Send email to customer with file download link(s).'), |
| 796 | '#default_value' => variable_get('uc_file_download_notification', FALSE), |
| 797 | ); |
| 798 | $form['uc_file_download_notification_subject'] = array( |
| 799 | '#type' => 'textfield', |
| 800 | '#title' => t('Message subject'), |
| 801 | '#default_value' => variable_get('uc_file_download_notification_subject', uc_get_message('uc_file_download_subject')), |
| 802 | ); |
| 803 | $form['uc_file_download_notification_message'] = array( |
| 804 | '#type' => 'textarea', |
| 805 | '#title' => t('Message text'), |
| 806 | '#default_value' => variable_get('uc_file_download_notification_message', uc_get_message('uc_file_download_message')), |
| 807 | '#description' => t('The message the user receives after purchasing products with file downloads (<a href="!token_url">uses order, uc_file, and global tokens</a>)', array('!token_url' => url('admin/store/help/tokens'))), |
| 808 | '#rows' => 10, |
| 809 | ); |
| 810 | $form['uc_file_download_notification_format'] = filter_form(variable_get('uc_file_download_notification_format', FILTER_FORMAT_DEFAULT), NULL, array('uc_file_download_notification_format')); |
| 811 | |
| 812 | return system_settings_form($form); |
| 813 | } |
| 814 | |
| 815 | /** |
| 816 | * Table builder for file products admin |
| 817 | */ |
| 818 | function uc_file_files_table($form_state, $args = array()) { |
| 819 | $table = array(); |
| 820 | |
| 821 | $fields = array(); |
| 822 | $fields[] = array( |
| 823 | 'id' => 'select', |
| 824 | 'cell' => '', |
| 825 | 'weight' => 0, |
| 826 | ); |
| 827 | $fields[] = array( |
| 828 | 'id' => 'filename', |
| 829 | 'cell' => array('data' => t('File'), 'field' => 'f.filename'), |
| 830 | 'weight' => 1, |
| 831 | ); |
| 832 | $fields[] = array( |
| 833 | 'id' => 'product', |
| 834 | 'cell' => array('data' => t('Product'), 'field' => 'n.title'), |
| 835 | 'weight' => 2, |
| 836 | ); |
| 837 | $fields[] = array( |
| 838 | 'id' => 'model', |
| 839 | 'cell' => array('data' => t('Model/SKU'), 'field' => 'fp.model'), |
| 840 | 'weight' => 3, |
| 841 | 'attributes' => array() |
| 842 | ); |
| 843 | $table['columns'] = $fields; |
| 844 | |
| 845 | $files = _group_filenames($args['files']); |
| 846 | foreach ($files as $file) { |
| 847 | $data = array(); |
| 848 | $data['select'] = array('value' => $args['form']['file_select_'. $file->fid], 'cell' => drupal_render($args['form']['file_select_'. $file->fid])); |
| 849 | $filename = (is_dir(variable_get('uc_file_base_dir', NULL) .'/'. $file->filename)) ? '<strong>'. $file->filename .'</strong>' : $file->filename; |
| 850 | $data['filename'] = array('cell' => $filename == $last_filename ? '' : $filename); |
| 851 | if ($filename == $last_filename && !empty($data['#attributes'])) { |
| 852 | $table['rows'][count($table['rows']) - 1]['attributes'] = array('class' => 'group'); |
| 853 | } |
| 854 | $last_filename = (empty($last_filename) || $filename != $last_filename) ? $filename : $last_filename; |
| 855 | $data['product'] = array('cell' => !empty($file->title) ? l($file->title, 'node/'. $file->nid) : ''); |
| 856 | $data['model'] = array('cell' => !empty($file->model) ? $file->model : ''); |
| 857 | $data['#attributes'][] = array(); |
| 858 | $table['rows'][] = array('data' => $data, 'attributes' => array()); |
| 859 | } |
| 860 | |
| 861 | $form['table'] = array( |
| 862 | '#value' => $table, |
| 863 | '#theme' => 'tapir_table', |
| 864 | '#attributes' => array( |
| 865 | 'class' => 'file-table', |
| 866 | ), |
| 867 | ); |
| 868 | } |
| 869 | |
| 870 | /** |
| 871 | * Table builder for user downloads |
| 872 | */ |
| 873 | function uc_file_user_downloads($account) { |
| 874 | drupal_set_title(t('File downloads')); |
| 875 | uc_add_js(drupal_get_path('module', 'uc_file') .'/uc_file.js'); |
| 876 | |
| 877 | $header = array( |
| 878 | array('data' => t('Purchased'), 'field' => 'u.granted', 'sort' => 'desc'), |
| 879 | array('data' => t('Filename'), 'field' => 'f.filename'), |
| 880 | array('data' => t('Description'), 'field' => 'p.description'), |
| 881 | array('data' => t('Downloads'), 'field' => 'u.accessed'), |
| 882 | ); |
| 883 | |
| 884 | $sql = "SELECT granted, filename, accessed, description, `key`, f.fid FROM {uc_file_users} as u LEFT JOIN {uc_files} as f ON u.fid = f.fid LEFT JOIN {uc_file_products} as p ON p.pfid = u.pfid WHERE uid = %d"; |
| 885 | $count_query = "SELECT COUNT(*) FROM {uc_file_users} WHERE uid = %d"; |
| 886 | $download_limit = variable_get('uc_file_download_limit_number', NULL); |
| 887 | $file_ids = array(); |
| 888 | $rows = array(); |
| 889 | $files = pager_query($sql . tablesort_sql($header), UC_FILE_PAGER_SIZE, 0, $count_query, $account->uid); |
| 890 | |
| 891 | while ($file = db_fetch_object($files)) { |
| 892 | $row = count($rows); |
| 893 | $expiration = _file_expiration_date($file->granted); |
| 894 | $onclick = array('onclick' => 'uc_file_update_download('. $row .', '. $file->accessed .', '. ((empty($download_limit)) ? -1 : $download_limit) .');', 'id' => 'link-'. $row); |
| 895 | |
| 896 | if (!$expiration) { |
| 897 | $file_link = l(basename($file->filename), 'download/'. $file->fid .'/'. $file->key, $onclick); |
| 898 | } |
| 899 | else { |
| 900 | if (time() > $expiration) { |
| 901 | $file_link = basename($file->filename); |
| 902 | } |
| 903 | else { |
| 904 | $file_link = l(basename($file->filename), 'download/'. $file->fid .'/'. $file->key, $onclick) .' ('. t('expires on @date', array('@date' => format_date($expiration, 'custom', variable_get('uc_date_format_default', 'm/d/Y')))) .')'; |
| 905 | } |
| 906 | } |
| 907 | |
| 908 | $rows[] = array( |
| 909 | array('data' => format_date($file->granted, 'custom', variable_get('uc_date_format_default', 'm/d/Y')), 'class' => 'date-row', 'id' => 'date-'. $row), |
| 910 | array('data' => $file_link, 'class' => 'filename-row', 'id' => 'filename-'. $row), |
| 911 | array('data' => $file->description, 'class' => 'description-row', 'id' => 'description-'. $row), |
| 912 | array('data' => $file->accessed, 'class' => 'download-row', 'id' => 'download-'. $row), |
| 913 | ); |
| 914 | } |
| 915 | if (empty($rows)) { |
| 916 | $rows[] = array(array('data' => t('No downloads found'), 'colspan' => 4)); |
| 917 | } |
| 918 | |
| 919 | $output = theme('table', $header, $rows) . theme('pager', NULL, UC_FILE_PAGER_SIZE, 0); |
| 920 | return $output; |
| 921 | } |
| 922 | |
| 923 | /* **************************************************************************** * |
| 924 | * Module and Helper Functions * |
| 925 | * **************************************************************************** */ |
| 926 | |
| 927 | /** |
| 928 | * Implement Drupal autocomplete textfield |
| 929 | * |
| 930 | * @return: |
| 931 | * Sends string containing javascript array of matched files |
| 932 | */ |
| 933 | function _autocomplete_filename() { |
| 934 | // Catch "/" characters that drupal autocomplete doesn't escape |
| 935 | $url = explode('_autocomplete_file/', request_uri()); |
| 936 | $string = $url[1]; |
| 937 | $matches = array(); |
| 938 | $files = db_query("SELECT filename FROM {uc_files} WHERE filename LIKE LOWER('%s')", '%'. $string .'%'); |
| 939 | |
| 940 | while ($file = db_fetch_object($files)) { |
| 941 | $matches[$file->filename] = $file->filename; |
| 942 | } |
| 943 | print drupal_to_js($matches); |
| 944 | exit(); |
| 945 | } |
| 946 | |
| 947 | /** |
| 948 | * Email a user with download links for a product file download |
| 949 | * |
| 950 | * @param $user |
| 951 | * The Drupal user object |
| 952 | * @param $order |
| 953 | * The order object associated with message |
| 954 | * @param $file_user |
| 955 | * An array for user file downloads (uc_file_user row) associated with message |
| 956 | * @return: |
| 957 | * Sends result of drupal_mail |
| 958 | */ |
| 959 | function _email_file_download($user, $order, $file_users) { |
| 960 | if (!variable_get('uc_file_download_notification', FALSE)) { |
| 961 | return; |
| 962 | } |
| 963 | $key = 'uc_file_download_notify'; |
| 964 | $to = $order->primary_email; |
| 965 | $from = uc_store_email_from(); |
| 966 | $params = array(); |
| 967 | |
| 968 | //drupal_set_message("Mail Sent<br/>key: $key, <br/>to: $to, <br/>subject: $subject, <br/>body: $body, <br/>from: $from, <br/>"); |
| 969 | return drupal_mail('uc_file', $key, $to, user_preferred_language($user), $params, $from); |
| 970 | } |
| 971 | |
| 972 | function uc_file_mail($key, &$message, $params) { |
| 973 | $token_filters = array('global' => NULL, 'user' => $user, 'order' => $order, 'uc_file' => $file_users); |
| 974 | $message['subject'] = token_replace_multiple(variable_get('uc_file_download_notification_subject', uc_get_message('uc_file_download_subject')), $token_filters); |
| 975 | $body = token_replace_multiple(variable_get('uc_file_download_notification_message', uc_get_message('uc_file_download_message')), $token_filters); |
| 976 | $body = check_markup($body, variable_get('uc_file_download_notification_format', 3), FALSE); |
| 977 | $message['body'][] = $body; |
| 978 | $message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed'; |
| 979 | } |
| 980 | |
| 981 | /** |
| 982 | * Perform first-pass authorization. Call authorization hooks afterwards. |
| 983 | * |
| 984 | * Called when a user requests a file download, function checks download |
| 985 | * limits then checks for any implementation of hook_download_authorize. |
| 986 | * Passing that, the function _file_download_transfer is called. |
| 987 | * |
| 988 | * @param $fid |
| 989 | * The fid of the file specified to download. |
| 990 | * @param $key |
| 991 | * The hash key of a user's download |
| 992 | */ |
| 993 | function _file_download($fid, $key) { |
| 994 | global $user; |
| 995 | $ip = ip_address(); |
| 996 | $message_admin = t('Please contact the site administrator if this message has been received in error.'); |
| 997 | |
| 998 | $message_user = ($user->uid) ? t('The user %username ', array('%username' => $user->name)) : t('The IP address %ip ', array('%ip' => $ip)); |
| 999 | $file_download = db_fetch_object(db_query("SELECT * FROM {uc_file_users} WHERE fid = %d AND `key` = '%s'", $fid, $key)); |
| 1000 | $request_cache = cache_get('uc_file_'. $ip); |
| 1001 | $requests = ($request_cache) ? $request_cache->data + 1 : 1; |
| 1002 | |
| 1003 | if ($requests > UC_FILE_REQUEST_LIMIT) { |
| 1004 | _file_download_deny($user->uid, t('You have attempted to download an incorrect file URL too many times. ') . $message_admin); |
| 1005 | } |
| 1006 | |
| 1007 | if (!$file_download) { |
| 1008 | cache_set('uc_file_'. $ip, $requests, 'cache', time() + 86400); |
| 1009 | if ($requests == UC_FILE_REQUEST_LIMIT) { |
| 1010 | watchdog('uc_file', '%username has been temporarily banned from file downloads.', array('%username' => $message_user), WATCHDOG_WARNING); |
| 1011 | } |
| 1012 | _file_download_deny($user->uid, t("The following URL is not a valid download link. ") . $message_admin); |
| 1013 | } |
| 1014 | else { |
| 1015 | $ip_limit = variable_get |