########################### upload_field.info ############################ ; $Id$ name = FAPI Upload field description = A FAPI element to handle file uploads. package = Other core = 6.x ########################### upload_field.module ############################ '. t('A module that provides a FAPI element to handle file uploads.') .'

'; return $output; } } /** * Implementation of hook_theme(). */ function upload_field_theme() { return array( 'upload_field' => array( 'arguments' => array('element' => NULL), ), 'image_upload_field' => array( 'arguments' => array('element' => NULL), ), 'upload_field_preview' => array( 'arguments' => array('file' => FALSE), ), 'upload_field_image_preview' => array( 'arguments' => array('file' => FALSE), ), ); } /** * Implementation of hook_elements * * Defines an file form element that is linked into the native Drupal file handling system. */ function upload_field_elements() { $type['upload_field'] = array( '#input' => TRUE, '#collapsible' => TRUE, '#collapsed' => FALSE, '#default_value' => '', '#process' => array('_upload_field_expand'), '#element_validate' => array('upload_field_element_validate'), '#file_formatter' => 'upload_field_preview', '#file_validators' => array(), ); $type['image_upload_field'] = array( '#input' => TRUE, '#collapsible' => TRUE, '#collapsed' => FALSE, '#default_value' => '', '#process' => array('_upload_field_expand'), '#element_validate' => array('upload_field_element_validate'), '#file_formatter' => 'upload_field_image_preview', '#file_validators' => array('file_validate_is_image' => array()), ); return $type; } /** * Our process callback to expand the control. * * There are two main roles performed, to rename the field name * into one that is usable by Drupal native file functionality, * and to add the extra attributes for fields with is_image set */ function _upload_field_expand($element) { $element['#original_name'] = $element['#name']; $element['#name'] = 'files['. $element['#name'] .']'; return $element; } /** * This handles the uploading and workflow * * @param unknown_type $form * @param unknown_type $edit * @return unknown */ function form_type_image_upload_field_value($form, $edit = FALSE) { return form_type_upload_field_value($form, $edit); } /** * This handles the uploading and workflow * * @param unknown_type $form * @param unknown_type $edit * @return unknown */ function form_type_upload_field_value($form, $edit = FALSE) { if ($edit !== FALSE) { $field_name = upload_field_name($form); $key = $field_name .'_form_key'; if (!array_key_exists($key, $form['#post'])) { form_set_error($field_name, t('Upload field form error, please try to load the form again. If this error persists, please contact the site administrator.')); return $form['#default_value']; } // handle the extras first $field_key = $form['#post'][$key]; $action = $form['#post'][$field_name][$field_name .'_action']; if (is_object($form['#default_value'])) { if ($action == 'delete') { upload_field_session_handler('delete', $form, $field_key); } if ($action == 'restore') { upload_field_session_handler('restore', $form, $field_key); } } if ($action == 'revert') { upload_field_session_handler('revert', $form, $field_key); } $file = file_save_upload($field_name, $form['#file_validators']); return !empty($file) ? upload_field_session_handler('store', $form, $field_key, $file) : upload_field_session_handler('value', $form, $field_key); } else { return $form['#default_value']; } } /** * The custom validation required for files that are marked * as deleted, but are required. * * @param array $element * @param array $form_state */ function upload_field_element_validate($element, &$form_state) { if ($element['#required'] && is_object($element['#value']) && property_exists($element['#value'], 'submit_action') && $element['#value']->submit_action == UPLOAD_FIELD_DELETE) { form_error($element, t('!name field is required.', array('!name' => $element['#title']))); } } function upload_field_equals($a = FALSE, $b = FALSE) { if (is_object($a) && is_object($b)) { return $a->fid == $b->fid; } return FALSE; } /** * Theme function to format the output. * * We use the container-inline class so that all three of the HTML elements * are placed next to each other, rather than on separate lines. */ function theme_image_upload_field($element) { return theme_upload_field($element); } /** * Theme function to format the output. * * We use the container-inline class so that all three of the HTML elements * are placed next to each other, rather than on separate lines. */ function theme_upload_field($element) { $key_field = _upload_field_form_key_field($element); $action_field = _upload_field_action_field($element); $fieldset_attributes = array('class' => ''); if ($element['#collapsible']) { drupal_add_js('misc/collapse.js'); $fieldset_attributes['class'] .= ' collapsible'; if ($element['#collapsed']) { $fieldset_attributes['class'] .= ' collapsed'; } } _form_set_class($element, array('form-file')); $preview = ''; if ($element['#file_formatter']) { $preview = theme($element['#file_formatter'], $element['#value']); } return '' . ($element['#title'] ? ''. $element['#title'] .'' : '') . $preview .'
' . drupal_render($action_field) . drupal_render($key_field) .'
\n" . $element['#children'] ."\n"; } function _upload_field_form_key_field($element) { $key = upload_field_name($element) .'_form_key'; $field[$key]= array( '#type' => 'hidden', '#name' => $key, '#value' => _upload_field_key($key, $element['#post'], $element), ); return $field; } function _upload_field_action_field($element) { $field = array(); if (is_object($element['#value'])) { $field_name = upload_field_name($element); $key = $field_name .'_action'; $field[$key]= array( '#type' => 'checkbox', '#id' => form_clean_id("edit-{$key}"), '#name' => "{$field_name}[{$key}]", '#value' => 0, '#weight' => -10, ); if (upload_field_equals($element['#value'], $element['#default_value'])) { if (property_exists($element['#value'], 'submit_action') && $element['#value']->submit_action == UPLOAD_FIELD_DELETE) { $field[$key]['#return_value'] = 'restore'; $field[$key]['#title'] = t('Restore original'); } else { $field[$key]['#return_value'] = 'delete'; $field[$key]['#title'] = t('Delete original'); $field[$key]['#value'] = (property_exists($element['#value'], 'submit_action') ? ($element['#value']->submit_action == UPLOAD_FIELD_DELETE ? 'delete' : 0) : 0); } } else { $field[$key]['#return_value'] = 'revert'; $field[$key]['#title'] = (is_object($element['#default_value']) ? t('Discard replacment') : t('Discard upload')); } } return $field; } function theme_upload_field_preview($file = FALSE) { if ($file) { $class = 'upload-field-preview'; if ($file->filemime) { list($base_mime, $extended_mime) = explode('/', $file->filemime); $class = trim($class .' mime-'. $base_mime .' '. ($extended_mime ? ' mime-'. $base_mime .'-'. $extended_mime : '')); } $size = ($file->filesize > 1048576) ? sprintf("%01.2f", $file->filesize / 1048576) .'MB' : sprintf("%01.2f", $file->filesize / 1024) .'KB'; return '
'. check_plain($file->filename) .' ('. $size .')
'; } else { return '
---
'; } } function theme_upload_field_image_preview($file = FALSE) { $src = $file ? 'upload_field/'. $file->fid : drupal_get_path('module', 'upload_field') .'/no_image.gif'; return 'Image Preview
'; } function upload_field_save(&$file, $dest = 0, $replace = FILE_EXISTS_RENAME, $presetname = FALSE) { if (is_object($file)) { $base = file_directory_path(); if (strstr($dest, $base) === FALSE) { $dest = $base . '/' . ltrim($dest, '/'); } file_check_directory($dest, 1); if (!property_exists($file, 'submit_action')) { $file->submit_action = UPLOAD_FIELD_NONE; } switch ($file->submit_action) { case UPLOAD_FIELD_NONE: return $file->fid; case UPLOAD_FIELD_DELETE: file_set_status($file, FILE_STATUS_TEMPORARY); return 0; case UPLOAD_FIELD_REPLACE: $_file = clone $file; $_file->fid = $file->original_fid; file_set_status($_file, FILE_STATUS_TEMPORARY); drupal_write_record('files', $_file); // fall through case UPLOAD_FIELD_NEW: $uploaded = FALSE; if($presetname) { $destination = file_create_filename($file->filename, $dest); if( upload_field_imagecache_action($presetname, $file->filepath, $destination)) { $file->filepath = $destination; $uploaded = TRUE; } } if (!$uploaded) { file_move($file, $dest .'/'. $file->filename, FILE_EXISTS_RENAME); } if($uploaded) { $file->status = FILE_STATUS_PERMANENT; drupal_write_record('files', $file, 'fid'); return $file->fid; } else { drupal_set_message(t('Error occured while saving the image!'), 'error'); return 0; } } } return 0; } /** * Hooks into imageache preset for save action */ function upload_field_imagecache_action($presetname, $path, $dst) { if (!function_exists(imagecache_preset_by_name)) { return FALSE; } if (!$preset = imagecache_preset_by_name($presetname)) { return FALSE; } if (is_file($dst)) { return TRUE; } $src = $path; if (!is_file($src) && !is_file($src = file_create_path($src))) { return FALSE; }; if (!getimagesize($src)) { return FALSE; } $lockfile = file_directory_temp() .'/'. $preset['presetname'] . basename($src); if (file_exists($lockfile)) { watchdog('imagecache', 'Imagecache already generating: %dst, Lock file: %tmp.', array('%dst' => $dst, '%tmp' => $lockfile), WATCHDOG_NOTICE); return FALSE; } touch($lockfile); register_shutdown_function('file_delete', realpath($lockfile)); if (file_exists($dst) || imagecache_build_derivative($preset['actions'], $src, $dst)) { return TRUE; } // Generate an error if image could not generate. watchdog('imagecache', 'Failed generating an image from %image using imagecache preset %preset.', array('%image' => $path, '%preset' => $preset['presetname']), WATCHDOG_ERROR); return FALSE; } /** * Implementation of hook_menu * * This is for node editing only */ function upload_field_menu() { $items = array(); $items['upload_field/%'] = array( 'title' => 'Upload field preview', 'file' => 'image.preview.inc', 'type' => MENU_CALLBACK, 'access arguments' => array('access content'), 'page callback' => 'upload_field_image_preview', 'page arguments' => array(1), ); return $items; } function upload_field_preview($fid) { //$_SESSION['files']['upload_field'][FORM_FIELD_ID][FIELD_NAME] //$_SESSION['files']['upload_field'][FORM_FIELD_ID][FIELD_NAME . '_default'] if (is_numeric($fid) && is_array($_SESSION['files']['upload_field'])) { foreach ($_SESSION['files']['upload_field'] as $form_field_key => $field) { if (is_array($field)) { foreach ($field as $file) { if (is_object($file) && $file->fid == $fid) { if (property_exists($file, 'submit_action') && $file->submit_action == UPLOAD_FIELD_DELETE) { return 'marked_delete'; } return $file; } } } } } return 'no_image'; } function upload_field_name($form) { return (array_key_exists('#original_name', $form)) ? $form['#original_name'] : $form['#name']; } function upload_field_session_handler($op, &$form, $field_key = FALSE, $file = '') { $field_name = upload_field_name($form); switch ($op) { case 'revert': $_SESSION['files']['upload_field'][$field_key][$field_name] = $_SESSION['files']['upload_field'][$field_key][$field_name .'_default']; break; case 'value': $file = (isset($_SESSION['files']['upload_field'][$field_key][$field_name])) ? $_SESSION['files']['upload_field'][$field_key][$field_name] : $_SESSION['files']['upload_field'][$field_key][$field_name .'_default']; return is_object($file) ? $file : ''; break; case 'restore': case 'delete': $submit_action = ($op == 'restore') ? UPLOAD_FIELD_NONE : UPLOAD_FIELD_DELETE; $_SESSION['files']['upload_field'][$field_key][$field_name .'_default']->submit_action = $submit_action; unset($_SESSION['files']['upload_field'][$field_key][$field_name]); if (is_object($form['#default_value'])) { $form['#default_value']->submit_action = $submit_action; } break; case 'store': if (is_object(($_SESSION['files']['upload_field'][$field_key][$field_name .'_default']))) { $file->submit_action = UPLOAD_FIELD_REPLACE; $file->original_fid = $_SESSION['files']['upload_field'][$field_key][$field_name .'_default']->fid; } else { $file->submit_action = UPLOAD_FIELD_NEW; } $_SESSION['files']['upload_field'][$field_key][$field_name] = $file; return $file; break; case 'store default': $_SESSION['files']['upload_field'][$field_key][$field_name .'_default'] = $file; $_SESSION['files']['upload_field'][$field_key]['timestamp'] = time(); return $file; break; } } /** * Parses the post array for a valid field key to distingish * between different forms that use the same upload_field. * * @param string $key Field name */ function _upload_field_key($key, $post = array(), $form = '') { if (isset($post[$key])) { return $post[$key]; } else { if (empty($_SESSION['files']['upload_field']['last_known_key'])) { $_SESSION['files']['upload_field']['last_known_key'] = 1; } // set the session for formators that need this populated // on the original form display $key = $_SESSION['files']['upload_field']['last_known_key']++; upload_field_session_handler('store default', $form, $key, $form['#value']); return $key; } } ########################### image.preview.inc ############################ filepath; $info = image_get_info($image); if ($info) { // create temp file, minimise conflicts by instant touch $tmp_file = file_destination(file_directory_temp() .'/upload_field.'. $info['extension'], FILE_EXISTS_RENAME); if (!image_scale($image, $tmp_file, 75, 75)) { $tmp_file = $image; } $tmp_info = image_get_info($tmp_file); if ($tmp_info) { $headers = array( 'Content-type: '. $tmp_info['mime_type'], 'Content-Length: '. $tmp_info['file_size'], 'Cache-Control: max-age=0, no-cache', 'Expires: '. gmdate('D, d M Y H:i:s', time()) .' GMT', 'Last-Modified: '. time(), ); ob_end_clean(); foreach ($headers as $header) { $header = preg_replace('/\r?\n(?!\t| )/', '', $header); drupal_set_header($header); } // Transfer file in 1024 byte chunks to save memory usage. if ($fd = fopen($tmp_file, 'rb')) { while (!feof($fd)) { print fread($fd, 1024); } fclose($fd); } } // We're using the original if it is too small - do not delete! if ($image != $tmp_file) { unlink($tmp_file); } } if (!headers_sent()) { drupal_not_found(); } exit; }