Added new (clean) yii boilerplate
This commit is contained in:
350
framework/utils/CDateTimeParser.php
Normal file
350
framework/utils/CDateTimeParser.php
Normal file
@@ -0,0 +1,350 @@
|
||||
<?php
|
||||
/**
|
||||
* CDateTimeParser class file
|
||||
*
|
||||
* @author Wei Zhuo <weizhuo[at]gamil[dot]com>
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @author Tomasz Suchanek <tomasz[dot]suchanek[at]gmail[dot]com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright 2008-2013 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
/**
|
||||
* CDateTimeParser converts a date/time string to a UNIX timestamp according to the specified pattern.
|
||||
*
|
||||
* The following pattern characters are recognized:
|
||||
* <pre>
|
||||
* Pattern | Description
|
||||
* ----------------------------------------------------
|
||||
* d | Day of month 1 to 31, no padding
|
||||
* dd | Day of month 01 to 31, zero leading
|
||||
* M | Month digit 1 to 12, no padding
|
||||
* MM | Month digit 01 to 12, zero leading
|
||||
* MMM | Abbreviation representation of month (available since 1.1.11; locale aware since 1.1.13)
|
||||
* MMMM | Full name representation (available since 1.1.13; locale aware)
|
||||
* yy | 2 year digit, e.g., 96, 05
|
||||
* yyyy | 4 year digit, e.g., 2005
|
||||
* h | Hour in 0 to 23, no padding
|
||||
* hh | Hour in 00 to 23, zero leading
|
||||
* H | Hour in 0 to 23, no padding
|
||||
* HH | Hour in 00 to 23, zero leading
|
||||
* m | Minutes in 0 to 59, no padding
|
||||
* mm | Minutes in 00 to 59, zero leading
|
||||
* s | Seconds in 0 to 59, no padding
|
||||
* ss | Seconds in 00 to 59, zero leading
|
||||
* a | AM or PM, case-insensitive (since version 1.1.5)
|
||||
* ? | matches any character (wildcard) (since version 1.1.11)
|
||||
* ----------------------------------------------------
|
||||
* </pre>
|
||||
* All other characters must appear in the date string at the corresponding positions.
|
||||
*
|
||||
* For example, to parse a date string '21/10/2008', use the following:
|
||||
* <pre>
|
||||
* $timestamp=CDateTimeParser::parse('21/10/2008','dd/MM/yyyy');
|
||||
* </pre>
|
||||
*
|
||||
* Locale specific patterns such as MMM and MMMM uses {@link CLocale} for retrieving needed information.
|
||||
*
|
||||
* To format a timestamp to a date string, please use {@link CDateFormatter}.
|
||||
*
|
||||
* @author Wei Zhuo <weizhuo[at]gmail[dot]com>
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @package system.utils
|
||||
* @since 1.0
|
||||
*/
|
||||
class CDateTimeParser
|
||||
{
|
||||
/**
|
||||
* @var boolean whether 'mbstring' PHP extension available. This static property introduced for
|
||||
* the better overall performance of the class functionality. Checking 'mbstring' availability
|
||||
* through static property with predefined status value is much faster than direct calling
|
||||
* of function_exists('...').
|
||||
* Intended for internal use only.
|
||||
* @since 1.1.13
|
||||
*/
|
||||
private static $_mbstringAvailable;
|
||||
|
||||
/**
|
||||
* Converts a date string to a timestamp.
|
||||
* @param string $value the date string to be parsed
|
||||
* @param string $pattern the pattern that the date string is following
|
||||
* @param array $defaults the default values for year, month, day, hour, minute and second.
|
||||
* The default values will be used in case when the pattern doesn't specify the
|
||||
* corresponding fields. For example, if the pattern is 'MM/dd/yyyy' and this
|
||||
* parameter is array('minute'=>0, 'second'=>0), then the actual minute and second
|
||||
* for the parsing result will take value 0, while the actual hour value will be
|
||||
* the current hour obtained by date('H'). This parameter has been available since version 1.1.5.
|
||||
* @return integer timestamp for the date string. False if parsing fails.
|
||||
*/
|
||||
public static function parse($value,$pattern='MM/dd/yyyy',$defaults=array())
|
||||
{
|
||||
if(self::$_mbstringAvailable===null)
|
||||
self::$_mbstringAvailable=extension_loaded('mbstring');
|
||||
|
||||
$tokens=self::tokenize($pattern);
|
||||
$i=0;
|
||||
$n=self::$_mbstringAvailable ? mb_strlen($value,Yii::app()->charset) : strlen($value);
|
||||
foreach($tokens as $token)
|
||||
{
|
||||
switch($token)
|
||||
{
|
||||
case 'yyyy':
|
||||
{
|
||||
if(($year=self::parseInteger($value,$i,4,4))===false)
|
||||
return false;
|
||||
$i+=4;
|
||||
break;
|
||||
}
|
||||
case 'yy':
|
||||
{
|
||||
if(($year=self::parseInteger($value,$i,1,2))===false)
|
||||
return false;
|
||||
$i+=strlen($year);
|
||||
break;
|
||||
}
|
||||
case 'MMMM':
|
||||
{
|
||||
$monthName='';
|
||||
if(($month=self::parseMonth($value,$i,'wide',$monthName))===false)
|
||||
return false;
|
||||
$i+=self::$_mbstringAvailable ? mb_strlen($monthName,Yii::app()->charset) : strlen($monthName);
|
||||
break;
|
||||
}
|
||||
case 'MMM':
|
||||
{
|
||||
$monthName='';
|
||||
if(($month=self::parseMonth($value,$i,'abbreviated',$monthName))===false)
|
||||
return false;
|
||||
$i+=self::$_mbstringAvailable ? mb_strlen($monthName,Yii::app()->charset) : strlen($monthName);
|
||||
break;
|
||||
}
|
||||
case 'MM':
|
||||
{
|
||||
if(($month=self::parseInteger($value,$i,2,2))===false)
|
||||
return false;
|
||||
$i+=2;
|
||||
break;
|
||||
}
|
||||
case 'M':
|
||||
{
|
||||
if(($month=self::parseInteger($value,$i,1,2))===false)
|
||||
return false;
|
||||
$i+=strlen($month);
|
||||
break;
|
||||
}
|
||||
case 'dd':
|
||||
{
|
||||
if(($day=self::parseInteger($value,$i,2,2))===false)
|
||||
return false;
|
||||
$i+=2;
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
{
|
||||
if(($day=self::parseInteger($value,$i,1,2))===false)
|
||||
return false;
|
||||
$i+=strlen($day);
|
||||
break;
|
||||
}
|
||||
case 'h':
|
||||
case 'H':
|
||||
{
|
||||
if(($hour=self::parseInteger($value,$i,1,2))===false)
|
||||
return false;
|
||||
$i+=strlen($hour);
|
||||
break;
|
||||
}
|
||||
case 'hh':
|
||||
case 'HH':
|
||||
{
|
||||
if(($hour=self::parseInteger($value,$i,2,2))===false)
|
||||
return false;
|
||||
$i+=2;
|
||||
break;
|
||||
}
|
||||
case 'm':
|
||||
{
|
||||
if(($minute=self::parseInteger($value,$i,1,2))===false)
|
||||
return false;
|
||||
$i+=strlen($minute);
|
||||
break;
|
||||
}
|
||||
case 'mm':
|
||||
{
|
||||
if(($minute=self::parseInteger($value,$i,2,2))===false)
|
||||
return false;
|
||||
$i+=2;
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
{
|
||||
if(($second=self::parseInteger($value,$i,1,2))===false)
|
||||
return false;
|
||||
$i+=strlen($second);
|
||||
break;
|
||||
}
|
||||
case 'ss':
|
||||
{
|
||||
if(($second=self::parseInteger($value,$i,2,2))===false)
|
||||
return false;
|
||||
$i+=2;
|
||||
break;
|
||||
}
|
||||
case 'a':
|
||||
{
|
||||
if(($ampm=self::parseAmPm($value,$i))===false)
|
||||
return false;
|
||||
if(isset($hour))
|
||||
{
|
||||
if($hour==12 && $ampm==='am')
|
||||
$hour=0;
|
||||
elseif($hour<12 && $ampm==='pm')
|
||||
$hour+=12;
|
||||
}
|
||||
$i+=2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
$tn=self::$_mbstringAvailable ? mb_strlen($token,Yii::app()->charset) : strlen($token);
|
||||
if($i>=$n || ($token{0}!='?' && (self::$_mbstringAvailable ? mb_substr($value,$i,$tn,Yii::app()->charset) : substr($value,$i,$tn))!==$token))
|
||||
return false;
|
||||
$i+=$tn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if($i<$n)
|
||||
return false;
|
||||
|
||||
if(!isset($year))
|
||||
$year=isset($defaults['year']) ? $defaults['year'] : date('Y');
|
||||
if(!isset($month))
|
||||
$month=isset($defaults['month']) ? $defaults['month'] : date('n');
|
||||
if(!isset($day))
|
||||
$day=isset($defaults['day']) ? $defaults['day'] : date('j');
|
||||
|
||||
if(strlen($year)===2)
|
||||
{
|
||||
if($year>=70)
|
||||
$year+=1900;
|
||||
else
|
||||
$year+=2000;
|
||||
}
|
||||
$year=(int)$year;
|
||||
$month=(int)$month;
|
||||
$day=(int)$day;
|
||||
|
||||
if(
|
||||
!isset($hour) && !isset($minute) && !isset($second)
|
||||
&& !isset($defaults['hour']) && !isset($defaults['minute']) && !isset($defaults['second'])
|
||||
)
|
||||
$hour=$minute=$second=0;
|
||||
else
|
||||
{
|
||||
if(!isset($hour))
|
||||
$hour=isset($defaults['hour']) ? $defaults['hour'] : date('H');
|
||||
if(!isset($minute))
|
||||
$minute=isset($defaults['minute']) ? $defaults['minute'] : date('i');
|
||||
if(!isset($second))
|
||||
$second=isset($defaults['second']) ? $defaults['second'] : date('s');
|
||||
$hour=(int)$hour;
|
||||
$minute=(int)$minute;
|
||||
$second=(int)$second;
|
||||
}
|
||||
|
||||
if(CTimestamp::isValidDate($year,$month,$day) && CTimestamp::isValidTime($hour,$minute,$second))
|
||||
return CTimestamp::getTimestamp($hour,$minute,$second,$month,$day,$year);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param string $pattern the pattern that the date string is following
|
||||
*/
|
||||
private static function tokenize($pattern)
|
||||
{
|
||||
if(!($n=self::$_mbstringAvailable ? mb_strlen($pattern,Yii::app()->charset) : strlen($pattern)))
|
||||
return array();
|
||||
$tokens=array();
|
||||
$c0=self::$_mbstringAvailable ? mb_substr($pattern,0,1,Yii::app()->charset) : substr($pattern,0,1);
|
||||
|
||||
for($start=0,$i=1;$i<$n;++$i)
|
||||
{
|
||||
$c=self::$_mbstringAvailable ? mb_substr($pattern,$i,1,Yii::app()->charset) : substr($pattern,$i,1);
|
||||
if($c!==$c0)
|
||||
{
|
||||
$tokens[]=self::$_mbstringAvailable ? mb_substr($pattern,$start,$i-$start,Yii::app()->charset) : substr($pattern,$start,$i-$start);
|
||||
$c0=$c;
|
||||
$start=$i;
|
||||
}
|
||||
}
|
||||
$tokens[]=self::$_mbstringAvailable ? mb_substr($pattern,$start,$n-$start,Yii::app()->charset) : substr($pattern,$start,$n-$start);
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value the date string to be parsed
|
||||
* @param integer $offset starting offset
|
||||
* @param integer $minLength minimum length
|
||||
* @param integer $maxLength maximum length
|
||||
* @return string parsed integer value
|
||||
*/
|
||||
protected static function parseInteger($value,$offset,$minLength,$maxLength)
|
||||
{
|
||||
for($len=$maxLength;$len>=$minLength;--$len)
|
||||
{
|
||||
$v=self::$_mbstringAvailable ? mb_substr($value,$offset,$len,Yii::app()->charset) : substr($value,$offset,$len);
|
||||
if(ctype_digit($v) && (self::$_mbstringAvailable ? mb_strlen($v,Yii::app()->charset) : strlen($v))>=$minLength)
|
||||
return $v;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value the date string to be parsed
|
||||
* @param integer $offset starting offset
|
||||
* @return string parsed day period value
|
||||
*/
|
||||
protected static function parseAmPm($value, $offset)
|
||||
{
|
||||
$v=strtolower(self::$_mbstringAvailable ? mb_substr($value,$offset,2,Yii::app()->charset) : substr($value,$offset,2));
|
||||
return $v==='am' || $v==='pm' ? $v : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value the date string to be parsed.
|
||||
* @param integer $offset starting offset.
|
||||
* @param string $width month name width. It can be 'wide', 'abbreviated' or 'narrow'.
|
||||
* @param string $monthName extracted month name. Passed by reference.
|
||||
* @return string parsed month name.
|
||||
* @since 1.1.13
|
||||
*/
|
||||
protected static function parseMonth($value,$offset,$width,&$monthName)
|
||||
{
|
||||
$valueLength=self::$_mbstringAvailable ? mb_strlen($value,Yii::app()->charset) : strlen($value);
|
||||
for($len=1; $offset+$len<=$valueLength; $len++)
|
||||
{
|
||||
$monthName=self::$_mbstringAvailable ? mb_substr($value,$offset,$len,Yii::app()->charset) : substr($value,$offset,$len);
|
||||
if(!preg_match('/^[\p{L}\p{M}]+$/u',$monthName)) // unicode aware replacement for ctype_alpha($monthName)
|
||||
{
|
||||
$monthName=self::$_mbstringAvailable ? mb_substr($monthName,0,-1,Yii::app()->charset) : substr($monthName,0,-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$monthName=self::$_mbstringAvailable ? mb_strtolower($monthName,Yii::app()->charset) : strtolower($monthName);
|
||||
|
||||
$monthNames=Yii::app()->getLocale()->getMonthNames($width,false);
|
||||
foreach($monthNames as $k=>$v)
|
||||
$monthNames[$k]=rtrim(self::$_mbstringAvailable ? mb_strtolower($v,Yii::app()->charset) : strtolower($v),'.');
|
||||
|
||||
$monthNamesStandAlone=Yii::app()->getLocale()->getMonthNames($width,true);
|
||||
foreach($monthNamesStandAlone as $k=>$v)
|
||||
$monthNamesStandAlone[$k]=rtrim(self::$_mbstringAvailable ? mb_strtolower($v,Yii::app()->charset) : strtolower($v),'.');
|
||||
|
||||
if(($v=array_search($monthName,$monthNames))===false && ($v=array_search($monthName,$monthNamesStandAlone))===false)
|
||||
return false;
|
||||
return $v;
|
||||
}
|
||||
}
|
||||
311
framework/utils/CFileHelper.php
Normal file
311
framework/utils/CFileHelper.php
Normal file
@@ -0,0 +1,311 @@
|
||||
<?php
|
||||
/**
|
||||
* CFileHelper class file.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright 2008-2013 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
/**
|
||||
* CFileHelper provides a set of helper methods for common file system operations.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @package system.utils
|
||||
* @since 1.0
|
||||
*/
|
||||
class CFileHelper
|
||||
{
|
||||
/**
|
||||
* Returns the extension name of a file path.
|
||||
* For example, the path "path/to/something.php" would return "php".
|
||||
* @param string $path the file path
|
||||
* @return string the extension name without the dot character.
|
||||
* @since 1.1.2
|
||||
*/
|
||||
public static function getExtension($path)
|
||||
{
|
||||
return pathinfo($path,PATHINFO_EXTENSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a directory recursively as another.
|
||||
* If the destination directory does not exist, it will be created recursively.
|
||||
* @param string $src the source directory
|
||||
* @param string $dst the destination directory
|
||||
* @param array $options options for directory copy. Valid options are:
|
||||
* <ul>
|
||||
* <li>fileTypes: array, list of file name suffix (without dot). Only files with these suffixes will be copied.</li>
|
||||
* <li>exclude: array, list of directory and file exclusions. Each exclusion can be either a name or a path.
|
||||
* If a file or directory name or path matches the exclusion, it will not be copied. For example, an exclusion of
|
||||
* '.svn' will exclude all files and directories whose name is '.svn'. And an exclusion of '/a/b' will exclude
|
||||
* file or directory '$src/a/b'. Note, that '/' should be used as separator regardless of the value of the DIRECTORY_SEPARATOR constant.
|
||||
* </li>
|
||||
* <li>level: integer, recursion depth, default=-1.
|
||||
* Level -1 means copying all directories and files under the directory;
|
||||
* Level 0 means copying only the files DIRECTLY under the directory;
|
||||
* level N means copying those directories that are within N levels.
|
||||
* </li>
|
||||
* <li>newDirMode - the permission to be set for newly copied directories (defaults to 0777);</li>
|
||||
* <li>newFileMode - the permission to be set for newly copied files (defaults to the current environment setting).</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static function copyDirectory($src,$dst,$options=array())
|
||||
{
|
||||
$fileTypes=array();
|
||||
$exclude=array();
|
||||
$level=-1;
|
||||
extract($options);
|
||||
if(!is_dir($dst))
|
||||
self::mkdir($dst,$options,true);
|
||||
|
||||
self::copyDirectoryRecursive($src,$dst,'',$fileTypes,$exclude,$level,$options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a directory recursively.
|
||||
* @param string $directory to be deleted recursively.
|
||||
* @since 1.1.14
|
||||
*/
|
||||
public static function removeDirectory($directory)
|
||||
{
|
||||
$items=glob($directory.DIRECTORY_SEPARATOR.'{,.}*',GLOB_MARK | GLOB_BRACE);
|
||||
foreach($items as $item)
|
||||
{
|
||||
if(basename($item)=='.' || basename($item)=='..')
|
||||
continue;
|
||||
if(substr($item,-1)==DIRECTORY_SEPARATOR)
|
||||
self::removeDirectory($item);
|
||||
else
|
||||
unlink($item);
|
||||
}
|
||||
if(is_dir($directory))
|
||||
rmdir($directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the files 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 file searching. Valid options are:
|
||||
* <ul>
|
||||
* <li>fileTypes: array, list of file name suffix (without dot). Only files with these suffixes will be returned.</li>
|
||||
* <li>exclude: array, list of directory and file exclusions. Each exclusion can be either a name or a path.
|
||||
* If a file or directory name or path matches the exclusion, it will not be copied. For example, an exclusion of
|
||||
* '.svn' will exclude all files and directories whose name is '.svn'. And an exclusion of '/a/b' will exclude
|
||||
* file or directory '$src/a/b'. Note, that '/' should be used as separator regardless of the value of the DIRECTORY_SEPARATOR constant.
|
||||
* </li>
|
||||
* <li>level: integer, recursion depth, default=-1.
|
||||
* Level -1 means searching for all directories and files under the directory;
|
||||
* Level 0 means searching for only the files DIRECTLY under the directory;
|
||||
* level N means searching for those directories that are within N levels.
|
||||
* </li>
|
||||
* </ul>
|
||||
* @return array files found under the directory. The file list is sorted.
|
||||
*/
|
||||
public static function findFiles($dir,$options=array())
|
||||
{
|
||||
$fileTypes=array();
|
||||
$exclude=array();
|
||||
$level=-1;
|
||||
extract($options);
|
||||
$list=self::findFilesRecursive($dir,'',$fileTypes,$exclude,$level);
|
||||
sort($list);
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a directory.
|
||||
* This method is mainly used by {@link copyDirectory}.
|
||||
* @param string $src the source directory
|
||||
* @param string $dst the destination directory
|
||||
* @param string $base the path relative to the original source directory
|
||||
* @param array $fileTypes list of file name suffix (without dot). Only files with these suffixes will be copied.
|
||||
* @param array $exclude list of directory and file exclusions. Each exclusion can be either a name or a path.
|
||||
* If a file or directory name or path matches the exclusion, it will not be copied. For example, an exclusion of
|
||||
* '.svn' will exclude all files and directories whose name is '.svn'. And an exclusion of '/a/b' will exclude
|
||||
* file or directory '$src/a/b'. Note, that '/' should be used as separator regardless of the value of the DIRECTORY_SEPARATOR constant.
|
||||
* @param integer $level recursion depth. It defaults to -1.
|
||||
* Level -1 means copying all directories and files under the directory;
|
||||
* Level 0 means copying only the files DIRECTLY under the directory;
|
||||
* level N means copying those directories that are within N levels.
|
||||
* @param array $options additional options. The following options are supported:
|
||||
* newDirMode - the permission to be set for newly copied directories (defaults to 0777);
|
||||
* newFileMode - the permission to be set for newly copied files (defaults to the current environment setting).
|
||||
*/
|
||||
protected static function copyDirectoryRecursive($src,$dst,$base,$fileTypes,$exclude,$level,$options)
|
||||
{
|
||||
if(!is_dir($dst))
|
||||
self::mkdir($dst,$options,false);
|
||||
|
||||
$folder=opendir($src);
|
||||
while(($file=readdir($folder))!==false)
|
||||
{
|
||||
if($file==='.' || $file==='..')
|
||||
continue;
|
||||
$path=$src.DIRECTORY_SEPARATOR.$file;
|
||||
$isFile=is_file($path);
|
||||
if(self::validatePath($base,$file,$isFile,$fileTypes,$exclude))
|
||||
{
|
||||
if($isFile)
|
||||
{
|
||||
copy($path,$dst.DIRECTORY_SEPARATOR.$file);
|
||||
if(isset($options['newFileMode']))
|
||||
@chmod($dst.DIRECTORY_SEPARATOR.$file,$options['newFileMode']);
|
||||
}
|
||||
elseif($level)
|
||||
self::copyDirectoryRecursive($path,$dst.DIRECTORY_SEPARATOR.$file,$base.'/'.$file,$fileTypes,$exclude,$level-1,$options);
|
||||
}
|
||||
}
|
||||
closedir($folder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the files found under the specified directory and subdirectories.
|
||||
* This method is mainly used by {@link findFiles}.
|
||||
* @param string $dir the source directory
|
||||
* @param string $base the path relative to the original source directory
|
||||
* @param array $fileTypes list of file name suffix (without dot). Only files with these suffixes will be returned.
|
||||
* @param array $exclude list of directory and file exclusions. Each exclusion can be either a name or a path.
|
||||
* If a file or directory name or path matches the exclusion, it will not be copied. For example, an exclusion of
|
||||
* '.svn' will exclude all files and directories whose name is '.svn'. And an exclusion of '/a/b' will exclude
|
||||
* file or directory '$src/a/b'. Note, that '/' should be used as separator regardless of the value of the DIRECTORY_SEPARATOR constant.
|
||||
* @param integer $level recursion depth. It defaults to -1.
|
||||
* Level -1 means searching for all directories and files under the directory;
|
||||
* Level 0 means searching for only the files DIRECTLY under the directory;
|
||||
* level N means searching for those directories that are within N levels.
|
||||
* @return array files found under the directory.
|
||||
*/
|
||||
protected static function findFilesRecursive($dir,$base,$fileTypes,$exclude,$level)
|
||||
{
|
||||
$list=array();
|
||||
$handle=opendir($dir);
|
||||
while(($file=readdir($handle))!==false)
|
||||
{
|
||||
if($file==='.' || $file==='..')
|
||||
continue;
|
||||
$path=$dir.DIRECTORY_SEPARATOR.$file;
|
||||
$isFile=is_file($path);
|
||||
if(self::validatePath($base,$file,$isFile,$fileTypes,$exclude))
|
||||
{
|
||||
if($isFile)
|
||||
$list[]=$path;
|
||||
elseif($level)
|
||||
$list=array_merge($list,self::findFilesRecursive($path,$base.'/'.$file,$fileTypes,$exclude,$level-1));
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a file or directory.
|
||||
* @param string $base the path relative to the original source directory
|
||||
* @param string $file the file or directory name
|
||||
* @param boolean $isFile whether this is a file
|
||||
* @param array $fileTypes list of valid file name suffixes (without dot).
|
||||
* @param array $exclude list of directory and file exclusions. Each exclusion can be either a name or a path.
|
||||
* If a file or directory name or path matches the exclusion, false will be returned. For example, an exclusion of
|
||||
* '.svn' will return false for all files and directories whose name is '.svn'. And an exclusion of '/a/b' will return false for
|
||||
* file or directory '$src/a/b'. Note, that '/' should be used as separator regardless of the value of the DIRECTORY_SEPARATOR constant.
|
||||
* @return boolean whether the file or directory is valid
|
||||
*/
|
||||
protected static function validatePath($base,$file,$isFile,$fileTypes,$exclude)
|
||||
{
|
||||
foreach($exclude as $e)
|
||||
{
|
||||
if($file===$e || strpos($base.'/'.$file,$e)===0)
|
||||
return false;
|
||||
}
|
||||
if(!$isFile || empty($fileTypes))
|
||||
return true;
|
||||
if(($type=pathinfo($file,PATHINFO_EXTENSION))!=='')
|
||||
return in_array($type,$fileTypes);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the MIME type of the specified file.
|
||||
* This method will attempt the following approaches in order:
|
||||
* <ol>
|
||||
* <li>finfo</li>
|
||||
* <li>mime_content_type</li>
|
||||
* <li>{@link getMimeTypeByExtension}, when $checkExtension is set true.</li>
|
||||
* </ol>
|
||||
* @param string $file the file name.
|
||||
* @param string $magicFile name of a magic database file, usually something like /path/to/magic.mime.
|
||||
* This will be passed as the second parameter to {@link http://php.net/manual/en/function.finfo-open.php finfo_open}.
|
||||
* Magic file format described in {@link http://linux.die.net/man/5/magic man 5 magic}, note that this file does not
|
||||
* contain a standard PHP array as you might suppose. Specified magic file will be used only when fileinfo
|
||||
* PHP extension is available. This parameter has been available since version 1.1.3.
|
||||
* @param boolean $checkExtension whether to check the file extension in case the MIME type cannot be determined
|
||||
* based on finfo and mime_content_type. Defaults to true. This parameter has been available since version 1.1.4.
|
||||
* @return string the MIME type. Null is returned if the MIME type cannot be determined.
|
||||
*/
|
||||
public static function getMimeType($file,$magicFile=null,$checkExtension=true)
|
||||
{
|
||||
if(function_exists('finfo_open'))
|
||||
{
|
||||
$options=defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME;
|
||||
$info=$magicFile===null ? finfo_open($options) : finfo_open($options,$magicFile);
|
||||
|
||||
if($info && ($result=finfo_file($info,$file))!==false)
|
||||
return $result;
|
||||
}
|
||||
|
||||
if(function_exists('mime_content_type') && ($result=mime_content_type($file))!==false)
|
||||
return $result;
|
||||
|
||||
return $checkExtension ? self::getMimeTypeByExtension($file) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the MIME type based on the extension name of the specified file.
|
||||
* This method will use a local map between extension name and MIME type.
|
||||
* @param string $file the file name.
|
||||
* @param string $magicFile the path of the file that contains all available MIME type information.
|
||||
* If this is not set, the default 'system.utils.mimeTypes' file will be used.
|
||||
* This parameter has been available since version 1.1.3.
|
||||
* @return string the MIME type. Null is returned if the MIME type cannot be determined.
|
||||
*/
|
||||
public static function getMimeTypeByExtension($file,$magicFile=null)
|
||||
{
|
||||
static $extensions,$customExtensions=array();
|
||||
if($magicFile===null && $extensions===null)
|
||||
$extensions=require(Yii::getPathOfAlias('system.utils.mimeTypes').'.php');
|
||||
elseif($magicFile!==null && !isset($customExtensions[$magicFile]))
|
||||
$customExtensions[$magicFile]=require($magicFile);
|
||||
if(($ext=pathinfo($file,PATHINFO_EXTENSION))!=='')
|
||||
{
|
||||
$ext=strtolower($ext);
|
||||
if($magicFile===null && isset($extensions[$ext]))
|
||||
return $extensions[$ext];
|
||||
elseif($magicFile!==null && isset($customExtensions[$magicFile][$ext]))
|
||||
return $customExtensions[$magicFile][$ext];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared environment safe version of mkdir. Supports recursive creation.
|
||||
* For avoidance of umask side-effects chmod is used.
|
||||
*
|
||||
* @param string $dst path to be created
|
||||
* @param array $options newDirMode element used, must contain access bitmask
|
||||
* @param boolean $recursive whether to create directory structure recursive if parent dirs do not exist
|
||||
* @return boolean result of mkdir
|
||||
* @see mkdir
|
||||
*/
|
||||
private static function mkdir($dst,array $options,$recursive)
|
||||
{
|
||||
$prevDir=dirname($dst);
|
||||
if($recursive && !is_dir($dst) && !is_dir($prevDir))
|
||||
self::mkdir(dirname($dst),$options,true);
|
||||
|
||||
$mode=isset($options['newDirMode']) ? $options['newDirMode'] : 0777;
|
||||
$res=mkdir($dst, $mode);
|
||||
@chmod($dst,$mode);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
339
framework/utils/CFormatter.php
Normal file
339
framework/utils/CFormatter.php
Normal file
@@ -0,0 +1,339 @@
|
||||
<?php
|
||||
/**
|
||||
* CFormatter class file.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright 2008-2013 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
/**
|
||||
* CFormatter provides a set of commonly used data formatting methods.
|
||||
*
|
||||
* The formatting methods provided by CFormatter are all named in the form of <code>formatXyz</code>.
|
||||
* The behavior of some of them may be configured via the properties of CFormatter. For example,
|
||||
* by configuring {@link dateFormat}, one may control how {@link formatDate} formats the value into a date string.
|
||||
*
|
||||
* For convenience, CFormatter also implements the mechanism of calling formatting methods with their shortcuts (called types).
|
||||
* In particular, if a formatting method is named <code>formatXyz</code>, then its shortcut method is <code>xyz</code>
|
||||
* (case-insensitive). For example, calling <code>$formatter->date($value)</code> is equivalent to calling
|
||||
* <code>$formatter->formatDate($value)</code>.
|
||||
*
|
||||
* Currently, the following types are recognizable:
|
||||
* <ul>
|
||||
* <li>raw: the attribute value will not be changed at all.</li>
|
||||
* <li>text: the attribute value will be HTML-encoded when rendering.</li>
|
||||
* <li>ntext: the {@link formatNtext} method will be called to format the attribute value as a HTML-encoded plain text with newlines converted as the HTML <br /> or <p></p> tags.</li>
|
||||
* <li>html: the attribute value will be purified and then returned.</li>
|
||||
* <li>date: the {@link formatDate} method will be called to format the attribute value as a date.</li>
|
||||
* <li>time: the {@link formatTime} method will be called to format the attribute value as a time.</li>
|
||||
* <li>datetime: the {@link formatDatetime} method will be called to format the attribute value as a date with time.</li>
|
||||
* <li>boolean: the {@link formatBoolean} method will be called to format the attribute value as a boolean display.</li>
|
||||
* <li>number: the {@link formatNumber} method will be called to format the attribute value as a number display.</li>
|
||||
* <li>email: the {@link formatEmail} method will be called to format the attribute value as a mailto link.</li>
|
||||
* <li>image: the {@link formatImage} method will be called to format the attribute value as an image tag where the attribute value is the image URL.</li>
|
||||
* <li>url: the {@link formatUrl} method will be called to format the attribute value as a hyperlink where the attribute value is the URL.</li>
|
||||
* <li>size: the {@link formatSize} method will be called to format the attribute value, interpreted as a number of bytes, as a size in human readable form.</li>
|
||||
* </ul>
|
||||
*
|
||||
* By default, {@link CApplication} registers {@link CFormatter} as an application component whose ID is 'format'.
|
||||
* Therefore, one may call <code>Yii::app()->format->boolean(1)</code>.
|
||||
* You might want to replace this component with {@link CLocalizedFormatter} to enable formatting based on the
|
||||
* current locale settings.
|
||||
*
|
||||
* @property CHtmlPurifier $htmlPurifier The HTML purifier instance.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @package system.utils
|
||||
* @since 1.1.0
|
||||
*/
|
||||
class CFormatter extends CApplicationComponent
|
||||
{
|
||||
/**
|
||||
* @var CHtmlPurifier
|
||||
*/
|
||||
private $_htmlPurifier;
|
||||
|
||||
/**
|
||||
* @var string the format string to be used to format a date using PHP date() function. Defaults to 'Y/m/d'.
|
||||
*/
|
||||
public $dateFormat='Y/m/d';
|
||||
/**
|
||||
* @var string the format string to be used to format a time using PHP date() function. Defaults to 'h:i:s A'.
|
||||
*/
|
||||
public $timeFormat='h:i:s A';
|
||||
/**
|
||||
* @var string the format string to be used to format a date and time using PHP date() function. Defaults to 'Y/m/d h:i:s A'.
|
||||
*/
|
||||
public $datetimeFormat='Y/m/d h:i:s A';
|
||||
/**
|
||||
* @var array the format used to format a number with PHP number_format() function.
|
||||
* Three elements may be specified: "decimals", "decimalSeparator" and "thousandSeparator".
|
||||
* They correspond to the number of digits after the decimal point, the character displayed as the decimal point
|
||||
* and the thousands separator character.
|
||||
*/
|
||||
public $numberFormat=array('decimals'=>null, 'decimalSeparator'=>null, 'thousandSeparator'=>null);
|
||||
/**
|
||||
* @var array the text to be displayed when formatting a boolean value. The first element corresponds
|
||||
* to the text display for false, the second element for true. Defaults to <code>array('No', 'Yes')</code>.
|
||||
*/
|
||||
public $booleanFormat=array('No','Yes');
|
||||
/**
|
||||
* @var array the options to be passed to CHtmlPurifier instance used in this class. CHtmlPurifier is used
|
||||
* in {@link formatHtml} method, so this property could be useful to customize HTML filtering behavior.
|
||||
* @since 1.1.13
|
||||
*/
|
||||
public $htmlPurifierOptions=array();
|
||||
/**
|
||||
* @var array the format used to format size (bytes). Three elements may be specified: "base", "decimals" and "decimalSeparator".
|
||||
* They correspond to the base at which a kilobyte is calculated (1000 or 1024 bytes per kilobyte, defaults to 1024),
|
||||
* the number of digits after the decimal point (defaults to 2) and the character displayed as the decimal point.
|
||||
* "decimalSeparator" is available since version 1.1.13
|
||||
* @since 1.1.11
|
||||
*/
|
||||
public $sizeFormat=array(
|
||||
'base'=>1024,
|
||||
'decimals'=>2,
|
||||
'decimalSeparator'=>null,
|
||||
);
|
||||
|
||||
/**
|
||||
* Calls the format method when its shortcut is invoked.
|
||||
* This is a PHP magic method that we override to implement the shortcut format methods.
|
||||
* @param string $name the method name
|
||||
* @param array $parameters method parameters
|
||||
* @return mixed the method return value
|
||||
*/
|
||||
public function __call($name,$parameters)
|
||||
{
|
||||
if(method_exists($this,'format'.$name))
|
||||
return call_user_func_array(array($this,'format'.$name),$parameters);
|
||||
else
|
||||
return parent::__call($name,$parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a value based on the given type.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @param string $type the data type. This must correspond to a format method available in CFormatter.
|
||||
* For example, we can use 'text' here because there is method named {@link formatText}.
|
||||
* @throws CException if given type is unknown
|
||||
* @return string the formatted data
|
||||
*/
|
||||
public function format($value,$type)
|
||||
{
|
||||
$method='format'.$type;
|
||||
if(method_exists($this,$method))
|
||||
return $this->$method($value);
|
||||
else
|
||||
throw new CException(Yii::t('yii','Unknown type "{type}".',array('{type}'=>$type)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as is without any formatting.
|
||||
* This method simply returns back the parameter without any format.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function formatRaw($value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a HTML-encoded plain text.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function formatText($value)
|
||||
{
|
||||
return CHtml::encode($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a HTML-encoded plain text and converts newlines with HTML <br /> or
|
||||
* <p></p> tags.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @param boolean $paragraphs whether newlines should be converted to HTML <p></p> tags,
|
||||
* false by default meaning that HTML <br /> tags will be used
|
||||
* @param boolean $removeEmptyParagraphs whether empty paragraphs should be removed, defaults to true;
|
||||
* makes sense only when $paragraphs parameter is true
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function formatNtext($value,$paragraphs=false,$removeEmptyParagraphs=true)
|
||||
{
|
||||
$value=CHtml::encode($value);
|
||||
if($paragraphs)
|
||||
{
|
||||
$value='<p>'.str_replace(array("\r\n", "\n", "\r"), '</p><p>',$value).'</p>';
|
||||
if($removeEmptyParagraphs)
|
||||
$value=preg_replace('/(<\/p><p>){2,}/i','</p><p>',$value);
|
||||
return $value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nl2br($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as HTML text without any encoding.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function formatHtml($value)
|
||||
{
|
||||
return $this->getHtmlPurifier()->purify($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a date.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
* @see dateFormat
|
||||
*/
|
||||
public function formatDate($value)
|
||||
{
|
||||
return date($this->dateFormat,$this->normalizeDateValue($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a time.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
* @see timeFormat
|
||||
*/
|
||||
public function formatTime($value)
|
||||
{
|
||||
return date($this->timeFormat,$this->normalizeDateValue($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a date and time.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
* @see datetimeFormat
|
||||
*/
|
||||
public function formatDatetime($value)
|
||||
{
|
||||
return date($this->datetimeFormat,$this->normalizeDateValue($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes an expression as a timestamp.
|
||||
* @param mixed $time the time expression to be normalized
|
||||
* @return int the normalized result as a UNIX timestamp
|
||||
*/
|
||||
protected function normalizeDateValue($time)
|
||||
{
|
||||
if(is_string($time))
|
||||
{
|
||||
if(ctype_digit($time) || ($time{0}=='-' && ctype_digit(substr($time, 1))))
|
||||
return (int)$time;
|
||||
else
|
||||
return strtotime($time);
|
||||
}
|
||||
return (int)$time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a boolean.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
* @see booleanFormat
|
||||
*/
|
||||
public function formatBoolean($value)
|
||||
{
|
||||
return $value ? $this->booleanFormat[1] : $this->booleanFormat[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a mailto link.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function formatEmail($value)
|
||||
{
|
||||
return CHtml::mailto($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as an image tag.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function formatImage($value)
|
||||
{
|
||||
return CHtml::image($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a hyperlink.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function formatUrl($value)
|
||||
{
|
||||
$url=$value;
|
||||
if(strpos($url,'http://')!==0 && strpos($url,'https://')!==0)
|
||||
$url='http://'.$url;
|
||||
return CHtml::link(CHtml::encode($value),$url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a number using PHP number_format() function.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
* @see numberFormat
|
||||
*/
|
||||
public function formatNumber($value)
|
||||
{
|
||||
return number_format($value,$this->numberFormat['decimals'],$this->numberFormat['decimalSeparator'],$this->numberFormat['thousandSeparator']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CHtmlPurifier the HTML purifier instance
|
||||
*/
|
||||
public function getHtmlPurifier()
|
||||
{
|
||||
if($this->_htmlPurifier===null)
|
||||
$this->_htmlPurifier=new CHtmlPurifier;
|
||||
$this->_htmlPurifier->options=$this->htmlPurifierOptions;
|
||||
return $this->_htmlPurifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value in bytes as a size in human readable form.
|
||||
* @param integer $value value in bytes to be formatted
|
||||
* @param boolean $verbose if full names should be used (e.g. bytes, kilobytes, ...).
|
||||
* Defaults to false meaning that short names will be used (e.g. B, KB, ...).
|
||||
* @return string the formatted result
|
||||
* @see sizeFormat
|
||||
* @since 1.1.11
|
||||
*/
|
||||
public function formatSize($value,$verbose=false)
|
||||
{
|
||||
$base=$this->sizeFormat['base'];
|
||||
for($i=0; $base<=$value && $i<5; $i++)
|
||||
$value=$value/$base;
|
||||
|
||||
$value=round($value, $this->sizeFormat['decimals']);
|
||||
$formattedValue=isset($this->sizeFormat['decimalSeparator']) ? str_replace('.',$this->sizeFormat['decimalSeparator'],$value) : $value;
|
||||
$params=array($value,'{n}'=>$formattedValue);
|
||||
|
||||
switch($i)
|
||||
{
|
||||
case 0:
|
||||
return $verbose ? Yii::t('yii','{n} byte|{n} bytes',$params) : Yii::t('yii', '{n} B',$params);
|
||||
case 1:
|
||||
return $verbose ? Yii::t('yii','{n} kilobyte|{n} kilobytes',$params) : Yii::t('yii','{n} KB',$params);
|
||||
case 2:
|
||||
return $verbose ? Yii::t('yii','{n} megabyte|{n} megabytes',$params) : Yii::t('yii','{n} MB',$params);
|
||||
case 3:
|
||||
return $verbose ? Yii::t('yii','{n} gigabyte|{n} gigabytes',$params) : Yii::t('yii','{n} GB',$params);
|
||||
default:
|
||||
return $verbose ? Yii::t('yii','{n} terabyte|{n} terabytes',$params) : Yii::t('yii','{n} TB',$params);
|
||||
}
|
||||
}
|
||||
}
|
||||
131
framework/utils/CLocalizedFormatter.php
Normal file
131
framework/utils/CLocalizedFormatter.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/**
|
||||
* CLocalizedFormatter class file.
|
||||
*
|
||||
* @author Carsten Brandt <mail@cebe.cc>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright 2008-2013 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
/**
|
||||
* CLocalizedFormatter provides a set of commonly used data formatting methods based on the current locale settings.
|
||||
*
|
||||
* It provides the same functionality as {@link CFormatter}, but overrides all the settings for
|
||||
* {@link booleanFormat}, {@link datetimeFormat} and {@link numberFormat} with the values for the
|
||||
* current locale. Because of this you are not able to configure these properties for CLocalizedFormatter directly.
|
||||
* Date and time format can be adjsuted by setting {@link dateFormat} and {@link timeFormat}.
|
||||
*
|
||||
* It uses {@link CApplication::locale} by default but you can set a custom locale by using {@link setLocale}-method.
|
||||
*
|
||||
* For a list of recognizable format types, and details on how to call the formatter methods,
|
||||
* see {@link CFormatter} documentation.
|
||||
*
|
||||
* To replace the application component 'format', which is registered by {@link CApplication} by default, you can
|
||||
* put this in your application 'components' config:
|
||||
* <code>
|
||||
* 'format' => array(
|
||||
* 'class' => 'CLocalizedFormatter',
|
||||
* ),
|
||||
* </code>
|
||||
*
|
||||
* @author Carsten Brandt <mail@cebe.cc>
|
||||
* @package system.utils
|
||||
* @since 1.1.14
|
||||
*/
|
||||
class CLocalizedFormatter extends CFormatter
|
||||
{
|
||||
private $_locale;
|
||||
/**
|
||||
* @var string the width of the date pattern. It can be 'full', 'long', 'medium' and 'short'. Defaults to 'medium'.
|
||||
* @see CDateFormatter::formatDateTime()
|
||||
*/
|
||||
public $dateFormat='medium';
|
||||
/**
|
||||
* @var string the width of the time pattern. It can be 'full', 'long', 'medium' and 'short'. Defaults to 'medium'.
|
||||
* @see CDateFormatter::formatDateTime()
|
||||
*/
|
||||
public $timeFormat='medium';
|
||||
|
||||
/**
|
||||
* Set the locale to use for formatting values.
|
||||
* @param CLocale|string $locale an instance of CLocale or a locale ID
|
||||
*/
|
||||
public function setLocale($locale)
|
||||
{
|
||||
if(is_string($locale))
|
||||
$locale=CLocale::getInstance($locale);
|
||||
$this->sizeFormat['decimalSeparator']=$locale->getNumberSymbol('decimal');
|
||||
$this->_locale=$locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CLocale $locale the locale currently used for formatting values
|
||||
*/
|
||||
public function getLocale()
|
||||
{
|
||||
if($this->_locale === null) {
|
||||
$this->setLocale(Yii::app()->locale);
|
||||
}
|
||||
return $this->_locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a boolean.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
* @see booleanFormat
|
||||
*/
|
||||
public function formatBoolean($value)
|
||||
{
|
||||
return $value ? Yii::t('yii','Yes') : Yii::t('yii','No');
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a date using the {@link locale}s date formatter.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
* @see dateFormat
|
||||
* @see CLocale::getDateFormatter()
|
||||
*/
|
||||
public function formatDate($value)
|
||||
{
|
||||
return $this->getLocale()->dateFormatter->formatDateTime($this->normalizeDateValue($value), $this->dateFormat, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a time using the {@link locale}s date formatter.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
* @see timeFormat
|
||||
* @see CLocale::getDateFormatter()
|
||||
*/
|
||||
public function formatTime($value)
|
||||
{
|
||||
return $this->getLocale()->dateFormatter->formatDateTime($this->normalizeDateValue($value), null, $this->timeFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a date and time using the {@link locale}s date formatter.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
* @see dateFormat
|
||||
* @see timeFormat
|
||||
* @see CLocale::getDateFormatter()
|
||||
*/
|
||||
public function formatDatetime($value)
|
||||
{
|
||||
return $this->getLocale()->dateFormatter->formatDateTime($this->normalizeDateValue($value), $this->dateFormat, $this->timeFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a number using the {@link locale}s number formatter.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
* @see CLocale::getNumberFormatter()
|
||||
*/
|
||||
public function formatNumber($value)
|
||||
{
|
||||
return $this->getLocale()->numberFormatter->formatDecimal($value);
|
||||
}
|
||||
}
|
||||
208
framework/utils/CMarkdownParser.php
Normal file
208
framework/utils/CMarkdownParser.php
Normal file
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
/**
|
||||
* CMarkdownParser class file.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright 2008-2013 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
require_once(Yii::getPathOfAlias('system.vendors.markdown.markdown').'.php');
|
||||
if(!class_exists('HTMLPurifier_Bootstrap',false))
|
||||
{
|
||||
require_once(Yii::getPathOfAlias('system.vendors.htmlpurifier').DIRECTORY_SEPARATOR.'HTMLPurifier.standalone.php');
|
||||
HTMLPurifier_Bootstrap::registerAutoload();
|
||||
}
|
||||
|
||||
/**
|
||||
* CMarkdownParser is a wrapper of {@link http://michelf.com/projects/php-markdown/extra/ MarkdownExtra_Parser}.
|
||||
*
|
||||
* CMarkdownParser extends MarkdownExtra_Parser by using Text_Highlighter
|
||||
* to highlight code blocks with specific language syntax.
|
||||
* In particular, if a code block starts with the following:
|
||||
* <pre>
|
||||
* [language]
|
||||
* </pre>
|
||||
* The syntax for the specified language will be used to highlight
|
||||
* code block. The languages supported include (case-insensitive):
|
||||
* ABAP, CPP, CSS, DIFF, DTD, HTML, JAVA, JAVASCRIPT,
|
||||
* MYSQL, PERL, PHP, PYTHON, RUBY, SQL, XML
|
||||
*
|
||||
* You can also specify options to be passed to the syntax highlighter. For example:
|
||||
* <pre>
|
||||
* [php showLineNumbers=1]
|
||||
* </pre>
|
||||
* which will show line numbers in each line of the code block.
|
||||
*
|
||||
* For details about the standard markdown syntax, please check the following:
|
||||
* <ul>
|
||||
* <li>{@link http://daringfireball.net/projects/markdown/syntax official markdown syntax}</li>
|
||||
* <li>{@link http://michelf.com/projects/php-markdown/extra/ markdown extra syntax}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @property string $defaultCssFile The default CSS file that is used to highlight code blocks.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @package system.utils
|
||||
* @since 1.0
|
||||
*/
|
||||
class CMarkdownParser extends MarkdownExtra_Parser
|
||||
{
|
||||
/**
|
||||
* @var string the css class for the div element containing
|
||||
* the code block that is highlighted. Defaults to 'hl-code'.
|
||||
*/
|
||||
public $highlightCssClass='hl-code';
|
||||
/**
|
||||
* @var mixed the options to be passed to {@link http://htmlpurifier.org HTML Purifier}.
|
||||
* This can be a HTMLPurifier_Config object, an array of directives (Namespace.Directive => Value)
|
||||
* or the filename of an ini file.
|
||||
* This property is used only when {@link safeTransform} is invoked.
|
||||
* @see http://htmlpurifier.org/live/configdoc/plain.html
|
||||
* @since 1.1.4
|
||||
*/
|
||||
public $purifierOptions=null;
|
||||
|
||||
/**
|
||||
* Transforms the content and purifies the result.
|
||||
* This method calls the transform() method to convert
|
||||
* markdown content into HTML content. It then
|
||||
* uses {@link CHtmlPurifier} to purify the HTML content
|
||||
* to avoid XSS attacks.
|
||||
* @param string $content the markdown content
|
||||
* @return string the purified HTML content
|
||||
*/
|
||||
public function safeTransform($content)
|
||||
{
|
||||
$content=$this->transform($content);
|
||||
$purifier=new HTMLPurifier($this->purifierOptions);
|
||||
$purifier->config->set('Cache.SerializerPath',Yii::app()->getRuntimePath());
|
||||
return $purifier->purify($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the default CSS file that is used to highlight code blocks.
|
||||
*/
|
||||
public function getDefaultCssFile()
|
||||
{
|
||||
return Yii::getPathOfAlias('system.vendors.TextHighlighter.highlight').'.css';
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function when a code block is matched.
|
||||
* @param array $matches matches
|
||||
* @return string the highlighted code block
|
||||
*/
|
||||
public function _doCodeBlocks_callback($matches)
|
||||
{
|
||||
$codeblock = $this->outdent($matches[1]);
|
||||
if(($codeblock = $this->highlightCodeBlock($codeblock)) !== null)
|
||||
return "\n\n".$this->hashBlock($codeblock)."\n\n";
|
||||
else
|
||||
return parent::_doCodeBlocks_callback($matches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function when a fenced code block is matched.
|
||||
* @param array $matches matches
|
||||
* @return string the highlighted code block
|
||||
*/
|
||||
public function _doFencedCodeBlocks_callback($matches)
|
||||
{
|
||||
return "\n\n".$this->hashBlock($this->highlightCodeBlock($matches[2]))."\n\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlights the code block.
|
||||
* @param string $codeblock the code block
|
||||
* @return string the highlighted code block. Null if the code block does not need to highlighted
|
||||
*/
|
||||
protected function highlightCodeBlock($codeblock)
|
||||
{
|
||||
if(($tag=$this->getHighlightTag($codeblock))!==null && ($highlighter=$this->createHighLighter($tag)))
|
||||
{
|
||||
$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
|
||||
$tagLen = strpos($codeblock, $tag)+strlen($tag);
|
||||
$codeblock = ltrim(substr($codeblock, $tagLen));
|
||||
$output=preg_replace('/<span\s+[^>]*>(\s*)<\/span>/', '\1', $highlighter->highlight($codeblock));
|
||||
return "<div class=\"{$this->highlightCssClass}\">".$output."</div>";
|
||||
}
|
||||
else
|
||||
return "<pre>".CHtml::encode($codeblock)."</pre>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user-entered highlighting options.
|
||||
* @param string $codeblock code block with highlighting options.
|
||||
* @return string the user-entered highlighting options. Null if no option is entered.
|
||||
*/
|
||||
protected function getHighlightTag($codeblock)
|
||||
{
|
||||
$str = trim(current(preg_split("/\r|\n/", $codeblock,2)));
|
||||
if(strlen($str) > 2 && $str[0] === '[' && $str[strlen($str)-1] === ']')
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a highlighter instance.
|
||||
* @param string $options the user-entered options
|
||||
* @return Text_Highlighter the highlighter instance
|
||||
*/
|
||||
protected function createHighLighter($options)
|
||||
{
|
||||
if(!class_exists('Text_Highlighter', false))
|
||||
{
|
||||
require_once(Yii::getPathOfAlias('system.vendors.TextHighlighter.Text.Highlighter').'.php');
|
||||
require_once(Yii::getPathOfAlias('system.vendors.TextHighlighter.Text.Highlighter.Renderer.Html').'.php');
|
||||
}
|
||||
$lang = current(preg_split('/\s+/', substr(substr($options,1), 0,-1),2));
|
||||
$highlighter = Text_Highlighter::factory($lang);
|
||||
if($highlighter)
|
||||
$highlighter->setRenderer(new Text_Highlighter_Renderer_Html($this->getHighlightConfig($options)));
|
||||
return $highlighter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the config for the highlighter.
|
||||
* @param string $options user-entered options
|
||||
* @return array the highlighter config
|
||||
*/
|
||||
public function getHighlightConfig($options)
|
||||
{
|
||||
$config = array('use_language'=>true);
|
||||
if( $this->getInlineOption('showLineNumbers', $options, false) )
|
||||
$config['numbers'] = HL_NUMBERS_LI;
|
||||
$config['tabsize'] = $this->getInlineOption('tabSize', $options, 4);
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the config for the highlighter.
|
||||
*
|
||||
* NOTE: This method is deprecated due to a mistake in the method name.
|
||||
* Use {@link getHighlightConfig} instead of this.
|
||||
*
|
||||
* @param string $options user-entered options
|
||||
* @return array the highlighter config
|
||||
*/
|
||||
public function getHiglightConfig($options)
|
||||
{
|
||||
return $this->getHighlightConfig($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the specified configuration.
|
||||
* @param string $name the configuration name
|
||||
* @param string $str the user-entered options
|
||||
* @param mixed $defaultValue default value if the configuration is not present
|
||||
* @return mixed the configuration value
|
||||
*/
|
||||
protected function getInlineOption($name, $str, $defaultValue)
|
||||
{
|
||||
if(preg_match('/'.$name.'(\s*=\s*(\d+))?/i', $str, $v) && count($v) > 2)
|
||||
return $v[2];
|
||||
else
|
||||
return $defaultValue;
|
||||
}
|
||||
}
|
||||
193
framework/utils/CPasswordHelper.php
Normal file
193
framework/utils/CPasswordHelper.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/**
|
||||
* CPasswordHelper class file.
|
||||
*
|
||||
* @author Tom Worster <fsb@thefsb.org>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright 2008-2013 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
/**
|
||||
* CPasswordHelper provides a simple API for secure password hashing and verification.
|
||||
*
|
||||
* CPasswordHelper uses the Blowfish hash algorithm available in many PHP runtime
|
||||
* environments through the PHP {@link http://php.net/manual/en/function.crypt.php crypt()}
|
||||
* built-in function. As of Dec 2012 it is the strongest algorithm available in PHP
|
||||
* and the only algorithm without some security concerns surrounding it. For this reason,
|
||||
* CPasswordHelper fails to initialize when run in and environment that does not have
|
||||
* crypt() and its Blowfish option. Systems with the option include:
|
||||
* (1) Most *nix systems since PHP 4 (the algorithm is part of the library function crypt(3));
|
||||
* (2) All PHP systems since 5.3.0; (3) All PHP systems with the
|
||||
* {@link http://www.hardened-php.net/suhosin/ Suhosin patch}.
|
||||
* For more information about password hashing, crypt() and Blowfish, please read
|
||||
* the Yii Wiki article
|
||||
* {@link http://www.yiiframework.com/wiki/425/use-crypt-for-password-storage/ Use crypt() for password storage}.
|
||||
* and the
|
||||
* PHP RFC {@link http://wiki.php.net/rfc/password_hash Adding simple password hashing API}.
|
||||
*
|
||||
* CPasswordHelper throws an exception if the Blowfish hash algorithm is not
|
||||
* available in the runtime PHP's crypt() function. It can be used as follows
|
||||
*
|
||||
* Generate a hash from a password:
|
||||
* <pre>
|
||||
* $hash = CPasswordHelper::hashPassword($password);
|
||||
* </pre>
|
||||
* This hash can be stored in a database (e.g. CHAR(64) CHARACTER SET latin1). The
|
||||
* hash is usually generated and saved to the database when the user enters a new password.
|
||||
* But it can also be useful to generate and save a hash after validating a user's
|
||||
* password in order to change the cost or refresh the salt.
|
||||
*
|
||||
* To verify a password, fetch the user's saved hash from the database (into $hash) and:
|
||||
* <pre>
|
||||
* if (CPasswordHelper::verifyPassword($password, $hash))
|
||||
* // password is good
|
||||
* else
|
||||
* // password is bad
|
||||
* </pre>
|
||||
*
|
||||
* @author Tom Worster <fsb@thefsb.org>
|
||||
* @package system.utils
|
||||
* @since 1.1.14
|
||||
*/
|
||||
class CPasswordHelper
|
||||
{
|
||||
/**
|
||||
* Check for availability of PHP crypt() with the Blowfish hash option.
|
||||
* @throws CException if the runtime system does not have PHP crypt() or its Blowfish hash option.
|
||||
*/
|
||||
protected static function checkBlowfish()
|
||||
{
|
||||
if(!function_exists('crypt'))
|
||||
throw new CException(Yii::t('yii','{class} requires the PHP crypt() function. This system does not have it.',
|
||||
array('{class}'=>__CLASS__)));
|
||||
|
||||
if(!defined('CRYPT_BLOWFISH') || !CRYPT_BLOWFISH)
|
||||
throw new CException(Yii::t('yii',
|
||||
'{class} requires the Blowfish option of the PHP crypt() function. This system does not have it.',
|
||||
array('{class}'=>__CLASS__)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a secure hash from a password and a random salt.
|
||||
*
|
||||
* Uses the
|
||||
* PHP {@link http://php.net/manual/en/function.crypt.php crypt()} built-in function
|
||||
* with the Blowfish hash option.
|
||||
*
|
||||
* @param string $password The password to be hashed.
|
||||
* @param int $cost Cost parameter used by the Blowfish hash algorithm.
|
||||
* The higher the value of cost,
|
||||
* the longer it takes to generate the hash and to verify a password against it. Higher cost
|
||||
* therefore slows down a brute-force attack. For best protection against brute for attacks,
|
||||
* set it to the highest value that is tolerable on production servers. The time taken to
|
||||
* compute the hash doubles for every increment by one of $cost. So, for example, if the
|
||||
* hash takes 1 second to compute when $cost is 14 then then the compute time varies as
|
||||
* 2^($cost - 14) seconds.
|
||||
* @return string The password hash string, ASCII and not longer than 64 characters.
|
||||
* @throws CException on bad password parameter or if crypt() with Blowfish hash is not available.
|
||||
*/
|
||||
public static function hashPassword($password,$cost=13)
|
||||
{
|
||||
self::checkBlowfish();
|
||||
$salt=self::generateSalt($cost);
|
||||
$hash=crypt($password,$salt);
|
||||
|
||||
if(!is_string($hash) || (function_exists('mb_strlen') ? mb_strlen($hash, '8bit') : strlen($hash))<32)
|
||||
throw new CException(Yii::t('yii','Internal error while generating hash.'));
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a password against a hash.
|
||||
*
|
||||
* @param string $password The password to verify. If password is empty or not a string, method will return false.
|
||||
* @param string $hash The hash to verify the password against.
|
||||
* @return bool True if the password matches the hash.
|
||||
* @throws CException on bad password or hash parameters or if crypt() with Blowfish hash is not available.
|
||||
*/
|
||||
public static function verifyPassword($password, $hash)
|
||||
{
|
||||
self::checkBlowfish();
|
||||
if(!is_string($password) || $password==='')
|
||||
return false;
|
||||
|
||||
if (!$password || !preg_match('{^\$2[axy]\$(\d\d)\$[\./0-9A-Za-z]{22}}',$hash,$matches) ||
|
||||
$matches[1]<4 || $matches[1]>31)
|
||||
return false;
|
||||
|
||||
$test=crypt($password,$hash);
|
||||
if(!is_string($test) || strlen($test)<32)
|
||||
return false;
|
||||
|
||||
return self::same($test, $hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for sameness of two strings using an algorithm with timing
|
||||
* independent of the string values if the subject strings are of equal length.
|
||||
*
|
||||
* The function can be useful to prevent timing attacks. For example, if $a and $b
|
||||
* are both hash values from the same algorithm, then the timing of this function
|
||||
* does not reveal whether or not there is a match.
|
||||
*
|
||||
* NOTE: timing is affected if $a and $b are different lengths or either is not a
|
||||
* string. For the purpose of checking password hash this does not reveal information
|
||||
* useful to an attacker.
|
||||
*
|
||||
* @see http://blog.astrumfutura.com/2010/10/nanosecond-scale-remote-timing-attacks-on-php-applications-time-to-take-them-seriously/
|
||||
* @see http://codereview.stackexchange.com/questions/13512
|
||||
* @see https://github.com/ircmaxell/password_compat/blob/master/lib/password.php
|
||||
*
|
||||
* @param string $a First subject string to compare.
|
||||
* @param string $b Second subject string to compare.
|
||||
* @return bool true if the strings are the same, false if they are different or if
|
||||
* either is not a string.
|
||||
*/
|
||||
public static function same($a,$b)
|
||||
{
|
||||
if(!is_string($a) || !is_string($b))
|
||||
return false;
|
||||
|
||||
$mb=function_exists('mb_strlen');
|
||||
$length=$mb ? mb_strlen($a,'8bit') : strlen($a);
|
||||
if($length!==($mb ? mb_strlen($b,'8bit') : strlen($b)))
|
||||
return false;
|
||||
|
||||
$check=0;
|
||||
for($i=0;$i<$length;$i+=1)
|
||||
$check|=(ord($a[$i])^ord($b[$i]));
|
||||
|
||||
return $check===0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a salt that can be used to generate a password hash.
|
||||
*
|
||||
* The PHP {@link http://php.net/manual/en/function.crypt.php crypt()} built-in function
|
||||
* requires, for the Blowfish hash algorithm, a salt string in a specific format:
|
||||
* "$2a$" (in which the "a" may be replaced by "x" or "y" see PHP manual for details),
|
||||
* a two digit cost parameter,
|
||||
* "$",
|
||||
* 22 characters from the alphabet "./0-9A-Za-z".
|
||||
*
|
||||
* @param int $cost Cost parameter used by the Blowfish hash algorithm.
|
||||
* @return string the random salt value.
|
||||
* @throws CException in case of invalid cost number
|
||||
*/
|
||||
public static function generateSalt($cost=13)
|
||||
{
|
||||
if(!is_numeric($cost))
|
||||
throw new CException(Yii::t('yii','{class}::$cost must be a number.',array('{class}'=>__CLASS__)));
|
||||
|
||||
$cost=(int)$cost;
|
||||
if($cost<4 || $cost>31)
|
||||
throw new CException(Yii::t('yii','{class}::$cost must be between 4 and 31.',array('{class}'=>__CLASS__)));
|
||||
|
||||
if(($random=Yii::app()->getSecurityManager()->generateRandomString(22,true))===false)
|
||||
if(($random=Yii::app()->getSecurityManager()->generateRandomString(22,false))===false)
|
||||
throw new CException(Yii::t('yii','Unable to generate random string.'));
|
||||
return sprintf('$2a$%02d$',$cost).strtr($random,array('_'=>'.','~'=>'/'));
|
||||
}
|
||||
}
|
||||
157
framework/utils/CPropertyValue.php
Normal file
157
framework/utils/CPropertyValue.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
/**
|
||||
* CPropertyValue class file.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright 2008-2013 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
/**
|
||||
* CPropertyValue is a helper class that provides static methods to convert component property values to specific types.
|
||||
*
|
||||
* CPropertyValue is commonly used in component setter methods to ensure
|
||||
* the new property value is of the specific type.
|
||||
* For example, a boolean-typed property setter method would be as follows,
|
||||
* <pre>
|
||||
* public function setPropertyName($value)
|
||||
* {
|
||||
* $value=CPropertyValue::ensureBoolean($value);
|
||||
* // $value is now of boolean type
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Properties can be of the following types with specific type conversion rules:
|
||||
* <ul>
|
||||
* <li>string: a boolean value will be converted to 'true' or 'false'.</li>
|
||||
* <li>boolean: string 'true' (case-insensitive) will be converted to true,
|
||||
* string 'false' (case-insensitive) will be converted to false.</li>
|
||||
* <li>integer</li>
|
||||
* <li>float</li>
|
||||
* <li>array: string starting with '(' and ending with ')' will be considered as
|
||||
* as an array expression and will be evaluated. Otherwise, an array
|
||||
* with the value to be ensured is returned.</li>
|
||||
* <li>object</li>
|
||||
* <li>enum: enumerable type, represented by an array of strings.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @package system.utils
|
||||
* @since 1.0
|
||||
*/
|
||||
class CPropertyValue
|
||||
{
|
||||
/**
|
||||
* Converts a value to boolean type.
|
||||
* Note, string 'true' (case-insensitive) will be converted to true,
|
||||
* string 'false' (case-insensitive) will be converted to false.
|
||||
* If a string represents a non-zero number, it will be treated as true.
|
||||
* @param mixed $value the value to be converted.
|
||||
* @return boolean
|
||||
*/
|
||||
public static function ensureBoolean($value)
|
||||
{
|
||||
if (is_string($value))
|
||||
return !strcasecmp($value,'true') || $value!=0;
|
||||
else
|
||||
return (boolean)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value to string type.
|
||||
* Note, a boolean value will be converted to 'true' if it is true
|
||||
* and 'false' if it is false.
|
||||
* @param mixed $value the value to be converted.
|
||||
* @return string
|
||||
*/
|
||||
public static function ensureString($value)
|
||||
{
|
||||
if (is_bool($value))
|
||||
return $value?'true':'false';
|
||||
else
|
||||
return (string)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value to integer type.
|
||||
* @param mixed $value the value to be converted.
|
||||
* @return integer
|
||||
*/
|
||||
public static function ensureInteger($value)
|
||||
{
|
||||
return (integer)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value to float type.
|
||||
* @param mixed $value the value to be converted.
|
||||
* @return float
|
||||
*/
|
||||
public static function ensureFloat($value)
|
||||
{
|
||||
return (float)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value to array type. If the value is a string and it is
|
||||
* in the form (a,b,c) then an array consisting of each of the elements
|
||||
* will be returned. If the value is a string and it is not in this form
|
||||
* then an array consisting of just the string will be returned. If the value
|
||||
* is not a string then
|
||||
* @param mixed $value the value to be converted.
|
||||
* @return array
|
||||
*/
|
||||
public static function ensureArray($value)
|
||||
{
|
||||
if(is_string($value))
|
||||
{
|
||||
$value = trim($value);
|
||||
$len = strlen($value);
|
||||
if ($len >= 2 && $value[0] == '(' && $value[$len-1] == ')')
|
||||
{
|
||||
eval('$array=array'.$value.';');
|
||||
return $array;
|
||||
}
|
||||
else
|
||||
return $len>0?array($value):array();
|
||||
}
|
||||
else
|
||||
return (array)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value to object type.
|
||||
* @param mixed $value the value to be converted.
|
||||
* @return object
|
||||
*/
|
||||
public static function ensureObject($value)
|
||||
{
|
||||
return (object)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value to enum type.
|
||||
*
|
||||
* This method checks if the value is of the specified enumerable type.
|
||||
* A value is a valid enumerable value if it is equal to the name of a constant
|
||||
* in the specified enumerable type (class).
|
||||
* For more details about enumerable, see {@link CEnumerable}.
|
||||
*
|
||||
* @param string $value the enumerable value to be checked.
|
||||
* @param string $enumType the enumerable class name (make sure it is included before calling this function).
|
||||
* @return string the valid enumeration value
|
||||
* @throws CException if the value is not a valid enumerable value
|
||||
*/
|
||||
public static function ensureEnum($value,$enumType)
|
||||
{
|
||||
static $types=array();
|
||||
if(!isset($types[$enumType]))
|
||||
$types[$enumType]=new ReflectionClass($enumType);
|
||||
if($types[$enumType]->hasConstant($value))
|
||||
return $value;
|
||||
else
|
||||
throw new CException(Yii::t('yii','Invalid enumerable value "{value}". Please make sure it is among ({enum}).',
|
||||
array('{value}'=>$value, '{enum}'=>implode(', ',$types[$enumType]->getConstants()))));
|
||||
}
|
||||
}
|
||||
376
framework/utils/CTimestamp.php
Normal file
376
framework/utils/CTimestamp.php
Normal file
@@ -0,0 +1,376 @@
|
||||
<?php
|
||||
/**
|
||||
* CTimestamp class file.
|
||||
*
|
||||
* @author Wei Zhuo <weizhuo[at]gamil[dot]com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright 2008-2013 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
/**
|
||||
* CTimestamp represents a timestamp.
|
||||
*
|
||||
* Part of this class was adapted from the ADOdb Date Library
|
||||
* {@link http://phplens.com/phpeverywhere/ ADOdb abstraction library}.
|
||||
* The original source code was released under both BSD and GNU Lesser GPL
|
||||
* library license, with the following copyright notice:
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004 John Lim
|
||||
* All rights reserved.
|
||||
*
|
||||
* This class is provided to support UNIX timestamp that is beyond the range
|
||||
* of 1901-2038 on Unix and1970-2038 on Windows. Except {@link getTimestamp},
|
||||
* all other methods in this class can work with the extended timestamp range.
|
||||
* For {@link getTimestamp}, because it is merely a wrapper of
|
||||
* {@link mktime http://php.net/manual/en/function.mktime.php}, it may still
|
||||
* be subject to the limit of timestamp range on certain platforms. Please refer
|
||||
* to the PHP manual for more information.
|
||||
*
|
||||
* @author Wei Zhuo <weizhuo[at]gmail[dot]com>
|
||||
* @package system.utils
|
||||
* @since 1.0
|
||||
*/
|
||||
class CTimestamp
|
||||
{
|
||||
/**
|
||||
* Gets day of week, 0 = Sunday,... 6=Saturday.
|
||||
* Algorithm from PEAR::Date_Calc
|
||||
* @param integer $year year
|
||||
* @param integer $month month
|
||||
* @param integer $day day
|
||||
* @return integer day of week
|
||||
*/
|
||||
public static function getDayofWeek($year, $month, $day)
|
||||
{
|
||||
/*
|
||||
Pope Gregory removed 10 days - October 5 to October 14 - from the year 1582 and
|
||||
proclaimed that from that time onwards 3 days would be dropped from the calendar
|
||||
every 400 years.
|
||||
|
||||
Thursday, October 4, 1582 (Julian) was followed immediately by Friday, October 15, 1582 (Gregorian).
|
||||
*/
|
||||
if ($year <= 1582)
|
||||
{
|
||||
if ($year < 1582 ||
|
||||
($year == 1582 && ($month < 10 || ($month == 10 && $day < 15))))
|
||||
{
|
||||
$greg_correction = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
$greg_correction = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$greg_correction = 0;
|
||||
}
|
||||
|
||||
if($month > 2)
|
||||
$month -= 2;
|
||||
else
|
||||
{
|
||||
$month += 10;
|
||||
$year--;
|
||||
}
|
||||
|
||||
$day = floor((13 * $month - 1) / 5) +
|
||||
$day + ($year % 100) +
|
||||
floor(($year % 100) / 4) +
|
||||
floor(($year / 100) / 4) - 2 *
|
||||
floor($year / 100) + 77 + $greg_correction;
|
||||
|
||||
return $day - 7 * floor($day / 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for leap year, returns true if it is. No 2-digit year check. Also
|
||||
* handles julian calendar correctly.
|
||||
* @param integer $year year to check
|
||||
* @return boolean true if is leap year
|
||||
*/
|
||||
public static function isLeapYear($year)
|
||||
{
|
||||
$year = self::digitCheck($year);
|
||||
if ($year % 4 != 0)
|
||||
return false;
|
||||
|
||||
if ($year % 400 == 0)
|
||||
return true;
|
||||
// if gregorian calendar (>1582), century not-divisible by 400 is not leap
|
||||
elseif ($year > 1582 && $year % 100 == 0 )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix 2-digit years. Works for any century.
|
||||
* Assumes that if 2-digit is more than 30 years in future, then previous century.
|
||||
* @param integer $y year
|
||||
* @return integer change two digit year into multiple digits
|
||||
*/
|
||||
protected static function digitCheck($y)
|
||||
{
|
||||
if ($y < 100){
|
||||
$yr = (integer) date("Y");
|
||||
$century = (integer) ($yr /100);
|
||||
|
||||
if ($yr%100 > 50) {
|
||||
$c1 = $century + 1;
|
||||
$c0 = $century;
|
||||
} else {
|
||||
$c1 = $century;
|
||||
$c0 = $century - 1;
|
||||
}
|
||||
$c1 *= 100;
|
||||
// if 2-digit year is less than 30 years in future, set it to this century
|
||||
// otherwise if more than 30 years in future, then we set 2-digit year to the prev century.
|
||||
if (($y + $c1) < $yr+30) $y = $y + $c1;
|
||||
else $y = $y + $c0*100;
|
||||
}
|
||||
return $y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 4-digit representation of the year.
|
||||
* @param integer $y year
|
||||
* @return integer 4-digit representation of the year
|
||||
*/
|
||||
public static function get4DigitYear($y)
|
||||
{
|
||||
return self::digitCheck($y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer get local time zone offset from GMT
|
||||
*/
|
||||
public static function getGMTDiff()
|
||||
{
|
||||
static $TZ;
|
||||
if (isset($TZ)) return $TZ;
|
||||
|
||||
$TZ = mktime(0,0,0,1,2,1970) - gmmktime(0,0,0,1,2,1970);
|
||||
return $TZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the getdate() array.
|
||||
* @param integer|boolean $d original date timestamp. False to use the current timestamp.
|
||||
* @param boolean $fast false to compute the day of the week, default is true
|
||||
* @param boolean $gmt true to calculate the GMT dates
|
||||
* @return array an array with date info.
|
||||
*/
|
||||
public static function getDate($d=false,$fast=false,$gmt=false)
|
||||
{
|
||||
if($d===false)
|
||||
$d=time();
|
||||
if($gmt)
|
||||
{
|
||||
$tz = date_default_timezone_get();
|
||||
date_default_timezone_set('GMT');
|
||||
$result = getdate($d);
|
||||
date_default_timezone_set($tz);
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = getdate($d);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the year, month, day are valid combination.
|
||||
* @param integer $y year
|
||||
* @param integer $m month
|
||||
* @param integer $d day
|
||||
* @return boolean true if valid date, semantic check only.
|
||||
*/
|
||||
public static function isValidDate($y,$m,$d)
|
||||
{
|
||||
return checkdate($m, $d, $y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the hour, minute and second are valid.
|
||||
* @param integer $h hour
|
||||
* @param integer $m minute
|
||||
* @param integer $s second
|
||||
* @param boolean $hs24 whether the hours should be 0 through 23 (default) or 1 through 12.
|
||||
* @return boolean true if valid date, semantic check only.
|
||||
*/
|
||||
public static function isValidTime($h,$m,$s,$hs24=true)
|
||||
{
|
||||
if($hs24 && ($h < 0 || $h > 23) || !$hs24 && ($h < 1 || $h > 12)) return false;
|
||||
if($m > 59 || $m < 0) return false;
|
||||
if($s > 59 || $s < 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a timestamp to a date string.
|
||||
* @param string $fmt format pattern
|
||||
* @param integer|boolean $d timestamp
|
||||
* @param boolean $is_gmt whether this is a GMT timestamp
|
||||
* @return string formatted date based on timestamp $d
|
||||
*/
|
||||
public static function formatDate($fmt,$d=false,$is_gmt=false)
|
||||
{
|
||||
if ($d === false)
|
||||
return ($is_gmt)? @gmdate($fmt): @date($fmt);
|
||||
|
||||
// check if number in 32-bit signed range
|
||||
if ((abs($d) <= 0x7FFFFFFF))
|
||||
{
|
||||
// if windows, must be +ve integer
|
||||
if ($d >= 0)
|
||||
return ($is_gmt)? @gmdate($fmt,$d): @date($fmt,$d);
|
||||
}
|
||||
|
||||
$_day_power = 86400;
|
||||
|
||||
$arr = self::getDate($d,true,$is_gmt);
|
||||
|
||||
$year = $arr['year'];
|
||||
$month = $arr['mon'];
|
||||
$day = $arr['mday'];
|
||||
$hour = $arr['hours'];
|
||||
$min = $arr['minutes'];
|
||||
$secs = $arr['seconds'];
|
||||
|
||||
$max = strlen($fmt);
|
||||
$dates = '';
|
||||
|
||||
/*
|
||||
at this point, we have the following integer vars to manipulate:
|
||||
$year, $month, $day, $hour, $min, $secs
|
||||
*/
|
||||
for ($i=0; $i < $max; $i++)
|
||||
{
|
||||
switch($fmt[$i])
|
||||
{
|
||||
case 'T': $dates .= date('T');break;
|
||||
// YEAR
|
||||
case 'L': $dates .= $arr['leap'] ? '1' : '0'; break;
|
||||
case 'r': // Thu, 21 Dec 2000 16:01:07 +0200
|
||||
|
||||
// 4.3.11 uses '04 Jun 2004'
|
||||
// 4.3.8 uses ' 4 Jun 2004'
|
||||
$dates .= gmdate('D',$_day_power*(3+self::getDayOfWeek($year,$month,$day))).', '
|
||||
. ($day<10?'0'.$day:$day) . ' '.date('M',mktime(0,0,0,$month,2,1971)).' '.$year.' ';
|
||||
|
||||
if ($hour < 10) $dates .= '0'.$hour; else $dates .= $hour;
|
||||
|
||||
if ($min < 10) $dates .= ':0'.$min; else $dates .= ':'.$min;
|
||||
|
||||
if ($secs < 10) $dates .= ':0'.$secs; else $dates .= ':'.$secs;
|
||||
|
||||
$gmt = self::getGMTDiff();
|
||||
$dates .= sprintf(' %s%04d',($gmt<=0)?'+':'-',abs($gmt)/36);
|
||||
break;
|
||||
|
||||
case 'Y': $dates .= $year; break;
|
||||
case 'y': $dates .= substr($year,strlen($year)-2,2); break;
|
||||
// MONTH
|
||||
case 'm': if ($month<10) $dates .= '0'.$month; else $dates .= $month; break;
|
||||
case 'Q': $dates .= ($month+3)>>2; break;
|
||||
case 'n': $dates .= $month; break;
|
||||
case 'M': $dates .= date('M',mktime(0,0,0,$month,2,1971)); break;
|
||||
case 'F': $dates .= date('F',mktime(0,0,0,$month,2,1971)); break;
|
||||
// DAY
|
||||
case 't': $dates .= $arr['ndays']; break;
|
||||
case 'z': $dates .= $arr['yday']; break;
|
||||
case 'w': $dates .= self::getDayOfWeek($year,$month,$day); break;
|
||||
case 'l': $dates .= gmdate('l',$_day_power*(3+self::getDayOfWeek($year,$month,$day))); break;
|
||||
case 'D': $dates .= gmdate('D',$_day_power*(3+self::getDayOfWeek($year,$month,$day))); break;
|
||||
case 'j': $dates .= $day; break;
|
||||
case 'd': if ($day<10) $dates .= '0'.$day; else $dates .= $day; break;
|
||||
case 'S':
|
||||
$d10 = $day % 10;
|
||||
if ($d10 == 1) $dates .= 'st';
|
||||
elseif ($d10 == 2 && $day != 12) $dates .= 'nd';
|
||||
elseif ($d10 == 3) $dates .= 'rd';
|
||||
else $dates .= 'th';
|
||||
break;
|
||||
|
||||
// HOUR
|
||||
case 'Z':
|
||||
$dates .= ($is_gmt) ? 0 : -self::getGMTDiff(); break;
|
||||
case 'O':
|
||||
$gmt = ($is_gmt) ? 0 : self::getGMTDiff();
|
||||
|
||||
$dates .= sprintf('%s%04d',($gmt<=0)?'+':'-',abs($gmt)/36);
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
if ($hour < 10) $dates .= '0'.$hour;
|
||||
else $dates .= $hour;
|
||||
break;
|
||||
case 'h':
|
||||
if ($hour > 12) $hh = $hour - 12;
|
||||
else {
|
||||
if ($hour == 0) $hh = '12';
|
||||
else $hh = $hour;
|
||||
}
|
||||
|
||||
if ($hh < 10) $dates .= '0'.$hh;
|
||||
else $dates .= $hh;
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
$dates .= $hour;
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
if ($hour > 12) $hh = $hour - 12;
|
||||
else {
|
||||
if ($hour == 0) $hh = '12';
|
||||
else $hh = $hour;
|
||||
}
|
||||
$dates .= $hh;
|
||||
break;
|
||||
// MINUTES
|
||||
case 'i': if ($min < 10) $dates .= '0'.$min; else $dates .= $min; break;
|
||||
// SECONDS
|
||||
case 'U': $dates .= $d; break;
|
||||
case 's': if ($secs < 10) $dates .= '0'.$secs; else $dates .= $secs; break;
|
||||
// AM/PM
|
||||
// Note 00:00 to 11:59 is AM, while 12:00 to 23:59 is PM
|
||||
case 'a':
|
||||
if ($hour>=12) $dates .= 'pm';
|
||||
else $dates .= 'am';
|
||||
break;
|
||||
case 'A':
|
||||
if ($hour>=12) $dates .= 'PM';
|
||||
else $dates .= 'AM';
|
||||
break;
|
||||
default:
|
||||
$dates .= $fmt[$i]; break;
|
||||
// ESCAPE
|
||||
case "\\":
|
||||
$i++;
|
||||
if ($i < $max) $dates .= $fmt[$i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $dates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a timestamp.
|
||||
* This is the same as the PHP function {@link mktime http://php.net/manual/en/function.mktime.php}.
|
||||
* @param integer $hr hour
|
||||
* @param integer $min minute
|
||||
* @param integer $sec second
|
||||
* @param integer|boolean $mon month
|
||||
* @param integer|boolean $day day
|
||||
* @param integer|boolean $year year
|
||||
* @param boolean $is_gmt whether this is GMT time. If true, gmmktime() will be used.
|
||||
* @return integer|float a timestamp given a local time.
|
||||
*/
|
||||
public static function getTimestamp($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_gmt=false)
|
||||
{
|
||||
if ($mon === false)
|
||||
return $is_gmt? @gmmktime($hr,$min,$sec): @mktime($hr,$min,$sec);
|
||||
return $is_gmt ? @gmmktime($hr,$min,$sec,$mon,$day,$year) : @mktime($hr,$min,$sec,$mon,$day,$year);
|
||||
}
|
||||
}
|
||||
140
framework/utils/CVarDumper.php
Normal file
140
framework/utils/CVarDumper.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
/**
|
||||
* CVarDumper class file.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright 2008-2013 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
/**
|
||||
* CVarDumper is intended to replace the buggy PHP function var_dump and print_r.
|
||||
* It can correctly identify the recursively referenced objects in a complex
|
||||
* object structure. It also has a recursive depth control to avoid indefinite
|
||||
* recursive display of some peculiar variables.
|
||||
*
|
||||
* CVarDumper can be used as follows,
|
||||
* <pre>
|
||||
* CVarDumper::dump($var);
|
||||
* </pre>
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @package system.utils
|
||||
* @since 1.0
|
||||
*/
|
||||
class CVarDumper
|
||||
{
|
||||
private static $_objects;
|
||||
private static $_output;
|
||||
private static $_depth;
|
||||
|
||||
/**
|
||||
* Displays a variable.
|
||||
* This method achieves the similar functionality as var_dump and print_r
|
||||
* but is more robust when handling complex objects such as Yii controllers.
|
||||
* @param mixed $var variable to be dumped
|
||||
* @param integer $depth maximum depth that the dumper should go into the variable. Defaults to 10.
|
||||
* @param boolean $highlight whether the result should be syntax-highlighted
|
||||
*/
|
||||
public static function dump($var,$depth=10,$highlight=false)
|
||||
{
|
||||
echo self::dumpAsString($var,$depth,$highlight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps a variable in terms of a string.
|
||||
* This method achieves the similar functionality as var_dump and print_r
|
||||
* but is more robust when handling complex objects such as Yii controllers.
|
||||
* @param mixed $var variable to be dumped
|
||||
* @param integer $depth maximum depth that the dumper should go into the variable. Defaults to 10.
|
||||
* @param boolean $highlight whether the result should be syntax-highlighted
|
||||
* @return string the string representation of the variable
|
||||
*/
|
||||
public static function dumpAsString($var,$depth=10,$highlight=false)
|
||||
{
|
||||
self::$_output='';
|
||||
self::$_objects=array();
|
||||
self::$_depth=$depth;
|
||||
self::dumpInternal($var,0);
|
||||
if($highlight)
|
||||
{
|
||||
$result=highlight_string("<?php\n".self::$_output,true);
|
||||
self::$_output=preg_replace('/<\\?php<br \\/>/','',$result,1);
|
||||
}
|
||||
return self::$_output;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param mixed $var variable to be dumped
|
||||
* @param integer $level depth level
|
||||
*/
|
||||
private static function dumpInternal($var,$level)
|
||||
{
|
||||
switch(gettype($var))
|
||||
{
|
||||
case 'boolean':
|
||||
self::$_output.=$var?'true':'false';
|
||||
break;
|
||||
case 'integer':
|
||||
self::$_output.="$var";
|
||||
break;
|
||||
case 'double':
|
||||
self::$_output.="$var";
|
||||
break;
|
||||
case 'string':
|
||||
self::$_output.="'".addslashes($var)."'";
|
||||
break;
|
||||
case 'resource':
|
||||
self::$_output.='{resource}';
|
||||
break;
|
||||
case 'NULL':
|
||||
self::$_output.="null";
|
||||
break;
|
||||
case 'unknown type':
|
||||
self::$_output.='{unknown}';
|
||||
break;
|
||||
case 'array':
|
||||
if(self::$_depth<=$level)
|
||||
self::$_output.='array(...)';
|
||||
elseif(empty($var))
|
||||
self::$_output.='array()';
|
||||
else
|
||||
{
|
||||
$keys=array_keys($var);
|
||||
$spaces=str_repeat(' ',$level*4);
|
||||
self::$_output.="array\n".$spaces.'(';
|
||||
foreach($keys as $key)
|
||||
{
|
||||
self::$_output.="\n".$spaces.' ';
|
||||
self::dumpInternal($key,0);
|
||||
self::$_output.=' => ';
|
||||
self::dumpInternal($var[$key],$level+1);
|
||||
}
|
||||
self::$_output.="\n".$spaces.')';
|
||||
}
|
||||
break;
|
||||
case 'object':
|
||||
if(($id=array_search($var,self::$_objects,true))!==false)
|
||||
self::$_output.=get_class($var).'#'.($id+1).'(...)';
|
||||
elseif(self::$_depth<=$level)
|
||||
self::$_output.=get_class($var).'(...)';
|
||||
else
|
||||
{
|
||||
$id=array_push(self::$_objects,$var);
|
||||
$className=get_class($var);
|
||||
$members=(array)$var;
|
||||
$spaces=str_repeat(' ',$level*4);
|
||||
self::$_output.="$className#$id\n".$spaces.'(';
|
||||
foreach($members as $key=>$value)
|
||||
{
|
||||
$keyDisplay=strtr(trim($key),array("\0"=>':'));
|
||||
self::$_output.="\n".$spaces." [$keyDisplay] => ";
|
||||
self::$_output.=self::dumpInternal($value,$level+1);
|
||||
}
|
||||
self::$_output.="\n".$spaces.')';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
188
framework/utils/mimeTypes.php
Normal file
188
framework/utils/mimeTypes.php
Normal file
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
/**
|
||||
* MIME types.
|
||||
*
|
||||
* This file contains most commonly used MIME types
|
||||
* according to file extension names.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright 2008-2013 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
return array(
|
||||
'ai'=>'application/postscript',
|
||||
'aif'=>'audio/x-aiff',
|
||||
'aifc'=>'audio/x-aiff',
|
||||
'aiff'=>'audio/x-aiff',
|
||||
'anx'=>'application/annodex',
|
||||
'asc'=>'text/plain',
|
||||
'au'=>'audio/basic',
|
||||
'avi'=>'video/x-msvideo',
|
||||
'axa'=>'audio/annodex',
|
||||
'axv'=>'video/annodex',
|
||||
'bcpio'=>'application/x-bcpio',
|
||||
'bin'=>'application/octet-stream',
|
||||
'bmp'=>'image/bmp',
|
||||
'c'=>'text/plain',
|
||||
'cc'=>'text/plain',
|
||||
'ccad'=>'application/clariscad',
|
||||
'cdf'=>'application/x-netcdf',
|
||||
'class'=>'application/octet-stream',
|
||||
'cpio'=>'application/x-cpio',
|
||||
'cpt'=>'application/mac-compactpro',
|
||||
'csh'=>'application/x-csh',
|
||||
'css'=>'text/css',
|
||||
'csv'=>'text/csv',
|
||||
'dcr'=>'application/x-director',
|
||||
'dir'=>'application/x-director',
|
||||
'dms'=>'application/octet-stream',
|
||||
'doc'=>'application/msword',
|
||||
'drw'=>'application/drafting',
|
||||
'dvi'=>'application/x-dvi',
|
||||
'dwg'=>'application/acad',
|
||||
'dxf'=>'application/dxf',
|
||||
'dxr'=>'application/x-director',
|
||||
'eps'=>'application/postscript',
|
||||
'etx'=>'text/x-setext',
|
||||
'exe'=>'application/octet-stream',
|
||||
'ez'=>'application/andrew-inset',
|
||||
'f'=>'text/plain',
|
||||
'f90'=>'text/plain',
|
||||
'flac'=>'audio/flac',
|
||||
'fli'=>'video/x-fli',
|
||||
'flv'=>'video/x-flv',
|
||||
'gif'=>'image/gif',
|
||||
'gtar'=>'application/x-gtar',
|
||||
'gz'=>'application/x-gzip',
|
||||
'h'=>'text/plain',
|
||||
'hdf'=>'application/x-hdf',
|
||||
'hh'=>'text/plain',
|
||||
'hqx'=>'application/mac-binhex40',
|
||||
'htm'=>'text/html',
|
||||
'html'=>'text/html',
|
||||
'ice'=>'x-conference/x-cooltalk',
|
||||
'ief'=>'image/ief',
|
||||
'iges'=>'model/iges',
|
||||
'igs'=>'model/iges',
|
||||
'ips'=>'application/x-ipscript',
|
||||
'ipx'=>'application/x-ipix',
|
||||
'jpe'=>'image/jpeg',
|
||||
'jpeg'=>'image/jpeg',
|
||||
'jpg'=>'image/jpeg',
|
||||
'js'=>'application/x-javascript',
|
||||
'kar'=>'audio/midi',
|
||||
'latex'=>'application/x-latex',
|
||||
'lha'=>'application/octet-stream',
|
||||
'lsp'=>'application/x-lisp',
|
||||
'lzh'=>'application/octet-stream',
|
||||
'm'=>'text/plain',
|
||||
'man'=>'application/x-troff-man',
|
||||
'me'=>'application/x-troff-me',
|
||||
'mesh'=>'model/mesh',
|
||||
'mid'=>'audio/midi',
|
||||
'midi'=>'audio/midi',
|
||||
'mif'=>'application/vnd.mif',
|
||||
'mime'=>'www/mime',
|
||||
'mov'=>'video/quicktime',
|
||||
'movie'=>'video/x-sgi-movie',
|
||||
'mp2'=>'audio/mpeg',
|
||||
'mp3'=>'audio/mpeg',
|
||||
'mpe'=>'video/mpeg',
|
||||
'mpeg'=>'video/mpeg',
|
||||
'mpg'=>'video/mpeg',
|
||||
'mpga'=>'audio/mpeg',
|
||||
'ms'=>'application/x-troff-ms',
|
||||
'msh'=>'model/mesh',
|
||||
'nc'=>'application/x-netcdf',
|
||||
'oga'=>'audio/ogg',
|
||||
'ogg'=>'audio/ogg',
|
||||
'ogv'=>'video/ogg',
|
||||
'ogx'=>'application/ogg',
|
||||
'oda'=>'application/oda',
|
||||
'pbm'=>'image/x-portable-bitmap',
|
||||
'pdb'=>'chemical/x-pdb',
|
||||
'pdf'=>'application/pdf',
|
||||
'pgm'=>'image/x-portable-graymap',
|
||||
'pgn'=>'application/x-chess-pgn',
|
||||
'png'=>'image/png',
|
||||
'pnm'=>'image/x-portable-anymap',
|
||||
'pot'=>'application/mspowerpoint',
|
||||
'ppm'=>'image/x-portable-pixmap',
|
||||
'pps'=>'application/mspowerpoint',
|
||||
'ppt'=>'application/mspowerpoint',
|
||||
'ppz'=>'application/mspowerpoint',
|
||||
'pre'=>'application/x-freelance',
|
||||
'prt'=>'application/pro_eng',
|
||||
'ps'=>'application/postscript',
|
||||
'qt'=>'video/quicktime',
|
||||
'ra'=>'audio/x-realaudio',
|
||||
'ram'=>'audio/x-pn-realaudio',
|
||||
'ras'=>'image/cmu-raster',
|
||||
'rgb'=>'image/x-rgb',
|
||||
'rm'=>'audio/x-pn-realaudio',
|
||||
'roff'=>'application/x-troff',
|
||||
'rpm'=>'audio/x-pn-realaudio-plugin',
|
||||
'rtf'=>'text/rtf',
|
||||
'rtx'=>'text/richtext',
|
||||
'scm'=>'application/x-lotusscreencam',
|
||||
'set'=>'application/set',
|
||||
'sgm'=>'text/sgml',
|
||||
'sgml'=>'text/sgml',
|
||||
'sh'=>'application/x-sh',
|
||||
'shar'=>'application/x-shar',
|
||||
'silo'=>'model/mesh',
|
||||
'sit'=>'application/x-stuffit',
|
||||
'skd'=>'application/x-koan',
|
||||
'skm'=>'application/x-koan',
|
||||
'skp'=>'application/x-koan',
|
||||
'skt'=>'application/x-koan',
|
||||
'smi'=>'application/smil',
|
||||
'smil'=>'application/smil',
|
||||
'snd'=>'audio/basic',
|
||||
'sol'=>'application/solids',
|
||||
'spl'=>'application/x-futuresplash',
|
||||
'spx'=>'audio/ogg',
|
||||
'src'=>'application/x-wais-source',
|
||||
'step'=>'application/STEP',
|
||||
'stl'=>'application/SLA',
|
||||
'stp'=>'application/STEP',
|
||||
'sv4cpio'=>'application/x-sv4cpio',
|
||||
'sv4crc'=>'application/x-sv4crc',
|
||||
'swf'=>'application/x-shockwave-flash',
|
||||
't'=>'application/x-troff',
|
||||
'tar'=>'application/x-tar',
|
||||
'tcl'=>'application/x-tcl',
|
||||
'tex'=>'application/x-tex',
|
||||
'texi'=>'application/x-texinfo',
|
||||
'texinfo'=>'application/x-texinfo',
|
||||
'tif'=>'image/tiff',
|
||||
'tiff'=>'image/tiff',
|
||||
'tr'=>'application/x-troff',
|
||||
'tsi'=>'audio/TSP-audio',
|
||||
'tsp'=>'application/dsptype',
|
||||
'tsv'=>'text/tab-separated-values',
|
||||
'txt'=>'text/plain',
|
||||
'unv'=>'application/i-deas',
|
||||
'ustar'=>'application/x-ustar',
|
||||
'vcd'=>'application/x-cdlink',
|
||||
'vda'=>'application/vda',
|
||||
'viv'=>'video/vnd.vivo',
|
||||
'vivo'=>'video/vnd.vivo',
|
||||
'vrml'=>'model/vrml',
|
||||
'wav'=>'audio/x-wav',
|
||||
'wrl'=>'model/vrml',
|
||||
'xbm'=>'image/x-xbitmap',
|
||||
'xlc'=>'application/vnd.ms-excel',
|
||||
'xll'=>'application/vnd.ms-excel',
|
||||
'xlm'=>'application/vnd.ms-excel',
|
||||
'xls'=>'application/vnd.ms-excel',
|
||||
'xlw'=>'application/vnd.ms-excel',
|
||||
'xml'=>'application/xml',
|
||||
'xpm'=>'image/x-xpixmap',
|
||||
'xspf'=>'application/xspf+xml',
|
||||
'xwd'=>'image/x-xwindowdump',
|
||||
'xyz'=>'chemical/x-pdb',
|
||||
'zip'=>'application/zip',
|
||||
);
|
||||
Reference in New Issue
Block a user