The Windows Azure Blob module allows for the uploading and storing of files on the Windows Azure storage service. But unfortunately, this module is not compatible with IMCE.
The problem is that with Windows Azure Storage, you don't have direct access to the file system. You have to go through a REST API to get information about stored files. So, PHP methods like opendir or readdir can't work in such configuration.

To bypass this problem, the azure_blob module has a class WindowsAzureBlobStreamWrapper which implements the DrupalStreamWrapperInterface interface. This interface has several interesting methods, such has dir_opendir and dir_readdir, which can be used as replacement for the PHP ones.

So, with this idea, I've made some modifications to IMCE module to avoid direct calls to low-level PHP methods like opendir or readdir. Instead, I use the Drupal built-in file stream wrapper mechanism to retrieve the correct implementation class, base on the file scheme.

Here's the patch:

--- a/sites/all/modules/imce/inc/imce.page.inc
+++ b/sites/all/modules/imce/inc/imce.page.inc
@@ -971,13 +971,22 @@ function imce_scan_directory($dirname, $imce) {
   $directory = array('dirsize' => 0, 'files' => array(), 'subdirectories' => array(), 'error' => FALSE);
   $diruri = imce_dir_uri($imce, $dirname);

-  if (!is_string($dirname) || $dirname == '' || !$handle = opendir($diruri)) {
+  // Attempt to retrieve the appropriate wrapper.
+  $fileStreamWrapper = file_stream_wrapper_get_instance_by_uri($diruri);
+  if (!$fileStreamWrapper) {
+    // raise an error if no wrapper was found.
     imce_inaccessible_directory($dirname, $imce);
     $directory['error'] = TRUE;
     return $directory;
   }

-  while (($file = readdir($handle)) !== FALSE) {
+  if (!is_string($dirname) || $dirname == '' || !$handle = $fileStreamWrapper->dir_opendir($diruri)) {
+    imce_inaccessible_directory($dirname, $imce);
+    $directory['error'] = TRUE;
+    return $directory;
+  }
+
+  while (($file = $fileStreamWrapper->dir_readdir($handle)) !== FALSE) {

     // Do not include dot files and folders
     if (substr($file, 0, 1) === '.') {
@@ -1008,7 +1017,7 @@ function imce_scan_directory($dirname, $imce) {
     $directory['dirsize'] += $size;
   }

-  closedir($handle);
+  $fileStreamWrapper->dir_closedir($handle);
   sort($directory['subdirectories']);
   return $directory;
 }

This adds a layer of abstraction and add the possibility to have different implementations based on different scheme.

While this patch work in simple situations, this patch is incomplete at the moment. Methods likes is_dir, filesize or filemtime doesn't have any equivalent in DrupalStreamWrapperInterface. So they can't be ported easily to use this new abstraction layer.
Also, the method imce_image_info (which is called inside imce_scan_directory) also uses low-level PHP functions such as is_file and getimagesize which may not work in a Windows Azure Storage configuration.

I'm pretty sure a better and more robust patch could be applied for this problem, but this one is a good start.
Also, I've done another patch in azure_blob to avoid another compatibility issue between azure_blob and IMCE Drupal modules: https://www.drupal.org/node/2423001. Hope this helps anyone having the same issue :)

Cheers,

Romain

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

ufku’s picture

Version: 7.x-1.6 » 7.x-1.x-dev
Status: Active » Closed (works as designed)

IMCE works with custom stream wrappers like s3. Azure blob module should be implementing a similar interface.