Browse Source

ZF-7271, ZF-8913: backport r20903 to trunk

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@20904 44c647ce-9c0f-0410-b52a-842ac1e357ba
matthew 16 years ago
parent
commit
311676a927

+ 36 - 7
library/Zend/Loader.php

@@ -173,16 +173,45 @@ class Zend_Loader
      */
     public static function isReadable($filename)
     {
-        // Phar occasionally fails when using fopen()
-        if (strpos($filename, 'phar://') !== false) {
-            return is_readable($filename);
+        foreach (self::explodeIncludePath() as $path) {
+            if ($path == '.') {
+                if (is_readable($filename)) {
+                    return true;
+                }
+                continue;
+            }
+            $file = $path . '/' . $filename;
+            if (is_readable($file)) {
+                return true;
+            }
         }
+        return false;
+    }
 
-        if (!$fh = @fopen($filename, 'r', true)) {
-            return false;
+    /**
+     * Explode an include path into an array
+     *
+     * If no path provided, uses current include_path. Works around issues that
+     * occur when the path includes stream schemas.
+     * 
+     * @param  string|null $path 
+     * @return array
+     */
+    public static function explodeIncludePath($path = null)
+    {
+        if (null === $path) {
+            $path = get_include_path();
         }
-        @fclose($fh);
-        return true;
+
+        if (PATH_SEPARATOR == ':') {
+            // On *nix systems, include_paths which include paths with a stream 
+            // schema cannot be safely explode'd, so we have to be a bit more
+            // intelligent in the approach.
+            $paths = preg_split('#:(?!//)#', $path);
+        } else {
+            $paths = explode(PATH_SEPARATOR, $path);
+        }
+        return $paths;
     }
 
     /**

+ 2 - 1
library/Zend/Reflection/File.php

@@ -109,7 +109,8 @@ class Zend_Reflection_File implements Reflector
      */
     public static function findRealpathInIncludePath($fileName)
     {
-        $includePaths = explode(PATH_SEPARATOR, get_include_path());
+        require_once 'Zend/Loader.php';
+        $includePaths = Zend_Loader::explodeIncludePath();
         while (count($includePaths) > 0) {
             $filePath = array_shift($includePaths) . DIRECTORY_SEPARATOR . $fileName;
 

+ 2 - 1
library/Zend/Tool/Framework/Loader/IncludePathLoader.php

@@ -46,7 +46,8 @@ class Zend_Tool_Framework_Loader_IncludePathLoader extends Zend_Tool_Framework_L
      */
     protected function _getFiles()
     {
-        $paths = explode(PATH_SEPARATOR, get_include_path());
+        require_once 'Zend/Loader.php';
+        $paths = Zend_Loader::explodeIncludePath();
 
         // used for checking similarly named files
         $relativeItems   = array();

+ 3 - 3
library/Zend/Tool/Project/Context/Zf/ZfStandardLibraryDirectory.php

@@ -87,8 +87,8 @@ class Zend_Tool_Project_Context_Zf_ZfStandardLibraryDirectory extends Zend_Tool_
      */
     protected function _getZfPath()
     {
-        foreach (explode(PATH_SEPARATOR, get_include_path()) as $includePath) {
-
+        require_once 'Zend/Loader.php';
+        foreach (Zend_Loader::explodeIncludePath() as $includePath) {
             if (!file_exists($includePath) || $includePath[0] == '.') {
                 continue;
             }
@@ -101,4 +101,4 @@ class Zend_Tool_Project_Context_Zf_ZfStandardLibraryDirectory extends Zend_Tool_
         return false;
     }
 
-}
+}

BIN
tests/Zend/Loader/_files/Zend_LoaderTest.phar


+ 57 - 1
tests/Zend/LoaderTest.php

@@ -256,7 +256,7 @@ class Zend_LoaderTest extends PHPUnit_Framework_TestCase
         $this->assertFalse(Zend_Loader::isReadable(__FILE__ . '.foobaar'));
 
         // test that a file in include_path gets loaded, see ZF-2985
-        $this->assertTrue(Zend_Loader::isReadable('Zend/Controller/Front.php'));
+        $this->assertTrue(Zend_Loader::isReadable('Zend/Controller/Front.php'), get_include_path());
     }
 
     /**
@@ -470,6 +470,62 @@ class Zend_LoaderTest extends PHPUnit_Framework_TestCase
     }
 
     /**
+     * @group ZF-7271
+     * @group ZF-8913
+     */
+    public function testIsReadableShouldHonorStreamDefinitions()
+    {
+        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+            $this->markTestSkipped();
+        }
+
+        $pharFile = dirname(__FILE__) . '/Loader/_files/Zend_LoaderTest.phar';
+        $phar     = new Phar($pharFile, 0, 'zlt.phar');
+        $incPath = 'phar://zlt.phar'
+                 . PATH_SEPARATOR . $this->includePath;
+        set_include_path($incPath);
+        $this->assertTrue(Zend_Loader::isReadable('User.php'));
+        unset($phar);
+    }
+
+    /**
+     * @group ZF-8913
+     */
+    public function testIsReadableShouldNotLockWhenTestingForNonExistantFileInPhar()
+    {
+        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+            $this->markTestSkipped();
+        }
+
+        $pharFile = dirname(__FILE__) . '/Loader/_files/Zend_LoaderTest.phar';
+        $phar     = new Phar($pharFile, 0, 'zlt.phar');
+        $incPath = 'phar://zlt.phar'
+                 . PATH_SEPARATOR . $this->includePath;
+        set_include_path($incPath);
+        $this->assertFalse(Zend_Loader::isReadable('does-not-exist'));
+        unset($phar);
+    }
+
+    /**
+     * @group ZF-7271
+     */
+    public function testExplodeIncludePathProperlyIdentifiesStreamSchemes()
+    {
+        if (PATH_SEPARATOR != ':') {
+            $this->markTestSkipped();
+        }
+        $path = 'phar://zlt.phar:/var/www:.:filter://[a-z]:glob://*';
+        $paths = Zend_Loader::explodeIncludePath($path);
+        $this->assertSame(array(
+            'phar://zlt.phar',
+            '/var/www',
+            '.',
+            'filter://[a-z]',
+            'glob://*',
+        ), $paths);
+    }
+
+    /**
      * In order to play nice with spl_autoload, an autoload callback should
      * *not* emit errors (exceptions are okay). ZF-2923 requests that this
      * behavior be applied, which counters the previous request in ZF-2463.