From dc65b62aceddb0dc5f7b61bd1f1f3d46015a5969 Mon Sep 17 00:00:00 2001
From: Dries Buytaert <dries@buytaert.net>
Date: Sun, 16 Nov 2008 19:41:14 +0000
Subject: [PATCH] - Patch #74645 by drewish, roychri et al: modify
 file_scan_directory to use a regex for the nomask (and code clean-up).

---
 includes/bootstrap.inc               | 18 ++++++++--------
 includes/common.inc                  |  6 +++---
 includes/file.inc                    |  6 +++---
 includes/locale.inc                  |  4 ++--
 includes/registry.inc                |  2 +-
 install.php                          |  4 ++--
 modules/book/book.module             |  2 +-
 modules/comment/comment.module       | 18 ++++++++--------
 modules/comment/comment.pages.inc    |  2 +-
 modules/simpletest/tests/file.test   | 32 ++++++++++++++++++++++++++++
 modules/simpletest/tests/schema.test |  2 +-
 11 files changed, 64 insertions(+), 32 deletions(-)

diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index a08bff5ef9bd..6cb1e02f0644 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -215,12 +215,12 @@
 define('PASS_THROUGH', -1);
 
 /**
- * Signals that the registry lookup cache should be reset. 
+ * Signals that the registry lookup cache should be reset.
  */
 define('REGISTRY_RESET_LOOKUP_CACHE', 1);
 
 /**
- * Signals that the registry lookup cache should be written to storage. 
+ * Signals that the registry lookup cache should be written to storage.
  */
 define('REGISTRY_WRITE_LOOKUP_CACHE', 2);
 
