You are here

image_fupload.module in Image FUpload 6.2

Same filename and directory in other branches
  1. 6.3 image_fupload.module
  2. 6 image_fupload.module

File

image_fupload.module
View source
<?php

define('IMAGE_UNMACHINED', 'image_raw');
define('IMAGE_HALFPROCESSED', 'image_halfwork');
define('IMAGE_PROCESSED', 'image_processed');

/**
 * Implementation of hook_help
 */
function image_fupload_help($path, $arg) {
  switch ($path) {
    case 'admin/help#image_fupload':
      $output = '<p>' . t("The Image FUpload module is used to provide an alternate upload form to image module itself.") . '</p>';
      $output .= '<p>' . t("This is a great advantage because multiple images can be selected with one click which are automatically uploaded and processed without any further user interaction. Additionally, this module fully integrates in image module. Consequently, all settings made by image module are observed (thumb creation, file size limit etc.).") . '</p>';
      $output .= '<p>' . t("Image FUpload administration allows to define some characters which are replaced in the node title by a whitespace. In addition to that, the option can be selected to show a link to the original upload form to those users whose browser doesn't support this Flash / JS solution.") . '</p>';
      $output .= t('<p>You can</p>
<ul>
<li>create images using F(lash)Upload at <a href="!node-create-image">node &gt;&gt; create &gt;&gt; image</a>.</li>
<li>configure Image FUpload settings at <a href="!admin-settings-image-fupload">administer &gt;&gt; settings &gt;&gt; image &gt;&gt; image_fupload</a>.</li>
', array(
        '!node-create-image' => url('node/add/image'),
        '!admin-image-galleries' => url('admin/image/galleries'),
        '!admin-settings-image-fupload' => url('admin/settings/image/image_fupload'),
      )) . '</ul>';
      $output .= '<p>' . t('For more information please read the configuration and customization handbook <a href="!image">Image FUpload page</a>.', array(
        '!image' => 'http://www.drupal.org/handbook/modules/image/',
      )) . '</p>';
      return $output;
  }
}

/**
 * Implementation of hook_menu().
 */
