Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
567 lines (489 sloc) 22.1 KB
<?php
// $Id$
/*//
Author: Doug Logan
Email: My first name @dlogan.com
TODO: Organize code into logical sections and write a header for what each function does.
TODO: Separate Admin functions for an admin include.
TODO: Fix http://localhost/drupal/?q=node/6/edit/options so notes on use with file upload is output
TODO: Adjust the price of items in the cart based on the extension of the option chosen
TODO: Clear cache on permissions and get it working for both view upload, and view all upload.
TODO: Track down why getting "Invalid type of order was passed by user" within Watchdog
//*/
function uc_attribute_files_perm() {
return array('view all uploads', 'upload files', 'view upload');
}
function uc_attribute_files_menu() {
$items = array();
$items['uploads/cart/%'] = array(
'page callback' => '_uc_attribute_files_download',
'page arguments' => array(1, 2),
'access callback' => 'uc_attribute_files_user_view_upload_access',
'type' => MENU_CALLBACK,
);
$items['uploads/order/%/%/%'] = array(
'page callback' => '_uc_attribute_files_download',
'page arguments' => array(1, 4, 2, 3),
'access callback' => 'uc_attribute_files_user_view_upload_access',
'type' => MENU_CALLBACK,
);
return $items;
}
function uc_attribute_files_user_view_upload_access() {
if (user_access('view upload') || user_access('view all uploads') ) {
return TRUE;
}
else {
return FALSE;
}
}
function uc_attribute_files_menu_alter(&$items) {
$items['admin/store/attributes']['page callback'] = 'uc_attribute_files_admin';
unset($items['admin/store/attributes']['file']);
}
function uc_attribute_files_admin() {
$header = array(
array('data' => t('Name'), 'field' => 'a.name', 'sort' => 'asc'),
array('data' => t('Label'), 'field' => 'a.label'),
t('Required'),
array('data' => t('List position'), 'field' => 'a.ordering'),
t('Number of options'),
t('Display type'),
t('Operations'),
);
$display_types = array(
0 => t('Text field'),
1 => t('Select box'),
2 => t('Radio buttons'),
3 => t('Checkboxes'),
variable_get('uc_attribute_files_attribute_number', 4) => t('File Upload'),
);
$result = pager_query("SELECT a.aid, a.name, a.label, a.required, a.ordering, a.display, COUNT(ao.oid) AS options FROM {uc_attributes} AS a LEFT JOIN {uc_attribute_options} AS ao ON a.aid = ao.aid GROUP BY a.aid, a.name, a.label, a.ordering, a.required, a.display". tablesort_sql($header), 30, 0, "SELECT COUNT(aid) FROM {uc_attributes}");
while ($attr = db_fetch_object($result)) {
if (empty($attr->label)) {
$attr->label = $attr->name;
}
$ops = array(
l(t('edit'), 'admin/store/attributes/'. $attr->aid .'/edit'),
l(t('options'), 'admin/store/attributes/'. $attr->aid .'/options'),
l(t('delete'), 'admin/store/attributes/'. $attr->aid .'/delete'),
);
$rows[] = array(
check_plain($attr->name),
check_plain($attr->label),
$attr->required == 1 ? t('Yes') : t('No'),
array('data' => $attr->ordering, 'align' => 'center'),
array('data' => $attr->options, 'align' => 'center'),
$display_types[$attr->display],
implode(' ', $ops),
);
}
if (count($rows) == 0) {
$rows[] = array(
array('data' => t('No product attributes have been added yet.'), 'colspan' => '6')
);
}
$output = theme('table', $header, $rows) . theme('pager', NULL, 30) . l(t('Add an attribute'), 'admin/store/attributes/add');
return $output;
}
function _uc_attribute_files_download($type, $file, $uid = NULL, $order_id = NULL) {
global $user;
switch ($type) {
case 'cart':
$dir = variable_get('uc_attribute_files_cart_filepath', NULL) . "/" . uc_cart_get_id();
break;
case 'anonymous':
case 'order':
$dir = variable_get('uc_attribute_files_order_filepath', NULL) . "/" . $uid . "/" . $order_id;
if ($type !== 'anonymous' && $uid == $user->uid && $uid == 0) { //Force anonymous orders to provide zip
return drupal_get_form('uc_attribute_files_anonymous_zip_form', $file, $uid, $order_id);
}
break;
default:
$dir = NULL;
break;
}
if ( !is_null(variable_get('uc_attribute_files_cart_filepath', NULL)) && //Validate variable set
!is_null(variable_get('uc_attribute_files_order_filepath', NULL)) && //Validate variable set
($uid == $user->uid || user_access('view all uploads')) && //Check permission
!is_null($dir) && is_readable($dir . '/' . check_plain($file)) //Check dir & file are valid
) {
uc_attribute_files_download_transfer(check_plain($file), $dir);
}
elseif ($user->uid == 0) {
drupal_set_title(t('Access denied'));
return t('You must logon to access this file.');
}
else {
//Handle & Log Errors
if (is_null(variable_get('uc_attribute_files_cart_filepath', NULL))) {
watchdog('uc_attribute_files', 'uc_attribute_files_cart_filepath is not set');
$dir = NULL;
if ($user->uid == 1) {
drupal_set_message(t('uc_attribute_files_cart_filepath is not set. !link to edit.', array('!link' => l(t('Click here'), 'admin/store/settings/attributes'))));
}
}
if (is_null(variable_get('uc_attribute_files_order_filepath', NULL))) {
watchdog('uc_attribute_files', 'uc_attribute_files_order_filepath is not set');
$dir = NULL;
if ($user->uid == 1) {
drupal_set_message(t('uc_attribute_files_order_filepath is not set. !link to edit.', array('!link' => l(t('Click here'), 'admin/store/settings/attributes'))));
}
}
if (is_readable($dir . '/' . check_plain($file))) {
watchdog('uc_attribute_files', 'File not readable: %user attempted to access %file from %type: %id. in dir: %dir', array('%user' => $user->name, '%file' => check_plain($file), '%type' => $type, '%id' => $id, '%dir' => $dir));
}
if (is_null($dir)) {
watchdog('uc_attribute_files', 'Invalid type of %type was passed by user %user for file %file', array('%user' => $user->name, '%file' => check_plain($file), '%type' => $type));
}
drupal_set_header('HTTP/1.1 404 Not Found');
drupal_set_title(t('Page not found'));
return t('The requested page could not be found.');
}
}
function uc_attribute_files_anonymous_zip_form($form_state, $file, $uid, $order_id) {
$form['zip'] = array( '#type' => 'textfield',
'#description' => t('Enter the billing zip code for the order'),
'#title' => t('Billing Zip Code'),
'#size' => 5,
'#maxlength' => 5,
);
$form['a'] = array( '#type' => 'hidden', '#value' => $file );
$form['b'] = array( '#type' => 'hidden', '#value' => $uid );
$form['c'] = array( '#type' => 'hidden', '#value' => $order_id );
$form['submit'] = array('#type' => 'submit', '#value' => t('Submit'));
return $form;
}
function uc_attribute_files_anonymous_zip_form_submit($form, &$form_state) {
$zip = $form_state['values']['zip'];
$file = $form_state['values']['a'];
$uid = $form_state['values']['b'];
$order_id = $form_state['values']['c'];
if (intval($order_id) > 0) {
$order = uc_order_load($order_id);
if ($order->billing_postal_code == $zip) {
return _uc_attribute_files_download('anonymous', $file, $uid, $order_id);
}
}
drupal_set_message(t('Zip code does not match order.'));
}
function uc_attribute_files_download_transfer($file, $path) {
//Function copied and modified slightly from uc_file.module
$filepath = $path . "/" . $file;
// Gather relevant info about the file.
$size = filesize($filepath);
$mimetype = file_get_mimetype($filepath);
// Workaround for IE filename bug with multiple periods / multiple dots in filename
// that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe
if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
$file = preg_replace('/\./', '%2e', $file, substr_count($file, '.') - 1);
}
// Check if HTTP_RANGE is sent by browser (or download manager)
if (isset($_SERVER['HTTP_RANGE'])) {
list($size_unit, $range_orig) = explode('=', $_SERVER['HTTP_RANGE'], 2);
if ($size_unit == 'bytes') {
// Multiple ranges could be specified at the same time, but for simplicity only serve the first range
// See http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
list($range, $extra_ranges) = explode(',', $range_orig, 2);
}
else {
$range = '';
}
}
else {
$range = '';
}
// Figure out download piece from range (if set)
list($seek_start, $seek_end) = explode('-', $range, 2);
// Set start and end based on range (if set), else set defaults and check for invalid ranges.
$seek_end = intval((empty($seek_end)) ? ($size - 1) : min(abs(intval($seek_end)), ($size - 1)));
$seek_start = intval((empty($seek_start) || $seek_end < abs(intval($seek_start))) ? 0 : max(abs(intval($seek_start)), 0));
ob_end_clean();
//Only send partial content header if downloading a piece of the file (IE workaround)
if ($seek_start > 0 || $seek_end < ($size - 1)) {
drupal_set_header('HTTP/1.1 206 Partial Content');
}
// Standard headers, including content-range and length
drupal_set_header('Pragma: public');
drupal_set_header('Cache-Control: cache, must-revalidate');
drupal_set_header('Accept-Ranges: bytes');
drupal_set_header('Content-Range: bytes '. $seek_start .'-'. $seek_end .'/'. $size);
drupal_set_header('Content-Type: '. $mimetype);
drupal_set_header('Content-Disposition: attachment; filename="'. $file .'"');
drupal_set_header('Content-Length: '. ($seek_end - $seek_start + 1));
// Last-Modified is required for content served dynamically
drupal_set_header('Last-Modified: '. gmdate("D, d M Y H:i:s", filemtime($filepath)) ." GMT");
// Etag header is required for Firefox3 and other managers
drupal_set_header('ETag: '. md5($filepath));
// Open the file and seek to starting byte
$fp = fopen($filepath, 'rb');
fseek($fp, $seek_start);
// Start buffered download
while (!feof($fp)) {
// Reset time limit for large files
set_time_limit(30);
// Push the data to the client.
print(fread($fp, 8192));
flush();
ob_flush();
}
fclose($fp);
}
//Implements hook_add_to_cart. Gives item information for anything added to cart
function uc_attribute_files_uc_form_alter(&$form_state, $node) {
if (count($form_state['node']['#value']->attributes) > 0) {
foreach ($form_state['node']['#value']->attributes as $attribute) {
if ($attribute->display == variable_get('uc_attribute_files_attribute_number', 4)) {
$form_state['#attributes']['enctype']='multipart/form-data';
$form_state['#validate'][] = "uc_attribute_files_cart_validate";
}
}
}
}
function uc_attribute_files_form_alter(&$form, $form_state, $form_id) {
global $user;
if (strpos($form_id, "add_to_cart_form")) {
if (count($form['attributes']) > 0) {
foreach ($form['attributes'] as $id => $attribute) {
if ($form['node']['#value']->attributes[$id]->display == variable_get('uc_attribute_files_attribute_number', 4)) {
if (!user_access('upload files')) {
$form['attributes'][$id]['#type'] = 'hidden';
$form['attributes'][$id]['#value'] = '';
if ($attribute['#required']) {
$form['submit']['#attributes']['disabled'] = 'disabled';
$form['submit']['#title'] = 'You must login to add this to your cart';
if ($user->uid == 0) {
$form['uc_attribute_files_login_required']['#value'] = '<DIV>' . t('Please !login to see if you can add this item to your cart.', array('!login' => l(t('login'), 'user/login'))) . '</DIV>';
}
else {
$form['uc_attribute_files_login_required']['#value'] = '<DIV>' . t('Your userid can not add this item. Please contact an administrator for assistance.') . '</DIV>';
}
}//*
}
else {
$form['attributes'][$id]['#type'] = 'file';
$form['attributes'][$id]['#name'] = "files[" . check_plain($form['node']['#value']->attributes[$id]->name) . "]";
$form['attributes'][$id]['#value_callback'] = "uc_attribute_files_value_callback";
}
}
}
}
}
else {
switch ($form_id) {
case 'uc_attribute_admin_settings':
//Remove first form element, and put into array to be used so new form can be inserted before
//the submit buttons. This essentiall re-orders the form so it doesn't look stupid.
$uc_attribute_files_form[key($form)] = array_shift($form);
$uc_attribute_files_form['uc_attribute_files_cart_filepath'] =
array(
'#type' => 'textfield',
'#title' => t('File path for cart file uploads'),
'#description' => t('The absolute path (or relative to Drupal root) where files uploaded to a cart for an attribute should be put. For security reasons, it is recommended to choose a path outside the web root.'),
'#default_value' => variable_get('uc_attribute_files_cart_filepath', NULL),
);
$uc_attribute_files_form['uc_attribute_files_order_filepath'] =
array(
'#type' => 'textfield',
'#title' => t('File path for order files'),
'#description' => t('The absolute path (or relative to Drupal root) where uploaded files should be moved after a cart becomes an order. For security reasons, it is recommended to choose a path outside the web root.'),
'#default_value' => variable_get('uc_attribute_files_order_filepath', NULL),
);
$uc_attribute_files_form['uc_attribute_files_file_extensions'] =
array(
'#type' => 'textfield',
'#title' => t('List of file extensions allowed (Use a ; to separate)'),
'#description' => t('Default list of file extensions for files that can be uploaded. Separate each by a semi-colin (;) or use * as a wild card to allow any file type.<BR>' . 'NOTE: This can be overridden on an attribute by adding an option for each acceptable filetype. If any option is specified on the attribute directly, this setting is ignored for that attribute.'),
'#default_value' => variable_get('uc_attribute_files_file_extensions', "PDF;JPG;GIF;JPEG;TIFF;BMP"),
);
//Takes the above array and inserts it into the beginning of the form array
$form = array_merge($uc_attribute_files_form, $form);
$form['#validate'][] = "uc_attribute_files_admin_validate";
break;
case 'uc_attribute_form':
$numb = variable_get('uc_attribute_files_attribute_number', NULL);
if (is_null($numb)) {
$numb = count($form['display']['#options']);
variable_set('uc_attribute_files_attribute_number', $numb);
}
$form['display']['#options'][$numb] = t('File Upload');
break;
case 'user_login_block':
//Add Hidden form element to pass old cart id on logon
$form['uc_attribute_files_cartid'] = array('#type' => 'hidden', '#value' => uc_cart_get_id() );
break;
case 'uc_attribute_options_form':
if (count($form['#parameters']) < 1) {
break;
}
foreach ($form['#parameters'] as $id => $param) {
if ($param->display == 4) {
$form['uc_attribute_files_notes']['#value'] =
'<div>' . t('NOTE: Enter file extensions as options above to limit uploads to the file types listed. Enter a * for any file extension. This overrides site defaults.') . '</div>';
}
}
break;
case 'uc_attribute_option_form':
if (count($form['#parameters']) < 1) {
break;
}
foreach ($form['#parameters'] as $id => $param) {
if ($param->display == 4) {
$form['name']['#description'] =
t('The extension of a file type you would like a user to be able to upload. Enter a * for any extension.') . '</div>';
}
}
break;
case 'uc_object_attributes_form':
if (count($form['attributes']) < 1) {
break;
}
foreach ($form['attributes'] as $id => $attribute) {
$form['attributes'][$id]['display']['#options'][variable_get('uc_attribute_files_attribute_number', 4)] = t('File Upload');
}
break;
default:
/*print("abc");
print_r($form_id);//*/
}
}
}
function uc_attribute_files_admin_validate($form, &$form_state) {
$cart_dir = check_plain($form_state['values']['uc_attribute_files_cart_filepath']);
$order_dir = check_plain($form_state['values']['uc_attribute_files_order_filepath']);
if (!is_dir($cart_dir) && !@mkdir($cart_dir, 0755, TRUE)) {
form_set_error('uc_attribute_files_cart_filepath', t('Could not open or create path:') . $cart_dir);
}
if (!is_dir($order_dir) && !@mkdir($order_dir, 0755, TRUE)) {
form_set_error('uc_attribute_files_order_filepath', t('Could not open or create path:') . $order_dir);
}
}
function uc_attribute_files_value_callback($form, $edit = FALSE) {
if ($edit !== FALSE) {
preg_match("/files\[(.+)\]/", $form['#name'], $name);
if (count($_FILES['files']) > 0) {
$filename = file_munge_filename($_FILES['files']['name'][$name[1]], "");
$return = '[UC_ATTRIBUTE_FILES]' . $filename . '[/UC_ATTRIBUTE_FILES]';
}
return (string)$return;
}
}
function uc_attribute_files_cart_validate($form, &$form_state) {
$cart_id = uc_cart_get_id();
$_SESSION['uc_attribute_files_cartid'];
if (is_null(variable_get('uc_attribute_files_cart_filepath', NULL))) {
form_set_error('file', t('Upload to directory failed. Please contact an administrator.'));
return FALSE;
}
$upload_dir = variable_get('uc_attribute_files_cart_filepath', NULL) . '/' . $cart_id;
//Check if folder exists, or create it.
if (!is_dir($upload_dir) && !@mkdir($upload_dir, 0755, TRUE)) {
form_set_error('file', t('Upload to directory failed. Please contact an administrator.'));
return FALSE;
}
//Validate file type & file was uploaded properly
foreach ($_FILES['files']['name'] as $id => $value) {
foreach ($form['node']['#value']->attributes as $attribute) {
if ($attribute->name == $id) {
//Test to see if there are any options, since they can represent ok file types
$result = db_query("SELECT name FROM {uc_attribute_options} WHERE aid = %d", $attribute->aid);
unset($file_types);
while ($option = db_fetch_object($result)) {
$file_types[] = strtolower($option->name);
}
if (count($file_types) < 1) { //If there are no options, load the default acceptable file types
$file_types = array_map('strtolower', explode(';', variable_get('uc_attribute_files_file_extensions', NULL)));
}
$filename = file_munge_filename($value, "");
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if (!in_array($ext, $file_types) && !in_array('*', $file_types)) {
form_set_error($id, t('Sorry, but %label only accepts the following file types: !types', array('%label' => $attribute->label, '!types' => implode(";", $file_types))));
}
elseif (intval($_FILES['files']['error'][$id]) !== 0 || intval($_FILES['files']['size'][$id]) < 1 || !@copy($_FILES['files']['tmp_name'][$id], $upload_dir . '/' . $filename)) {
form_set_error($id, t('!filename: File upload failed for %label.', array('!filename' => $filename, '%lable' => $attribute->label)));
}
}
}
}
return TRUE;
}
function uc_attribute_files_product_description_alter($item) {
$item['#post_render'][] = "uc_attribute_files_render_links";
return $item;
}
function uc_attribute_files_render_links($html) {
preg_match('!\orders?/(\d+)!', $_SERVER[request_uri()], $order);
if (count($order[1]) > 0) {
$order_user = db_fetch_object(db_query("SELECT uid FROM {uc_orders} WHERE order_id = %d", $order[1]));
$uri = 'uploads/order/' . $order_user->uid . '/' . $order[1] . '/';
}
else {
$uri = "uploads/cart/";
}
preg_match_all('!\[UC_ATTRIBUTE_FILES\](.*)\[/UC_ATTRIBUTE_FILES\]!U', $html, $links);
for ($x =0; $x < count($links[1]); $x++) {
$find = $links[0][$x];
$replace = l($links[1][$x], $uri . $links[1][$x]);
$html = str_replace($find, $replace, $html ) ."\n";
}
return $html;
}
function uc_attribute_files_cron() {
$dir = realpath(variable_get('uc_attribute_files_cart_filepath', NULL) .'/');
$cart_dirs = array_flip(scandir($dir));
$result = db_query("SELECT DISTINCT cart_id FROM {uc_cart_products}");
while ($row = db_fetch_object($result)) {
unset($cart_dirs[$row->cart_id]);
}
unset($cart_dirs['.'], $cart_dirs['..']);
foreach ($cart_dirs as $id => $jnk) {
_uc_attribute_files_rrmdir($dir . $id);
}
}
function _uc_attribute_files_rrmdir($dir) {
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($dir . "/" . $object) == "dir") _uc_attribute_files_rrmdir($dir . "/" . $object); else unlink($dir . "/" . $object);
}
}
reset($objects);
rmdir($dir);
}
}
function uc_attribute_files_user($op, &$edit, &$user, $category = NULL) {
switch ($op) {
case 'login':
$dir = realpath(variable_get('uc_attribute_files_cart_filepath', NULL));
uc_attribute_files_move_files($dir . "/" . $edit['uc_attribute_files_cartid'], $dir . '/' . uc_cart_get_id());
break;
}
}
function uc_attribute_files_move_files($old_dir, $new_dir) {
if (is_dir($old_dir)) {
if (!is_dir($new_dir) && !@mkdir($new_dir, 0755, TRUE)) {
return FALSE;
}
foreach (scandir($old_dir) as $file) {
if ($file == '.' || $file == '..') {
continue;
}
@rename($old_dir . '/' . $file, $new_dir . '/' . $file);
}
_uc_attribute_files_rrmdir($old_dir);
}
}
function uc_attribute_files_order($op, &$arg1, $arg2) {
global $user;
switch ($op) {
case 'submit':
$cart_dir = variable_get('uc_attribute_files_cart_filepath', NULL) . '/' . uc_cart_get_id();
$order_dir = variable_get('uc_attribute_files_order_filepath', NULL) . '/' . $user->uid . '/' . $arg1->order_id;
uc_attribute_files_move_files($cart_dir, $order_dir);
break;
}
}
function uc_attribute_files_preprocess_table(&$variables) {
print_r("printed");
}