|  |  |  | <?php
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Filesystem helper class file.
 | 
					
						
							|  |  |  |  *
 | 
					
						
							|  |  |  |  * @author Qiang Xue <qiang.xue@gmail.com>
 | 
					
						
							|  |  |  |  * @author Alex Makarov <sam@rmcreative.ru>
 | 
					
						
							|  |  |  |  * @link http://www.yiiframework.com/
 | 
					
						
							|  |  |  |  * @copyright Copyright © 2008-2012 Yii Software LLC
 | 
					
						
							|  |  |  |  * @license http://www.yiiframework.com/license/
 | 
					
						
							|  |  |  |  */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace yii\util;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Filesystem helper
 | 
					
						
							|  |  |  |  *
 | 
					
						
							|  |  |  |  * @since 2.0
 | 
					
						
							|  |  |  |  */
 | 
					
						
							|  |  |  | class File
 | 
					
						
							|  |  |  | {
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * Copies a list of files from one place to another.
 | 
					
						
							|  |  |  | 	 * @param array $fileList the list of files to be copied (name=>spec).
 | 
					
						
							|  |  |  | 	 * The array keys are names displayed during the copy process, and array values are specifications
 | 
					
						
							|  |  |  | 	 * for files to be copied. Each array value must be an array of the following structure:
 | 
					
						
							|  |  |  | 	 * <ul>
 | 
					
						
							|  |  |  | 	 * <li>source: required, the full path of the file/directory to be copied from</li>
 | 
					
						
							|  |  |  | 	 * <li>target: required, the full path of the file/directory to be copied to</li>
 | 
					
						
							|  |  |  | 	 * <li>callback: optional, the callback to be invoked when copying a file. The callback function
 | 
					
						
							|  |  |  | 	 *   should be declared as follows:
 | 
					
						
							|  |  |  | 	 *   <pre>
 | 
					
						
							|  |  |  | 	 *   function foo($source,$params)
 | 
					
						
							|  |  |  | 	 *   </pre>
 | 
					
						
							|  |  |  | 	 *   where $source parameter is the source file path, and the content returned
 | 
					
						
							|  |  |  | 	 *   by the function will be saved into the target file.</li>
 | 
					
						
							|  |  |  | 	 * <li>params: optional, the parameters to be passed to the callback</li>
 | 
					
						
							|  |  |  | 	 * </ul>
 | 
					
						
							|  |  |  | 	 * @see buildFileList
 | 
					
						
							|  |  |  | 	 */
 | 
					
						
							|  |  |  | 	public function copyFiles($fileList)
 | 
					
						
							|  |  |  | 	{
 | 
					
						
							|  |  |  | 		$overwriteAll=false;
 | 
					
						
							|  |  |  | 		foreach($fileList as $name=>$file)
 | 
					
						
							|  |  |  | 		{
 | 
					
						
							|  |  |  | 			$source=strtr($file['source'],'/\\',DIRECTORY_SEPARATOR);
 | 
					
						
							|  |  |  | 			$target=strtr($file['target'],'/\\',DIRECTORY_SEPARATOR);
 | 
					
						
							|  |  |  | 			$callback=isset($file['callback']) ? $file['callback'] : null;
 | 
					
						
							|  |  |  | 			$params=isset($file['params']) ? $file['params'] : null;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(is_dir($source))
 | 
					
						
							|  |  |  | 			{
 | 
					
						
							|  |  |  | 				$this->ensureDirectory($target);
 | 
					
						
							|  |  |  | 				continue;
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if($callback!==null)
 | 
					
						
							|  |  |  | 				$content=call_user_func($callback,$source,$params);
 | 
					
						
							|  |  |  | 			else
 | 
					
						
							|  |  |  | 				$content=file_get_contents($source);
 | 
					
						
							|  |  |  | 			if(is_file($target))
 | 
					
						
							|  |  |  | 			{
 | 
					
						
							|  |  |  | 				if($content===file_get_contents($target))
 | 
					
						
							|  |  |  | 				{
 | 
					
						
							|  |  |  | 					echo "  unchanged $name\n";
 | 
					
						
							|  |  |  | 					continue;
 | 
					
						
							|  |  |  | 				}
 | 
					
						
							|  |  |  | 				if($overwriteAll)
 | 
					
						
							|  |  |  | 					echo "  overwrite $name\n";
 | 
					
						
							|  |  |  | 				else
 | 
					
						
							|  |  |  | 				{
 | 
					
						
							|  |  |  | 					echo "      exist $name\n";
 | 
					
						
							|  |  |  | 					echo "            ...overwrite? [Yes|No|All|Quit] ";
 | 
					
						
							|  |  |  | 					$answer=trim(fgets(STDIN));
 | 
					
						
							|  |  |  | 					if(!strncasecmp($answer,'q',1))
 | 
					
						
							|  |  |  | 						return;
 | 
					
						
							|  |  |  | 					else if(!strncasecmp($answer,'y',1))
 | 
					
						
							|  |  |  | 						echo "  overwrite $name\n";
 | 
					
						
							|  |  |  | 					else if(!strncasecmp($answer,'a',1))
 | 
					
						
							|  |  |  | 					{
 | 
					
						
							|  |  |  | 						echo "  overwrite $name\n";
 | 
					
						
							|  |  |  | 						$overwriteAll=true;
 | 
					
						
							|  |  |  | 					} else
 | 
					
						
							|  |  |  | 					{
 | 
					
						
							|  |  |  | 						echo "       skip $name\n";
 | 
					
						
							|  |  |  | 						continue;
 | 
					
						
							|  |  |  | 					}
 | 
					
						
							|  |  |  | 				}
 | 
					
						
							|  |  |  | 			} else
 | 
					
						
							|  |  |  | 			{
 | 
					
						
							|  |  |  | 				$this->ensureDirectory(dirname($target));
 | 
					
						
							|  |  |  | 				echo "   generate $name\n";
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 			file_put_contents($target,$content);
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * Builds the file list of a directory.
 | 
					
						
							|  |  |  | 	 * This method traverses through the specified directory and builds
 | 
					
						
							|  |  |  | 	 * a list of files and subdirectories that the directory contains.
 | 
					
						
							|  |  |  | 	 * The result of this function can be passed to {@link copyFiles}.
 | 
					
						
							|  |  |  | 	 * @param string $sourceDir the source directory
 | 
					
						
							|  |  |  | 	 * @param string $targetDir the target directory
 | 
					
						
							|  |  |  | 	 * @param string $baseDir base directory
 | 
					
						
							|  |  |  | 	 * @return array the file list (see {@link copyFiles})
 | 
					
						
							|  |  |  | 	 */
 | 
					
						
							|  |  |  | 	public function buildFileList($sourceDir, $targetDir, $baseDir='')
 | 
					
						
							|  |  |  | 	{
 | 
					
						
							|  |  |  | 		$list=array();
 | 
					
						
							|  |  |  | 		$handle=opendir($sourceDir);
 | 
					
						
							|  |  |  | 		while(($file=readdir($handle))!==false)
 | 
					
						
							|  |  |  | 		{
 | 
					
						
							|  |  |  | 			if($file==='.' || $file==='..' || $file==='.svn' ||$file==='.yii')
 | 
					
						
							|  |  |  | 				continue;
 | 
					
						
							|  |  |  | 			$sourcePath=$sourceDir.DIRECTORY_SEPARATOR.$file;
 | 
					
						
							|  |  |  | 			$targetPath=$targetDir.DIRECTORY_SEPARATOR.$file;
 | 
					
						
							|  |  |  | 			$name=$baseDir===''?$file : $baseDir.'/'.$file;
 | 
					
						
							|  |  |  | 			$list[$name]=array('source'=>$sourcePath, 'target'=>$targetPath);
 | 
					
						
							|  |  |  | 			if(is_dir($sourcePath))
 | 
					
						
							|  |  |  | 				$list=array_merge($list,$this->buildFileList($sourcePath,$targetPath,$name));
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 		closedir($handle);
 | 
					
						
							|  |  |  | 		return $list;
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * Creates all parent directories if they do not exist.
 | 
					
						
							|  |  |  | 	 * @param string $directory the directory to be checked
 | 
					
						
							|  |  |  | 	 */
 | 
					
						
							|  |  |  | 	public function ensureDirectory($directory)
 | 
					
						
							|  |  |  | 	{
 | 
					
						
							|  |  |  | 		if(!is_dir($directory))
 | 
					
						
							|  |  |  | 		{
 | 
					
						
							|  |  |  | 			$this->ensureDirectory(dirname($directory));
 | 
					
						
							|  |  |  | 			echo "      mkdir ".strtr($directory,'\\','/')."\n";
 | 
					
						
							|  |  |  | 			mkdir($directory);
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 |