function image_fupload_menu() {
  $items['admin/settings/image/image_fupload'] = array(
    'title' => 'Image FUpload Settings',
    'access arguments' => array(
      'administer site configuration',
    ),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'image_fupload_admin',
    ),
    'description' => 'Configure FUpload Settings',
    'type' => MENU_LOCAL_TASK,
    'file' => 'image_fupload.admin.inc',
  );
  $items['fupload/js'] = array(
    'title' => 'Image FUpload',
    'page callback' => 'fupload_node_create',
    'access arguments' => array(
      'create images',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'node.pages.inc',
    'file path' => drupal_get_path('module', 'node'),
  );
  $items['fupload/js/deletequeue'] = array(
    'title' => 'Image FUpload',
    'page callback' => 'fupload_empty_queue',
    'access arguments' => array(
      'create images',
    ),
    'type' => MENU_CALLBACK,
  );
  $items['fupload/flash'] = array(
    'title' => 'Image FUpload',
    'page callback' => 'fupload_filetransfer',
    'access callback' => TRUE,
    // must be examined later
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implementation of hook_theme() registry.
 **/
function image_fupload_theme() {
  return array(
    'swfupload_settings' => array(
      'template' => 'swfupload-settings',
      'arguments' => array(
        'modulepath' => NULL,
        'uploadpath' => NULL,
        'maxfilesize' => NULL,
        'sessionid' => NULL,
        'uploadlimit' => NULL,
      ),
    ),
    'fupload_create_filename' => array(
      'arguments' => array(
        'image' => NULL,
      ),
    ),
  );
}

/**
 * Implementation of hook_form_alter() registry.
 **/
function image_fupload_form_alter(&$form, $form_state, $form_id) {
  global $user;

  // examine whether it's a new image type & the user wants to have flash
  if ($form_id == "image_node_form" && !isset($form['#node']->nid) && arg(3) != "noflash") {

    // Some needed JS & CSS - Files to be included
    drupal_add_js(drupal_get_path('module', 'image_fupload') . '/swfupload/swfupload.js', 'module');
    drupal_add_js(drupal_get_path('module', 'image_fupload') . '/swfupload/swfupload.queue.js', 'module');
    drupal_add_js(drupal_get_path('module', 'image_fupload') . '/swfupload/fileprogress.js', 'module');
    drupal_add_js(drupal_get_path('module', 'image_fupload') . '/swfupload/handlers.js', 'module');
    drupal_add_js(theme('swfupload_settings', base_path() . drupal_get_path('module', 'image_fupload'), url('fupload/flash'), round(variable_get('image_max_upload_size', 800)), $user->sid, 100), 'inline');
    unset($form['title'], $form['rebuild_images'], $form['buttons']['preview']);

    //don't need this, title will be generated later using filepath
    isset($form['taxonomy']) ? $form['taxonomy']['#weight'] = -8 : "";

    //adds ablility to sort better in this case
    $form['message'] = array(
      '#value' => '<div id="jsstatus"></div>',
      '#weight' => -7,
    );
    $form['image'] = array(
      '#type' => 'fieldset',
      '#title' => t('Images'),
      '#weight' => -6,
      '#attributes' => array(
        'class' => 'flash',
        'id' => 'fsUploadProgress',
      ),
      '#collapsible' => FALSE,
      '#collapsed' => FALSE,
    );
    $form['upload_info'] = array(
      '#value' => t('0 Files uploaded.'),
      '#prefix' => '<div id="divStatus">',
      '#suffix' => '</div>',
      '#weight' => -5,
    );

    // Drupal 6 Bug: can't use "normal" buttons, only submit buttons are possible => workaround
    $form['upload_buttons'] = array(
      '#prefix' => '<div>',
      '#value' => '<input type="button" value="' . t('Select Images') . '" onclick="swfu.selectFiles()" /> <input id="btnCancel" type="button" value="' . t('Cancel All Uploads') . '" onclick="swfu.cancelQueue();" disabled="disabled" /> ',
      '#suffix' => '</div>',
      '#weight' => -4,
    );
    $form['upload_buttons']['node_create'] = array(
      '#type' => 'submit',
      '#value' => t('Process queued images'),
      '#weight' => -3,
      '#ahah' => array(
        'path' => 'fupload/js',
        'event' => 'click',
        'method' => 'replace',
        'wrapper' => 'jsstatus',
        'progress' => array(
          'type' => 'bar',
          'message' => t('Images in queue are processed...'),
        ),
      ),
    );
    $form['upload_buttons']['delete_queue'] = array(
      '#type' => 'submit',
      '#value' => t('Delete queued images'),
      '#weight' => -2,
      '#ahah' => array(
        'path' => 'fupload/js/deletequeue',
        'event' => 'click',
        'method' => 'append',
        'wrapper' => 'jsstatus',
      ),
    );
    $form['buttons']['submit'] = array(
      '#value' => '<input type="button" value="' . t('Upload Images') . '" id="startuploadbutton" onclick="startUploadProcess()" />',
      '#weight' => 5,
      '#submit' => array(
        'node_form_submit',
      ),
    );
    $form['#redirect'] = FALSE;

    // Important that $_POST is not empty after browser submit
    $form['#submit'][0] = '_image_node_form_submit';

    // use our emulated version instead of original one in image.module
  }
}
function fupload_node_create() {
  global $user;
  global $file_cache;

  // Remove images which couldn't be processed completly (--> mostly because of memory excaustion)
  db_query("DELETE FROM {files} WHERE uid = %d AND status = %d AND filename = '%s' LIMIT 3", $user->uid, FILE_STATUS_TEMPORARY, IMAGE_HALFPROCESSED);

  // Get some POST Variables
  $form_build_id = $_POST['form_build_id'];
  $form_id = $_POST['form_id'];
  if (isset($form_build_id) && isset($form_id)) {
    $form_error = 0;
    $message = '';

    // Load the form from the Form API cache.
    $cache = cache_get('form_' . $form_build_id, 'cache_form');
    $form = $cache->data;

    // Some form manipulations
    $form['#post'] = $_POST;
    $form['#post']['title'] = 'Image';

    // Default Value; Title will be overwritten in the next steps
    $form_state = array(
      'rebuild' => TRUE,
    );

    // rebuild option needed to prevent that "_image_node_form_submit" gets executed by drupal_process_form
    $form['#post']['form_id'] = $cache->data['form_id']['#value'];
    $form['title'] = array(
      '#type' => 'textfield',
      '#title' => 'Image',
      '#default_value' => t('Image'),
    );

    // Needed that validation is successful
    drupal_process_form($form_id, $form, $form_state);

    // Only validate input data
    if (!form_get_errors()) {
      $result = db_query("SELECT * FROM {files} WHERE uid = %d AND status = %d AND filename = '%s' LIMIT 0 , 3", $user->uid, FILE_STATUS_TEMPORARY, IMAGE_UNMACHINED);
      while ($image = db_fetch_object($result)) {

        // ahh.. first image to process
        $file_cache['image'] = $image;

        // Add image to cache for image.module
        // Set status flag on image (work on picture can begin); if there are problems with this image, it will be kicked next time
        db_query("UPDATE {files} SET filename = '%s' WHERE fid = %d LIMIT 1", IMAGE_HALFPROCESSED, $image->fid);

        // Create a filename out of the given image information; used a theme function so that it can be customised
        $form['title']['#value'] = check_plain(theme('fupload_create_filename', $image));
        $form = form_builder($form_id, $form, $form_state);

        // Mapping the new title to the form
        node_form_submit($form, $form_state);

        // Submit form --> Save it
        // Prevent that same image is processed twice; deleted later by cron
        db_query("UPDATE {files} SET filename = '%s' WHERE fid = %d LIMIT 1", IMAGE_PROCESSED, $image->fid);
      }

      // no files in cache, so no files have been processed yet because of empty queue
      if (empty($file_cache['image'])) {
        drupal_set_message(t('No images yet in queue.'));
      }

      // Examine how many images are left in queue and inform JS by sending a hidden element
      $result = db_fetch_object(db_query("SELECT COUNT(*) AS img_count FROM {files} WHERE uid = %d AND status = %d AND filename = '%s'", $user->uid, FILE_STATUS_TEMPORARY, IMAGE_UNMACHINED));
      $message .= '<input type="hidden" name="num_queued_images" id="num_queued_images" value="' . $result->img_count . '" />';
    }
    else {

      // Error in received form (for example a required field was not filled); inform JS => user
      $form_error = 1;
      $message .= '<input type="hidden" name="num_queued_images" id="num_queued_images" value="0" />';
    }

    // Inform JS about errors
    $message .= '<input type="hidden" name="form_errors" id="form_errors" value="' . $form_error . '"  />';
    $message .= theme('status_messages');

    // Theme all messages
    drupal_json(array(
      'status' => TRUE,
      'data' => $message,
    ));
  }
  else {
    drupal_json(array(
      'status' => TRUE,
      'data' => t('Error: No or wrong POST Data'),
    ));
  }
}
function fupload_filetransfer() {

  // huh.. swfUpload sends some data...let's see
  global $user;
  $sid = $_POST['PHPSESSID'];

  // validate given session id
  $result = db_query("SELECT * FROM {sessions} WHERE sid = '%s' AND hostname = '%s' LIMIT 0 , 1", $sid, ip_address());
  $upload_user = db_fetch_object($result);
  if (!empty($upload_user)) {

    // Get users profile
    $user = user_load(array(
      'uid' => $upload_user->uid,
    ));

    // Adapt to drupal files structure
    $_FILES['files']['name']['image'] = $_FILES['Filedata']['name'];
    $_FILES['files']['type']['image'] = $_FILES['Filedata']['type'];
    $_FILES['files']['tmp_name']['image'] = $_FILES['Filedata']['tmp_name'];
    $_FILES['files']['error']['image'] = $_FILES['Filedata']['error'];
    $_FILES['files']['size']['image'] = $_FILES['Filedata']['size'];

    // Validators for file_save_upload().
    $validators = array(
      'file_validate_is_image' => array(),
      'file_validate_size' => array(
        variable_get('image_max_upload_size', 800) * 1024,
      ),
    );
    if ($file = file_save_upload('image', $validators)) {
      $image = image_get_info($file->filepath);

      // Get real mime-type
      if (!db_query("UPDATE {files} SET filename = '%s', filemime = '%s' WHERE fid = %d LIMIT 1", IMAGE_UNMACHINED, $image['mime_type'], $file->fid)) {
        drupal_set_header('HTTP/1.1 405 Upload Error');
      }
      print 'OK';

      // Reply something to satisfy swfUpload
    }
    else {
      drupal_set_header('HTTP/1.1 408 Image Error');
    }
  }
  else {
    drupal_access_denied();
  }
}
function fupload_empty_queue() {
  global $user;

  // Set "processed" flag so that these images aren't processed again; images are deleted later by cron (--> temporary files)
  db_query("UPDATE {files} SET filename = '%s' WHERE uid = %d AND status = %d AND filename = '%s' LIMIT 100", IMAGE_PROCESSED, $user->uid, FILE_STATUS_TEMPORARY, IMAGE_UNMACHINED);

  // Output message to user via AJAX
  drupal_set_message(t('All queued images were deleted.'), 'warning');
  drupal_json(array(
    'status' => TRUE,
    'data' => theme('status_messages'),
  ));
}
function theme_fupload_create_filename($image) {

  // Get filename out of filepath
  $filename = trim(basename($image->filepath), ' ');
  $length1 = strlen(strrchr($filename, '.'));
  $length2 = strlen($filename);
  $image_name = ucwords(substr($filename, 0, $length2 - $length1));

  // Remove some given (userdefined) elements
  $replacements = explode(';', variable_get('fupload_title_replacements', '_;{;}'));
  $image_name = str_replace($replacements, ' ', $image_name);
  return $image_name;
}

/**
* Helper function which emulates "image_node_form_submit" of image.module v 1.274 2008/06/16 18:45:58 drewish
* Need this because the static variable "$upload_cache" doesn't seem to persist after execution of "form_execute_handlers" function
*/
function _image_node_form_submit($form, &$form_state) {
  global $file_cache;
  $nid = 'new_node';

  // in this case, we can define it permanentelly
  $file = $file_cache['image'];

  // fill our object with picture information
  // Code from image.module v 1.274 2008/06/16 18:45:58 drewish (line 199++)
  $image_info = image_get_info($file->filepath);
  $aspect_ratio = $image_info['height'] / $image_info['width'];
  $original_size = image_get_sizes(IMAGE_ORIGINAL, $aspect_ratio);
  if (!empty($original_size['width']) && !empty($original_size['height'])) {
    $result = image_scale($file->filepath, $file->filepath, $original_size['width'], $original_size['height']);
    if ($result) {
      clearstatcache();
      $file->filesize = filesize($file->filepath);
      drupal_set_message(t('The original image was resized to fit within the maximum allowed resolution of %width x %height pixels.', array(
        '%width' => $original_size['width'],
        '%height' => $original_size['height'],
      )));
    }
  }

  // We're good to go.
  $form_state['values']['images'][IMAGE_ORIGINAL] = $file->filepath;
  $form_state['values']['rebuild_images'] = FALSE;
  $form_state['values']['new_file'] = TRUE;

  // Call hook to allow other modules to modify the original image.
  module_invoke_all('image_alter', $form_state['values'], $file->filepath, IMAGE_ORIGINAL);
  $form_state['values']['images'] = _image_build_derivatives((object) $form_state['values'], TRUE);

  // Store the new file into the session.
  $_SESSION['image_new_files'][$nid] = $form_state['values']['images'];
}

Functions

Namesort descending Description
fupload_empty_queue
fupload_filetransfer
fupload_node_create
image_fupload_form_alter Implementation of hook_form_alter() registry.
image_fupload_help Implementation of hook_help
image_fupload_menu Implementation of hook_menu().
image_fupload_theme Implementation of hook_theme() registry.
theme_fupload_create_filename
_image_node_form_submit Helper function which emulates "image_node_form_submit" of image.module v 1.274 2008/06/16 18:45:58 drewish Need this because the static variable "$upload_cache" doesn't seem to persist after execution of…

Constants