@@ -1475,7 +1475,7 @@ function drupal_autoload_class($class) {
  * Helper to check for a resource in the registry.
  *
  * @param $type
- *   The type of resource we are looking up, or one of the constants 
+ *   The type of resource we are looking up, or one of the constants
  *   REGISTRY_RESET_LOOKUP_CACHE or REGISTRY_WRITE_LOOKUP_CACHE, which
  *   signal that we should reset or write the cache, respectively.
  * @param $name
@@ -1491,7 +1491,7 @@ function _registry_check_code($type, $name = NULL) {
   if (!isset($lookup_cache)) {
     $lookup_cache = _registry_get_lookup_cache();
   }
-  
+
   // When we rebuild the registry, we need to reset this cache so
   // we don't keep lookups for resources that changed during the rebuild.
   if ($type == REGISTRY_RESET_LOOKUP_CACHE) {
@@ -1508,8 +1508,8 @@ function _registry_check_code($type, $name = NULL) {
     }
     return;
   }
-  
-  // $type can be one of 'function', 'interface' or 'class', so we only need the 
+
+  // $type can be one of 'function', 'interface' or 'class', so we only need the
   // first letter to keep the cache key unique.
   $cache_key = $type[0] . $name;
   if (isset($lookup_cache[$cache_key])) {
@@ -1518,7 +1518,7 @@ function _registry_check_code($type, $name = NULL) {
     }
     return $lookup_cache[$cache_key];
   }
-  
+
   // This function may get called when the default database is not active, but
   // there is no reason we'd ever want to not use the default database for
   // this query.
@@ -1559,7 +1559,7 @@ function registry_rebuild() {
  * Wrapper function to perform array to string conversion of lookup cache.
  */
 function _registry_set_lookup_cache(array $lookup_cache) {
-  // Cache a string, not an array, so we can avoid the memory usage hit 
+  // Cache a string, not an array, so we can avoid the memory usage hit
   // from serialize() in the cache system.
   $key_value_pairs = array();
   foreach ($lookup_cache as $key => $value) {
@@ -1572,7 +1572,7 @@ function _registry_set_lookup_cache(array $lookup_cache) {
  * Wrapper function to perform string to array conversion of lookup cache.
  */
 function _registry_get_lookup_cache() {
-  // In _registry_set_lookup_cache, we cache a string, not an array, to avoid 
+  // In _registry_set_lookup_cache, we cache a string, not an array, to avoid
   // serialize() in the cache system. serialize() makes a copy, and thus uses
   // extra memory, which we are trying to avoid.
   $lookup_cache = array();
diff --git a/includes/common.inc b/includes/common.inc
index 2b79cc3d2b35..7ac9bad5b969 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -2116,7 +2116,7 @@ function _drupal_load_stylesheet($matches) {
  * Delete all cached CSS files.
  */
 function drupal_clear_css_cache() {
-  file_scan_directory(file_create_path('css'), '/.*/', array('.', '..', 'CVS'), 'file_unmanaged_delete', TRUE);
+  file_scan_directory(file_create_path('css'), '/.*/', '/(\.\.?|CVS)$/', 'file_unmanaged_delete', TRUE);
 }
 
 /**
@@ -2553,7 +2553,7 @@ function drupal_build_js_cache($files, $filename) {
  * Delete all cached JS files.
  */
 function drupal_clear_js_cache() {
-  file_scan_directory(file_create_path('js'), '/.*/', array('.', '..', 'CVS'), 'file_unmanaged_delete', TRUE);
+  file_scan_directory(file_create_path('js'), '/.*/', '/(\.\.?|CVS)$/', 'file_unmanaged_delete', TRUE);
   variable_set('javascript_parsed', array());
 }
 
@@ -2924,7 +2924,7 @@ function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1)
 
   // Get current list of items
   foreach ($searchdir as $dir) {
-    $files = array_merge($files, file_scan_directory($dir, $mask, array('.', '..', 'CVS'), 0, TRUE, $key, $min_depth));
+    $files = array_merge($files, file_scan_directory($dir, $mask, '/(\.\.?|CVS)$/', 0, TRUE, $key, $min_depth));
   }
 
   return $files;
diff --git a/includes/file.inc b/includes/file.inc
index 27d9d729a59d..4327e0b85611 100644
--- a/includes/file.inc
+++ b/includes/file.inc
@@ -1259,7 +1259,7 @@ function file_download() {
  * @param $mask
  *   The preg_match() regular expression of the files to find.
  * @param $nomask
- *   An array of files/directories to ignore.
+ *   The preg_match() regular expression of the files to ignore.
  * @param $callback
  *   The callback function to call for each match.
  * @param $recurse
@@ -1280,13 +1280,13 @@ function file_download() {
  *   "path", "basename", and "name" members corresponding to the
  *   matching files.
  */
-function file_scan_directory($dir, $mask, $nomask = array('.', '..', 'CVS'), $callback = 0, $recurse = TRUE, $key = 'filename', $min_depth = 0, $depth = 0) {
+function file_scan_directory($dir, $mask, $nomask = '/(\.\.?|CVS)$/', $callback = 0, $recurse = TRUE, $key = 'filename', $min_depth = 0, $depth = 0) {
   $key = (in_array($key, array('filename', 'basename', 'name')) ? $key : 'filename');
   $files = array();
 
   if (is_dir($dir) && $handle = opendir($dir)) {
     while (FALSE !== ($file = readdir($handle))) {
-      if (!in_array($file, $nomask) && $file[0] != '.') {
+      if (!preg_match($nomask, $file) && $file[0] != '.') {
         if (is_dir("$dir/$file") && $recurse) {
           // Give priority to files in this folder by merging them in after any subdirectory files.
           $files = array_merge(file_scan_directory("$dir/$file", $mask, $nomask, $callback, $recurse, $key, $min_depth, $depth + 1), $files);
diff --git a/includes/locale.inc b/includes/locale.inc
index 793e50010ac8..3e877545d4df 100644
--- a/includes/locale.inc
+++ b/includes/locale.inc
@@ -2485,7 +2485,7 @@ function locale_batch_by_language($langcode, $finished = NULL, $skip = array())
     // with names ending with $langcode.po. This allows for filenames
     // like node-module.de.po to let translators use small files and
     // be able to import in smaller chunks.
-    $files = array_merge($files, file_scan_directory(dirname($component->filename) . '/translations', '/(^|\.)' . $langcode . '\.po$/', array('.', '..', 'CVS'), 0, FALSE));
+    $files = array_merge($files, file_scan_directory(dirname($component->filename) . '/translations', '/(^|\.)' . $langcode . '\.po$/', '/(\.\.?|CVS)$/', 0, FALSE));
     $components[] = $component->name;
   }
 
@@ -2517,7 +2517,7 @@ function locale_batch_by_component($components, $finished = '_locale_batch_syste
         // as $langcode.po or with names ending with $langcode.po. This allows
         // for filenames like node-module.de.po to let translators use small
         // files and be able to import in smaller chunks.
-        $files = array_merge($files, file_scan_directory(dirname($component->filename) . '/translations', '/(^|\.)(' . $language_list . ')\.po$/', array('.', '..', 'CVS'), 0, FALSE));
+        $files = array_merge($files, file_scan_directory(dirname($component->filename) . '/translations', '/(^|\.)(' . $language_list . ')\.po$/', '/(\.\.?|CVS)$/', 0, FALSE));
       }
     }
     return _locale_batch_build($files, $finished);
diff --git a/includes/registry.inc b/includes/registry.inc
index ec968dd2ad6f..e4eb56348879 100644
--- a/includes/registry.inc
+++ b/includes/registry.inc
@@ -73,7 +73,7 @@ function _registry_rebuild() {
 
   $unchanged_resources = array();
   foreach (_registry_get_lookup_cache() as $key => $file) {
-    // If the file for this cached resource is carried over unchanged from 
+    // If the file for this cached resource is carried over unchanged from
     // the last registry build, then we can safely re-cache it.
     if ($file && in_array($file, array_keys($files)) && !in_array($file, $parsed_files)) {
       $unchanged_resources[$key] = $file;
diff --git a/install.php b/install.php
index c30b302d69be..a510df20cc7d 100644
--- a/install.php
+++ b/install.php
@@ -409,7 +409,7 @@ function install_settings_form_submit($form, &$form_state) {
  * Find all .profile files.
  */
 function install_find_profiles() {
-  return file_scan_directory('./profiles', '/\.profile$/', array('.', '..', 'CVS'), 0, TRUE, 'name', 0);
+  return file_scan_directory('./profiles', '/\.profile$/', '/(\.\.?|CVS)$/', 0, TRUE, 'name', 0);
 }
 
 /**
@@ -495,7 +495,7 @@ function install_select_profile_form(&$form_state, $profile_files) {
  * Find all .po files for the current profile.
  */
 function install_find_locales($profilename) {
-  $locales = file_scan_directory('./profiles/' . $profilename . '/translations', '/\.po$/', array('.', '..', 'CVS'), 0, FALSE);
+  $locales = file_scan_directory('./profiles/' . $profilename . '/translations', '/\.po$/', '/(\.\.?|CVS)$/', 0, FALSE);
   array_unshift($locales, (object) array('name' => 'en'));
   return $locales;
 }
diff --git a/modules/book/book.module b/modules/book/book.module
index 5b0f5f643126..fad546bda715 100644
--- a/modules/book/book.module
+++ b/modules/book/book.module
@@ -305,7 +305,7 @@ function book_get_books() {
       }
     }
   }
-  
+
   return $all_books;
 }
 
diff --git a/modules/comment/comment.module b/modules/comment/comment.module
index c8573d7c0216..4730dc0a33f8 100644
--- a/modules/comment/comment.module
+++ b/modules/comment/comment.module
@@ -370,16 +370,16 @@ function comment_new_page_count($num_comments, $new_replies, $node) {
   else {
     // Threaded comments.
     // Find the first thread with a new comment.
-    $result = db_query_range('(SELECT thread 
-      FROM {comments} 
-      WHERE nid = :nid 
-        AND status = 0 
-      ORDER BY timestamp DESC) 
+    $result = db_query_range('(SELECT thread
+      FROM {comments}
+      WHERE nid = :nid
+        AND status = 0
+      ORDER BY timestamp DESC)
       ORDER BY SUBSTRING(thread, 1, (LENGTH(thread) - 1))', array(':nid' => $node->nid), 0, $new_replies)
       ->fetchField();
     $thread = substr($result, 0, -1);
     $count = db_query('SELECT COUNT(*) FROM {comments} WHERE nid = :nid AND status = 0 AND SUBSTRING(thread, 1, (LENGTH(thread) - 1)) < :thread', array(
-      ':nid' => $node->nid, 
+      ':nid' => $node->nid,
       ':thread' => $thread))
       ->fetchField();
     $pageno =  $count / $comments_per_page;
@@ -763,7 +763,7 @@ function comment_save($edit) {
           $parent->thread = (string) rtrim((string) $parent->thread, '/');
           // Get the max value in *this* thread.
           $max = db_query("SELECT MAX(thread) FROM {comments} WHERE thread LIKE :thread AND nid = :nid", array(
-            ':thread' => $parent->thread .'.%', 
+            ':thread' => $parent->thread .'.%',
             ':nid' => $edit['nid']))
             ->fetchField();
 
@@ -1006,7 +1006,7 @@ function comment_render($node, $cid = 0) {
       }
     }
     else {
-      
+
       //TODO Convert to dynamic queries once the pager query is updated to the new DBTNG API.
 
       // Multiple comment view.
@@ -1150,7 +1150,7 @@ function comment_num_replies($pid) {
 
   if (!isset($cache[$pid])) {
     $cache[$pid] = db_query('SELECT COUNT(cid) FROM {comments} WHERE pid = :pid AND status = :status', array(
-      ':pid' => $pid, 
+      ':pid' => $pid,
       ':status' => COMMENT_PUBLISHED))
       ->fetchField();
   }
diff --git a/modules/comment/comment.pages.inc b/modules/comment/comment.pages.inc
index d1a3026fd683..cc2913520f35 100644
--- a/modules/comment/comment.pages.inc
+++ b/modules/comment/comment.pages.inc
@@ -70,7 +70,7 @@ function comment_reply($node, $pid = NULL) {
       if ($pid) {
         // Load the comment whose cid = $pid
         $comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid AND c.status = :status', array(
-          ':cid'=>$pid, 
+          ':cid'=>$pid,
           ':status'=>COMMENT_PUBLISHED))->fetchObject();
         if ( $comment ) {
           // If that comment exists, make sure that the current comment and the
diff --git a/modules/simpletest/tests/file.test b/modules/simpletest/tests/file.test
index 564ecea3503a..5da57ee5a625 100644
--- a/modules/simpletest/tests/file.test
+++ b/modules/simpletest/tests/file.test
@@ -541,6 +541,38 @@ class FileDirectoryTest extends FileTestCase {
 }
 
 
+/**
+ * Tests the file_scan_directory() function.
+ */
+class FileScanDirectoryTest extends FileTestCase {
+  /**
+   * Implementation of getInfo().
+   */
+  function getInfo() {
+    return array(
+      'name' => t('File scan directory'),
+      'description' => t('Tests the file_scan_directory() function.'),
+      'group' => t('File'),
+    );
+  }
+
+  /**
+   * Check that the no-mask parameter is honored.
+   */
+  function testNoMask() {
+    $path = $this->original_file_directory . '/simpletest';
+
+    // Grab a listing of all the JS files.
+    $all_files = file_scan_directory($path, '/javascript*/');
+    $this->assertEqual(2, count($all_files), t('Found two, expected javascript files.'));
+
+    // Now use the nomast parameter to filter out the .script file.
+    $filtered_files = file_scan_directory($path, '/javascript*/', '/.script$/');
+    $this->assertEqual(1, count($filtered_files), t('Filtered correctly.'));
+  }
+}
+
+
 /**
  * Deletion related tests.
  */
diff --git a/modules/simpletest/tests/schema.test b/modules/simpletest/tests/schema.test
index eeafc7796435..1e287e06dab2 100644
--- a/modules/simpletest/tests/schema.test
+++ b/modules/simpletest/tests/schema.test
@@ -19,7 +19,7 @@ class SchemaTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * 
+   *
    */
   function testSchema() {
     // Try creating a table.
-- 
GitLab