PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/common/lib/Yii/utils/CFileHelper.php

https://bitbucket.org/haichau59/manga
PHP | 261 lines | 116 code | 11 blank | 134 comment | 28 complexity | e15b9f7e8239440b1b26dc084ae1a582 MD5 | raw file
  1. <?php
  2. /**
  3. * CFileHelper class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright Copyright &copy; 2008-2011 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CFileHelper provides a set of helper methods for common file system operations.
  12. *
  13. * @author Qiang Xue <qiang.xue@gmail.com>
  14. * @version $Id$
  15. * @package system.utils
  16. * @since 1.0
  17. */
  18. class CFileHelper
  19. {
  20. /**
  21. * Returns the extension name of a file path.
  22. * For example, the path "path/to/something.php" would return "php".
  23. * @param string $path the file path
  24. * @return string the extension name without the dot character.
  25. * @since 1.1.2
  26. */
  27. public static function getExtension($path)
  28. {
  29. return pathinfo($path, PATHINFO_EXTENSION);
  30. }
  31. /**
  32. * Copies a directory recursively as another.
  33. * If the destination directory does not exist, it will be created.
  34. * @param string $src the source directory
  35. * @param string $dst the destination directory
  36. * @param array $options options for directory copy. Valid options are:
  37. * <ul>
  38. * <li>fileTypes: array, list of file name suffix (without dot). Only files with these suffixes will be copied.</li>
  39. * <li>exclude: array, list of directory and file exclusions. Each exclusion can be either a name or a path.
  40. * If a file or directory name or path matches the exclusion, it will not be copied. For example, an exclusion of
  41. * '.svn' will exclude all files and directories whose name is '.svn'. And an exclusion of '/a/b' will exclude
  42. * file or directory '$src/a/b'. Note, that '/' should be used as separator regardless of the value of the DIRECTORY_SEPARATOR constant.
  43. * </li>
  44. * <li>level: integer, recursion depth, default=-1.
  45. * Level -1 means copying all directories and files under the directory;
  46. * Level 0 means copying only the files DIRECTLY under the directory;
  47. * level N means copying those directories that are within N levels.
  48. * </li>
  49. * </ul>
  50. */
  51. public static function copyDirectory($src,$dst,$options=array())
  52. {
  53. $fileTypes=array();
  54. $exclude=array();
  55. $level=-1;
  56. extract($options);
  57. self::copyDirectoryRecursive($src,$dst,'',$fileTypes,$exclude,$level,$options);
  58. }
  59. /**
  60. * Returns the files found under the specified directory and subdirectories.
  61. * @param string $dir the directory under which the files will be looked for
  62. * @param array $options options for file searching. Valid options are:
  63. * <ul>
  64. * <li>fileTypes: array, list of file name suffix (without dot). Only files with these suffixes will be returned.</li>
  65. * <li>exclude: array, list of directory and file exclusions. Each exclusion can be either a name or a path.
  66. * If a file or directory name or path matches the exclusion, it will not be copied. For example, an exclusion of
  67. * '.svn' will exclude all files and directories whose name is '.svn'. And an exclusion of '/a/b' will exclude
  68. * file or directory '$src/a/b'. Note, that '/' should be used as separator regardless of the value of the DIRECTORY_SEPARATOR constant.
  69. * </li>
  70. * <li>level: integer, recursion depth, default=-1.
  71. * Level -1 means searching for all directories and files under the directory;
  72. * Level 0 means searching for only the files DIRECTLY under the directory;
  73. * level N means searching for those directories that are within N levels.
  74. * </li>
  75. * </ul>
  76. * @return array files found under the directory. The file list is sorted.
  77. */
  78. public static function findFiles($dir,$options=array())
  79. {
  80. $fileTypes=array();
  81. $exclude=array();
  82. $level=-1;
  83. extract($options);
  84. $list=self::findFilesRecursive($dir,'',$fileTypes,$exclude,$level);
  85. sort($list);
  86. return $list;
  87. }
  88. /**
  89. * Copies a directory.
  90. * This method is mainly used by {@link copyDirectory}.
  91. * @param string $src the source directory
  92. * @param string $dst the destination directory
  93. * @param string $base the path relative to the original source directory
  94. * @param array $fileTypes list of file name suffix (without dot). Only files with these suffixes will be copied.
  95. * @param array $exclude list of directory and file exclusions. Each exclusion can be either a name or a path.
  96. * If a file or directory name or path matches the exclusion, it will not be copied. For example, an exclusion of
  97. * '.svn' will exclude all files and directories whose name is '.svn'. And an exclusion of '/a/b' will exclude
  98. * file or directory '$src/a/b'. Note, that '/' should be used as separator regardless of the value of the DIRECTORY_SEPARATOR constant.
  99. * @param integer $level recursion depth. It defaults to -1.
  100. * Level -1 means copying all directories and files under the directory;
  101. * Level 0 means copying only the files DIRECTLY under the directory;
  102. * level N means copying those directories that are within N levels.
  103. * @param array $options additional options. The following options are supported:
  104. * newDirMode - the permission to be set for newly copied directories (defaults to 0777);
  105. * newFileMode - the permission to be set for newly copied files (defaults to the current environment setting).
  106. */
  107. protected static function copyDirectoryRecursive($src,$dst,$base,$fileTypes,$exclude,$level,$options)
  108. {
  109. if(!is_dir($dst))
  110. mkdir($dst);
  111. if(isset($options['newDirMode']))
  112. @chmod($dst,$options['newDirMode']);
  113. else
  114. @chmod($dst,0777);
  115. $folder=opendir($src);
  116. while(($file=readdir($folder))!==false)
  117. {
  118. if($file==='.' || $file==='..')
  119. continue;
  120. $path=$src.DIRECTORY_SEPARATOR.$file;
  121. $isFile=is_file($path);
  122. if(self::validatePath($base,$file,$isFile,$fileTypes,$exclude))
  123. {
  124. if($isFile)
  125. {
  126. copy($path,$dst.DIRECTORY_SEPARATOR.$file);
  127. if(isset($options['newFileMode']))
  128. @chmod($dst.DIRECTORY_SEPARATOR.$file, $options['newFileMode']);
  129. }
  130. else if($level)
  131. self::copyDirectoryRecursive($path,$dst.DIRECTORY_SEPARATOR.$file,$base.'/'.$file,$fileTypes,$exclude,$level-1,$options);
  132. }
  133. }
  134. closedir($folder);
  135. }
  136. /**
  137. * Returns the files found under the specified directory and subdirectories.
  138. * This method is mainly used by {@link findFiles}.
  139. * @param string $dir the source directory
  140. * @param string $base the path relative to the original source directory
  141. * @param array $fileTypes list of file name suffix (without dot). Only files with these suffixes will be returned.
  142. * @param array $exclude list of directory and file exclusions. Each exclusion can be either a name or a path.
  143. * If a file or directory name or path matches the exclusion, it will not be copied. For example, an exclusion of
  144. * '.svn' will exclude all files and directories whose name is '.svn'. And an exclusion of '/a/b' will exclude
  145. * file or directory '$src/a/b'. Note, that '/' should be used as separator regardless of the value of the DIRECTORY_SEPARATOR constant.
  146. * @param integer $level recursion depth. It defaults to -1.
  147. * Level -1 means searching for all directories and files under the directory;
  148. * Level 0 means searching for only the files DIRECTLY under the directory;
  149. * level N means searching for those directories that are within N levels.
  150. * @return array files found under the directory.
  151. */
  152. protected static function findFilesRecursive($dir,$base,$fileTypes,$exclude,$level)
  153. {
  154. $list=array();
  155. $handle=opendir($dir);
  156. while(($file=readdir($handle))!==false)
  157. {
  158. if($file==='.' || $file==='..')
  159. continue;
  160. $path=$dir.DIRECTORY_SEPARATOR.$file;
  161. $isFile=is_file($path);
  162. if(self::validatePath($base,$file,$isFile,$fileTypes,$exclude))
  163. {
  164. if($isFile)
  165. $list[]=$path;
  166. else if($level)
  167. $list=array_merge($list,self::findFilesRecursive($path,$base.'/'.$file,$fileTypes,$exclude,$level-1));
  168. }
  169. }
  170. closedir($handle);
  171. return $list;
  172. }
  173. /**
  174. * Validates a file or directory.
  175. * @param string $base the path relative to the original source directory
  176. * @param string $file the file or directory name
  177. * @param boolean $isFile whether this is a file
  178. * @param array $fileTypes list of file name suffix (without dot). Only files with these suffixes will be copied.
  179. * @param array $exclude list of directory and file exclusions. Each exclusion can be either a name or a path.
  180. * If a file or directory name or path matches the exclusion, it will not be copied. For example, an exclusion of
  181. * '.svn' will exclude all files and directories whose name is '.svn'. And an exclusion of '/a/b' will exclude
  182. * file or directory '$src/a/b'. Note, that '/' should be used as separator regardless of the value of the DIRECTORY_SEPARATOR constant.
  183. * @return boolean whether the file or directory is valid
  184. */
  185. protected static function validatePath($base,$file,$isFile,$fileTypes,$exclude)
  186. {
  187. foreach($exclude as $e)
  188. {
  189. if($file===$e || strpos($base.'/'.$file,$e)===0)
  190. return false;
  191. }
  192. if(!$isFile || empty($fileTypes))
  193. return true;
  194. if(($type=pathinfo($file, PATHINFO_EXTENSION))!=='')
  195. return in_array($type,$fileTypes);
  196. else
  197. return false;
  198. }
  199. /**
  200. * Determines the MIME type of the specified file.
  201. * This method will attempt the following approaches in order:
  202. * <ol>
  203. * <li>finfo</li>
  204. * <li>mime_content_type</li>
  205. * <li>{@link getMimeTypeByExtension}, when $checkExtension is set true.</li>
  206. * </ol>
  207. * @param string $file the file name.
  208. * @param string $magicFile name of a magic database file, usually something like /path/to/magic.mime.
  209. * This will be passed as the second parameter to {@link http://php.net/manual/en/function.finfo-open.php finfo_open}.
  210. * This parameter has been available since version 1.1.3.
  211. * @param boolean $checkExtension whether to check the file extension in case the MIME type cannot be determined
  212. * based on finfo and mime_content_type. Defaults to true. This parameter has been available since version 1.1.4.
  213. * @return string the MIME type. Null is returned if the MIME type cannot be determined.
  214. */
  215. public static function getMimeType($file,$magicFile=null,$checkExtension=true)
  216. {
  217. if(function_exists('finfo_open'))
  218. {
  219. $options=defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME;
  220. $info=$magicFile===null ? finfo_open($options) : finfo_open($options,$magicFile);
  221. if($info && ($result=finfo_file($info,$file))!==false)
  222. return $result;
  223. }
  224. if(function_exists('mime_content_type') && ($result=mime_content_type($file))!==false)
  225. return $result;
  226. return $checkExtension ? self::getMimeTypeByExtension($file) : null;
  227. }
  228. /**
  229. * Determines the MIME type based on the extension name of the specified file.
  230. * This method will use a local map between extension name and MIME type.
  231. * @param string $file the file name.
  232. * @param string $magicFile the path of the file that contains all available MIME type information.
  233. * If this is not set, the default 'system.utils.mimeTypes' file will be used.
  234. * This parameter has been available since version 1.1.3.
  235. * @return string the MIME type. Null is returned if the MIME type cannot be determined.
  236. */
  237. public static function getMimeTypeByExtension($file,$magicFile=null)
  238. {
  239. static $extensions;
  240. if($extensions===null)
  241. $extensions=$magicFile===null ? require(Yii::getPathOfAlias('system.utils.mimeTypes').'.php') : $magicFile;
  242. if(($ext=pathinfo($file, PATHINFO_EXTENSION))!=='')
  243. {
  244. $ext=strtolower($ext);
  245. if(isset($extensions[$ext]))
  246. return $extensions[$ext];
  247. }
  248. return null;
  249. }
  250. }