|  |  |  | @ -134,12 +134,21 @@ class FileHelper | 
			
		
	
		
			
				
					|  |  |  |  | 	 * | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - dirMode: integer, the permission to be set for newly copied directories. Defaults to 0777. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - fileMode:  integer, the permission to be set for newly copied files. Defaults to the current environment setting. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - beforeCopy: callback, a PHP callback that is called before copying each sub-directory or file. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   If the callback returns false, the copy operation for the sub-directory or file will be cancelled. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - filter: callback, a PHP callback that is called for each sub-directory or file. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   If the callback returns false, the the sub-directory or file will not be copied. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   The signature of the callback should be: `function ($path)`, where `$path` refers the full path to be copied. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - fileTypes: array, list of file name suffix (without dot). Only files with these suffixes will be copied. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - only: array, list of patterns that the files or directories should match if they want to be copied. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   A path matches a pattern if it contains the pattern string at its end. For example, | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   '/a/b' will match all files and directories ending with '/a/b'; and the '.svn' will match all files and | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   directories whose name ends with '.svn'. Note, the '/' characters in a pattern matches both '/' and '\'. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   If a file/directory matches both a name in "only" and "except", it will NOT be copied. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - except: array, list of patterns that the files or directories should NOT match if they want to be copied. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   For more details on how to specify the patterns, please refer to the "only" option. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - recursive: boolean, whether the files under the subdirectories should also be copied. Defaults to true. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - afterCopy: callback, a PHP callback that is called after each sub-directory or file is successfully copied. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   The signature of the callback should be: `function ($from, $to)`, where `$from` is the sub-directory or | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   file to be copied from, while `$to` is the copy target. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - afterCopy: callback, a PHP callback that is called after a sub-directory or file is successfully copied. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   The signature of the callback is similar to that of `beforeCopy`. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   file copied from, while `$to` is the copy target. | 
			
		
	
		
			
				
					|  |  |  |  | 	 */ | 
			
		
	
		
			
				
					|  |  |  |  | 	public static function copyDirectory($src, $dst, $options = array()) | 
			
		
	
		
			
				
					|  |  |  |  | 	{ | 
			
		
	
	
		
			
				
					|  |  |  | @ -154,7 +163,7 @@ class FileHelper | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			$from = $src . DIRECTORY_SEPARATOR . $file; | 
			
		
	
		
			
				
					|  |  |  |  | 			$to = $dst . DIRECTORY_SEPARATOR . $file; | 
			
		
	
		
			
				
					|  |  |  |  | 			if (!isset($options['beforeCopy']) || call_user_func($options['beforeCopy'], $from, $to)) { | 
			
		
	
		
			
				
					|  |  |  |  | 			if (static::filterPath($from, $options)) { | 
			
		
	
		
			
				
					|  |  |  |  | 				if (is_file($from)) { | 
			
		
	
		
			
				
					|  |  |  |  | 					copy($from, $to); | 
			
		
	
		
			
				
					|  |  |  |  | 					if (isset($options['fileMode'])) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -177,22 +186,23 @@ class FileHelper | 
			
		
	
		
			
				
					|  |  |  |  | 	 */ | 
			
		
	
		
			
				
					|  |  |  |  | 	public static function removeDirectory($dir) | 
			
		
	
		
			
				
					|  |  |  |  | 	{ | 
			
		
	
		
			
				
					|  |  |  |  | 		$items = glob($dir . DIRECTORY_SEPARATOR . '{,.}*', GLOB_MARK | GLOB_BRACE); | 
			
		
	
		
			
				
					|  |  |  |  | 		foreach ($items as $item) { | 
			
		
	
		
			
				
					|  |  |  |  | 			$itemBaseName = basename($item); | 
			
		
	
		
			
				
					|  |  |  |  | 			if ($itemBaseName === '.' || $itemBaseName === '..') { | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!is_dir($dir) || !($handle = opendir($dir))) { | 
			
		
	
		
			
				
					|  |  |  |  | 			return; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		while (($file = readdir($handle)) !== false) { | 
			
		
	
		
			
				
					|  |  |  |  | 			if ($file === '.' || $file === '..') { | 
			
		
	
		
			
				
					|  |  |  |  | 				continue; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			if (StringHelper::substr($item, -1, 1) == DIRECTORY_SEPARATOR) { | 
			
		
	
		
			
				
					|  |  |  |  | 				static::removeDirectory($item); | 
			
		
	
		
			
				
					|  |  |  |  | 			$path = $dir . DIRECTORY_SEPARATOR . $file; | 
			
		
	
		
			
				
					|  |  |  |  | 			if (is_file($path)) { | 
			
		
	
		
			
				
					|  |  |  |  | 				unlink($path); | 
			
		
	
		
			
				
					|  |  |  |  | 			} else { | 
			
		
	
		
			
				
					|  |  |  |  | 				unlink($item); | 
			
		
	
		
			
				
					|  |  |  |  | 				static::removeDirectory($path); | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		if (is_dir($dir)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		closedir($handle); | 
			
		
	
		
			
				
					|  |  |  |  | 		rmdir($dir); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	/** | 
			
		
	
		
			
				
					|  |  |  |  | 	 * Returns the files found under the specified directory and subdirectories. | 
			
		
	
	
		
			
				
					|  |  |  | @ -200,18 +210,17 @@ class FileHelper | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @param array $options options for file searching. Valid options are: | 
			
		
	
		
			
				
					|  |  |  |  | 	 * | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - filter: callback, a PHP callback that is called for each sub-directory or file. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   If the callback returns false, the the sub-directory or file will not be placed to the result set. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   The signature of the callback should be: `function ($base, $name, $isFile)`, where `$base` is the name of directory, | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   which contains file or sub-directory, `$name` file or sub-directory name, `$isFile` indicates if object is a file or a directory. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   If the callback returns false, the the sub-directory or file will be excluded from the returning result. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   The signature of the callback should be: `function ($path)`, where `$path` refers the full path to be filtered. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - fileTypes: array, list of file name suffix (without dot). Only files with these suffixes will be returned. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - only: array, list of path names that the files or directories should match if they want to be put in the result set. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   The matching is done in a partial manner. For example, the '.svn' will match all files and directories whose name ends with '.svn'. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   And the name '/a/b' will match all files and directories ending with '/a/b'. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   Note, that '/' should be used as separator regardless of the value of the DIRECTORY_SEPARATOR constant. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   If a file/directory matches both a name in "only" and "except", it will NOT be put in the result set. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - except: array, list of path names that the files or directories should NOT match if they want to be put in the result set. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - recursive: boolean, whether the files should be looked recursively under all subdirectories. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   Defaults to true. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - only: array, list of patterns that the files or directories should match if they want to be returned. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   A path matches a pattern if it contains the pattern string at its end. For example, | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   '/a/b' will match all files and directories ending with '/a/b'; and the '.svn' will match all files and | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   directories whose name ends with '.svn'. Note, the '/' characters in a pattern matches both '/' and '\'. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   If a file/directory matches both a name in "only" and "except", it will NOT be returned. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - except: array, list of patterns that the files or directories should NOT match if they want to be returned. | 
			
		
	
		
			
				
					|  |  |  |  | 	 *   For more details on how to specify the patterns, please refer to the "only" option. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * - recursive: boolean, whether the files under the subdirectories should also be lookied for. Defaults to true. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @return array files found under the directory. The file list is sorted. | 
			
		
	
		
			
				
					|  |  |  |  | 	 */ | 
			
		
	
		
			
				
					|  |  |  |  | 	public static function findFiles($dir, $options = array()) | 
			
		
	
	
		
			
				
					|  |  |  | @ -223,7 +232,7 @@ class FileHelper | 
			
		
	
		
			
				
					|  |  |  |  | 				continue; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			$path = $dir . DIRECTORY_SEPARATOR . $file; | 
			
		
	
		
			
				
					|  |  |  |  | 			if (static::validatePath($path, $options)) { | 
			
		
	
		
			
				
					|  |  |  |  | 			if (static::filterPath($path, $options)) { | 
			
		
	
		
			
				
					|  |  |  |  | 				if (is_file($path)) { | 
			
		
	
		
			
				
					|  |  |  |  | 					$list[] = $path; | 
			
		
	
		
			
				
					|  |  |  |  | 				} elseif (!isset($options['recursive']) || $options['recursive']) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -236,62 +245,61 @@ class FileHelper | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	/** | 
			
		
	
		
			
				
					|  |  |  |  | 	 * Validates a file or directory, checking if it match given conditions. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @param string $path the path of the file or directory to be validated | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @param array $options options for file searching. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @return boolean whether the file or directory is valid | 
			
		
	
		
			
				
					|  |  |  |  | 	 * Checks if the given file path satisfies the filtering options. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @param string $path the path of the file or directory to be checked | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @param array $options the filtering options. See [[findFiles()]] for explanations of | 
			
		
	
		
			
				
					|  |  |  |  | 	 * the supported options. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @return boolean whether the file or directory satisfies the filtering options. | 
			
		
	
		
			
				
					|  |  |  |  | 	 */ | 
			
		
	
		
			
				
					|  |  |  |  | 	protected static function validatePath($path, $options) | 
			
		
	
		
			
				
					|  |  |  |  | 	protected static function filterPath($path, $options) | 
			
		
	
		
			
				
					|  |  |  |  | 	{ | 
			
		
	
		
			
				
					|  |  |  |  | 		if (isset($options['filter']) && !call_user_func($options['filter'], $path)) { | 
			
		
	
		
			
				
					|  |  |  |  | 			return false; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		$path = str_replace('\\', '/', $path); | 
			
		
	
		
			
				
					|  |  |  |  | 		$n = strlen($path); | 
			
		
	
		
			
				
					|  |  |  |  | 		$n = StringHelper::strlen($path); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!empty($options['except'])) { | 
			
		
	
		
			
				
					|  |  |  |  | 			foreach ($options['except'] as $name) { | 
			
		
	
		
			
				
					|  |  |  |  | 				if (strrpos($path, $name) === $n - strlen($name)) { | 
			
		
	
		
			
				
					|  |  |  |  | 				if (StringHelper::substr($path, -StringHelper::strlen($name), $n) === $name) { | 
			
		
	
		
			
				
					|  |  |  |  | 					return false; | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!empty($options['only'])) { | 
			
		
	
		
			
				
					|  |  |  |  | 			foreach ($options['only'] as $name) { | 
			
		
	
		
			
				
					|  |  |  |  | 				if (strrpos($path, $name) !== $n - strlen($name)) { | 
			
		
	
		
			
				
					|  |  |  |  | 				if (StringHelper::substr($path, -StringHelper::strlen($name), $n) !== $name) { | 
			
		
	
		
			
				
					|  |  |  |  | 					return false; | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!empty($options['fileTypes'])) { | 
			
		
	
		
			
				
					|  |  |  |  | 			if (!is_file($path)) { | 
			
		
	
		
			
				
					|  |  |  |  | 				return true; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			if (($type = pathinfo($path, PATHINFO_EXTENSION)) !== '') { | 
			
		
	
		
			
				
					|  |  |  |  | 				return in_array($type, $options['fileTypes']); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!empty($options['fileTypes']) && is_file($path)) { | 
			
		
	
		
			
				
					|  |  |  |  | 			return in_array(pathinfo($path, PATHINFO_EXTENSION), $options['fileTypes']); | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { | 
			
		
	
		
			
				
					|  |  |  |  | 				return false; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 			return true; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	/** | 
			
		
	
		
			
				
					|  |  |  |  | 	 * Shared environment safe version of mkdir. Supports recursive creation. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * For avoidance of umask side-effects chmod is used. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * Makes directory. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * | 
			
		
	
		
			
				
					|  |  |  |  | 	 * This method is similar to the PHP `mkdir()` function except that | 
			
		
	
		
			
				
					|  |  |  |  | 	 * it uses `chmod()` to set the permission of the created directory | 
			
		
	
		
			
				
					|  |  |  |  | 	 * in order to avoid the impact of the `umask` setting. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @param string $path path to be created. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @param integer $mode  the permission to be set for created directory. If not set  0777 will be used. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @param boolean $recursive whether to create directory structure recursive if parent dirs do not exist. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @return boolean result of mkdir. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @see mkdir | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @param integer $mode the permission to be set for created directory. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @param boolean $recursive whether to create parent directories if they do not exist. | 
			
		
	
		
			
				
					|  |  |  |  | 	 * @return boolean whether the directory is created successfully | 
			
		
	
		
			
				
					|  |  |  |  | 	 */ | 
			
		
	
		
			
				
					|  |  |  |  | 	public static function mkdir($path, $mode = null, $recursive = false) | 
			
		
	
		
			
				
					|  |  |  |  | 	public static function mkdir($path, $mode = 0777, $recursive = true) | 
			
		
	
		
			
				
					|  |  |  |  | 	{ | 
			
		
	
		
			
				
					|  |  |  |  | 		$prevDir = dirname($path); | 
			
		
	
		
			
				
					|  |  |  |  | 		if ($recursive && !is_dir($path) && !is_dir($prevDir)) { | 
			
		
	
		
			
				
					|  |  |  |  | 			static::mkdir(dirname($path), $mode, true); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (is_dir($path)) { | 
			
		
	
		
			
				
					|  |  |  |  | 			return true; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		$parentDir = dirname($path); | 
			
		
	
		
			
				
					|  |  |  |  | 		if ($recursive && !is_dir($parentDir)) { | 
			
		
	
		
			
				
					|  |  |  |  | 			static::mkdir($parentDir, $mode, true); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		$mode = isset($mode) ? $mode : 0777; | 
			
		
	
		
			
				
					|  |  |  |  | 		$result = mkdir($path, $mode); | 
			
		
	
		
			
				
					|  |  |  |  | 		chmod($path, $mode); | 
			
		
	
		
			
				
					|  |  |  |  | 		return $result; | 
			
		
	
	
		
			
				
					|  |  |  | 
 |