mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-11-04 06:37:55 +08:00 
			
		
		
		
	Fixes #13465: Added yii\helpers\FileHelper::findDirectory() method
				
					
				
			This commit is contained in:
		@ -4,6 +4,7 @@ Yii Framework 2 Change Log
 | 
			
		||||
2.0.14 under development
 | 
			
		||||
------------------------
 | 
			
		||||
 | 
			
		||||
- Enh #13465: Added `yii\helpers\FileHelper::findDirectory()` method (ArsSirek, developeruz)
 | 
			
		||||
- Enh #8527: Added `yii\i18n\Locale` component having `getCurrencySymbol()` method (amarox, samdark)
 | 
			
		||||
- Enh #14546: Added `dataDirectory` property into `BaseActiveFixture` (leandrogehlen)
 | 
			
		||||
- Bug #15522: Fixed `yii\db\ActiveRecord::refresh()` method does not use an alias in the condition (vladis84)
 | 
			
		||||
 | 
			
		||||
@ -459,20 +459,10 @@ class BaseFileHelper
 | 
			
		||||
     */
 | 
			
		||||
    public static function findFiles($dir, $options = [])
 | 
			
		||||
    {
 | 
			
		||||
        if (!is_dir($dir)) {
 | 
			
		||||
            throw new InvalidParamException("The dir argument must be a directory: $dir");
 | 
			
		||||
        }
 | 
			
		||||
        $dir = rtrim($dir, DIRECTORY_SEPARATOR);
 | 
			
		||||
        if (!isset($options['basePath'])) {
 | 
			
		||||
            // this should be done only once
 | 
			
		||||
            $options['basePath'] = realpath($dir);
 | 
			
		||||
            $options = static::normalizeOptions($options);
 | 
			
		||||
        }
 | 
			
		||||
        $dir = self::clearDir($dir);
 | 
			
		||||
        $options = self::setBasePath($dir, $options);
 | 
			
		||||
        $list = [];
 | 
			
		||||
        $handle = opendir($dir);
 | 
			
		||||
        if ($handle === false) {
 | 
			
		||||
            throw new InvalidParamException("Unable to open directory: $dir");
 | 
			
		||||
        }
 | 
			
		||||
        $handle = self::openDir($dir);
 | 
			
		||||
        while (($file = readdir($handle)) !== false) {
 | 
			
		||||
            if ($file === '.' || $file === '..') {
 | 
			
		||||
                continue;
 | 
			
		||||
@ -491,6 +481,83 @@ class BaseFileHelper
 | 
			
		||||
        return $list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the directories found under the specified directory and subdirectories.
 | 
			
		||||
     * @param string $dir the directory under which the files will be looked for.
 | 
			
		||||
     * @param array $options options for directory searching. Valid options are:
 | 
			
		||||
     *
 | 
			
		||||
     * - `filter`: callback, a PHP callback that is called for each directory or file.
 | 
			
		||||
     *   The signature of the callback should be: `function ($path)`, where `$path` refers the full path to be filtered.
 | 
			
		||||
     *   The callback can return one of the following values:
 | 
			
		||||
     *
 | 
			
		||||
     *   * `true`: the directory will be returned
 | 
			
		||||
     *   * `false`: the directory will NOT be returned
 | 
			
		||||
     *
 | 
			
		||||
     * - `recursive`: boolean, whether the files under the subdirectories should also be looked for. Defaults to `true`.
 | 
			
		||||
     * @return array directories found under the directory, in no particular order. Ordering depends on the files system used.
 | 
			
		||||
     * @throws InvalidParamException if the dir is invalid.
 | 
			
		||||
     * @since 2.0.14
 | 
			
		||||
     */
 | 
			
		||||
    public static function findDirectory($dir, $options = [])
 | 
			
		||||
    {
 | 
			
		||||
        $dir = self::clearDir($dir);
 | 
			
		||||
        $options = self::setBasePath($dir, $options);
 | 
			
		||||
        $list = [];
 | 
			
		||||
        $handle = self::openDir($dir);
 | 
			
		||||
        while (($file = readdir($handle)) !== false) {
 | 
			
		||||
            if ($file === '.' || $file === '..') {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            $path = $dir . DIRECTORY_SEPARATOR . $file;
 | 
			
		||||
            if (is_dir($path) && static::filterPath($path, $options)) {
 | 
			
		||||
                $list[] = $path;
 | 
			
		||||
                if (!isset($options['recursive']) || $options['recursive']) {
 | 
			
		||||
                    $list = array_merge($list, static::findDirectory($path, $options));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        closedir($handle);
 | 
			
		||||
 | 
			
		||||
        return $list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * @param string $dir
 | 
			
		||||
     */
 | 
			
		||||
    private static function setBasePath($dir, $options)
 | 
			
		||||
    {
 | 
			
		||||
        if (!isset($options['basePath'])) {
 | 
			
		||||
            // this should be done only once
 | 
			
		||||
            $options['basePath'] = realpath($dir);
 | 
			
		||||
            $options = static::normalizeOptions($options);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $options;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * @param string $dir
 | 
			
		||||
     */
 | 
			
		||||
    private static function openDir($dir)
 | 
			
		||||
    {
 | 
			
		||||
        $handle = opendir($dir);
 | 
			
		||||
        if ($handle === false) {
 | 
			
		||||
            throw new InvalidParamException("Unable to open directory: $dir");
 | 
			
		||||
        }
 | 
			
		||||
        return $handle;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * @param string $dir
 | 
			
		||||
     */
 | 
			
		||||
    private static function clearDir($dir)
 | 
			
		||||
    {
 | 
			
		||||
        if (!is_dir($dir)) {
 | 
			
		||||
            throw new InvalidParamException("The dir argument must be a directory: $dir");
 | 
			
		||||
        }
 | 
			
		||||
        return rtrim($dir, DIRECTORY_SEPARATOR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks if the given file path satisfies the filtering options.
 | 
			
		||||
     * @param string $path the path of the file or directory to be checked
 | 
			
		||||
 | 
			
		||||
@ -882,4 +882,44 @@ class FileHelperTest extends TestCase
 | 
			
		||||
        $this->assertFileNotExists($dstDirName . DIRECTORY_SEPARATOR . 'dir2');
 | 
			
		||||
        $this->assertFileNotExists($dstDirName . DIRECTORY_SEPARATOR . 'dir3');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testFindDirectory()
 | 
			
		||||
    {
 | 
			
		||||
        $dirName = 'test_dir';
 | 
			
		||||
        $this->createFileStructure([
 | 
			
		||||
            $dirName => [
 | 
			
		||||
               'test_sub_dir' => [
 | 
			
		||||
                    'file_1.txt' => 'sub dir file 1 content',
 | 
			
		||||
                ],
 | 
			
		||||
                'second_sub_dir' => [
 | 
			
		||||
                    'file_1.txt' => 'sub dir file 2 content',
 | 
			
		||||
                ],
 | 
			
		||||
            ],
 | 
			
		||||
        ]);
 | 
			
		||||
        $basePath = $this->testFilePath;
 | 
			
		||||
        $dirName = $basePath . DIRECTORY_SEPARATOR . $dirName;
 | 
			
		||||
        $expectedFiles = [
 | 
			
		||||
            $dirName . DIRECTORY_SEPARATOR . 'test_sub_dir',
 | 
			
		||||
            $dirName . DIRECTORY_SEPARATOR . 'second_sub_dir'
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        $foundFiles = FileHelper::findDirectory($dirName);
 | 
			
		||||
        sort($expectedFiles);
 | 
			
		||||
        sort($foundFiles);
 | 
			
		||||
        $this->assertEquals($expectedFiles, $foundFiles);
 | 
			
		||||
 | 
			
		||||
        $expectedFiles = [
 | 
			
		||||
            $dirName . DIRECTORY_SEPARATOR . 'second_sub_dir'
 | 
			
		||||
        ];
 | 
			
		||||
        $options = [
 | 
			
		||||
            'filter' => function ($path) {
 | 
			
		||||
                return 'second_sub_dir' == basename($path);
 | 
			
		||||
            },
 | 
			
		||||
        ];
 | 
			
		||||
        $foundFiles = FileHelper::findDirectory($dirName, $options);
 | 
			
		||||
        sort($expectedFiles);
 | 
			
		||||
        sort($foundFiles);
 | 
			
		||||
        $this->assertEquals($expectedFiles, $foundFiles);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user