Implement upload progress feedback in core.

From: damz <damz@dev.local.local>


---

 upload/upload.module |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 63 insertions(+), 0 deletions(-)

diff --git modules/upload/upload.module modules/upload/upload.module
index 8d296a2..f011687 100644
--- modules/upload/upload.module
+++ modules/upload/upload.module
@@ -93,6 +93,11 @@ function upload_menu() {
     'access arguments' => array('upload files'),
     'type' => MENU_CALLBACK,
   );
+  $items['upload/progress'] = array(
+    'page callback' => 'upload_progress',
+    'access arguments' => array('upload files'),
+    'type' => MENU_CALLBACK,
+  );
   $items['admin/settings/uploads'] = array(
     'title' => 'File uploads',
     'description' => 'Control how files may be attached to content.',
@@ -576,6 +581,17 @@ function _upload_form($node) {
     }
     $limit_description .= t('Only files with the following extensions may be uploaded: %extensions. ', array('%extensions' => $limits['extensions']));
 
+    if ($implementation = upload_progress_implementation()) {
+      $upload_progress_key = md5(mt_rand());
+
+      if ($implementation == 'apc') {
+        $form['APC_UPLOAD_PROGRESS'] = array('#type' => 'hidden', '#value' => $upload_progress_key);
+      }
+      else if ($implementation == 'uploadprogress') {
+        $form['UPLOAD_IDENTIFIER'] = array('#type' => 'hidden', '#value' => $upload_progress_key);
+      }
+    }
+
     $form['new']['#weight'] = 10;
     $form['new']['upload'] = array(
       '#type' => 'file',
@@ -594,6 +610,11 @@ function _upload_form($node) {
       ),
       '#submit' => array('node_form_submit_build_node'),
     );
+
+    if (isset($upload_progress_key)) {
+      // Add the upload progress callback.
+      $form['new']['attach']['#ahah']['progress']['path'] = 'upload/progress/' . $upload_progress_key;
+    }
   }
 
   return $form;
@@ -705,3 +726,45 @@ function upload_js() {
   print drupal_to_js(array('status' => TRUE, 'data' => $output));
   exit;
 }
+
+/**
+ * Determine which upload progress implementation to use, if any available.
+ */
+function upload_progress_implementation() {
+  static $implementation;
+  if (!isset($implementation)) {
+    if (extension_loaded('apc') && ini_get('apc.rfc1867')) {
+      $implementation = 'apc';
+    }
+    else if (extension_loaded('uploadprogress')) {
+      $implementation = 'uploadprogress';
+    }
+  }
+  return $implementation;
+}
+
+/**
+ * Menu callback for upload progress.
+ */
+function upload_progress($key) {
+  $progress = array(
+    'message' => t('Please wait...'),
+    'percentage' => -1,
+  );
+
+  $implementation = upload_progress_implementation();
+  if ($implementation == 'apc') {
+    $status = apc_fetch('upload_' . $key);
+    if (isset($status['current']) && !empty($status['total'])) {
+      $progress['percentage'] = round(100 * $status['current'] / $status['total']);
+    }
+  }
+  else if ($implementation == 'uploadprogress') {
+    $status = uploadprogress_get_info($key);
+    if (isset($status['bytes_uploaded']) && !empty($status['bytes_total'])) {
+      $progress['percentage'] = round(100 * $status['current'] / $status['total']);
+    }
+  }
+
+  drupal_json($progress);
+}
