diff options
Diffstat (limited to 'framework/utils')
| -rw-r--r-- | framework/utils/CDateTimeParser.php | 277 | ||||
| -rw-r--r-- | framework/utils/CFileHelper.php | 261 | ||||
| -rw-r--r-- | framework/utils/CFormatter.php | 247 | ||||
| -rw-r--r-- | framework/utils/CMarkdownParser.php | 195 | ||||
| -rw-r--r-- | framework/utils/CPropertyValue.php | 158 | ||||
| -rw-r--r-- | framework/utils/CTimestamp.php | 377 | ||||
| -rw-r--r-- | framework/utils/CVarDumper.php | 140 | ||||
| -rw-r--r-- | framework/utils/mimeTypes.php | 178 |
8 files changed, 1833 insertions, 0 deletions
diff --git a/framework/utils/CDateTimeParser.php b/framework/utils/CDateTimeParser.php new file mode 100644 index 0000000..2f09f93 --- /dev/null +++ b/framework/utils/CDateTimeParser.php @@ -0,0 +1,277 @@ +<?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 Copyright © 2008-2011 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 + * 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) + * ---------------------------------------------------- + * </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> + * + * 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> + * @version $Id: CDateTimeParser.php 2928 2011-02-01 17:41:51Z alexander.makarow $ + * @package system.utils + * @since 1.0 + */ +class CDateTimeParser +{ + /** + * 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()) + { + $tokens=self::tokenize($pattern); + $i=0; + $n=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 '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; + else if($hour<12 && $ampm==='pm') + $hour+=12; + } + $i+=2; + break; + } + default: + { + $tn=strlen($token); + if($i>=$n || 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=strlen($pattern))) + return array(); + $tokens=array(); + for($c0=$pattern[0],$start=0,$i=1;$i<$n;++$i) + { + if(($c=$pattern[$i])!==$c0) + { + $tokens[]=substr($pattern,$start,$i-$start); + $c0=$c; + $start=$i; + } + } + $tokens[]=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 + */ + protected static function parseInteger($value,$offset,$minLength,$maxLength) + { + for($len=$maxLength;$len>=$minLength;--$len) + { + $v=substr($value,$offset,$len); + if(ctype_digit($v) && strlen($v)>=$minLength) + return $v; + } + return false; + } + + /* + * @param string $value the date string to be parsed + * @param integer $offset starting offset + */ + protected static function parseAmPm($value, $offset) + { + $v=strtolower(substr($value,$offset,2)); + return $v==='am' || $v==='pm' ? $v : false; + } +} diff --git a/framework/utils/CFileHelper.php b/framework/utils/CFileHelper.php new file mode 100644 index 0000000..4a1f1de --- /dev/null +++ b/framework/utils/CFileHelper.php @@ -0,0 +1,261 @@ +<?php +/** + * CFileHelper class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 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> + * @version $Id: CFileHelper.php 3289 2011-06-18 21:20:13Z qiang.xue $ + * @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. + * @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> + * </ul> + */ + public static function copyDirectory($src,$dst,$options=array()) + { + $fileTypes=array(); + $exclude=array(); + $level=-1; + extract($options); + self::copyDirectoryRecursive($src,$dst,'',$fileTypes,$exclude,$level,$options); + } + + /** + * 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)) + mkdir($dst); + if(isset($options['newDirMode'])) + @chmod($dst,$options['newDirMode']); + else + @chmod($dst,0777); + $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']); + } + else if($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; + else if($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 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. + * @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}. + * 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 mim_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; + if($extensions===null) + $extensions=$magicFile===null ? require(Yii::getPathOfAlias('system.utils.mimeTypes').'.php') : $magicFile; + if(($ext=pathinfo($file, PATHINFO_EXTENSION))!=='') + { + $ext=strtolower($ext); + if(isset($extensions[$ext])) + return $extensions[$ext]; + } + return null; + } +} diff --git a/framework/utils/CFormatter.php b/framework/utils/CFormatter.php new file mode 100644 index 0000000..277814a --- /dev/null +++ b/framework/utils/CFormatter.php @@ -0,0 +1,247 @@ +<?php +/** + * CFormatter class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 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 /> 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> + * </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>. + * + * @property CHtmlPurifier $htmlPurifier The HTML purifier instance. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CFormatter.php 3553 2012-02-06 22:07:58Z alexander.makarow $ + * @package system.utils + * @since 1.1.0 + */ +class CFormatter extends CApplicationComponent +{ + 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'); + + /** + * 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}. + * @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 tags. + * @param mixed $value the value to be formatted + * @return string the formatted result + */ + public function formatNtext($value) + { + return nl2br(CHtml::encode($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,$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,$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,$value); + } + + /** + * 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; + return $this->_htmlPurifier; + } +} diff --git a/framework/utils/CMarkdownParser.php b/framework/utils/CMarkdownParser.php new file mode 100644 index 0000000..bbdc9bc --- /dev/null +++ b/framework/utils/CMarkdownParser.php @@ -0,0 +1,195 @@ +<?php +/** + * CMarkdownParser class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 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> + * @version $Id: CMarkdownParser.php 3515 2011-12-28 12:29:24Z mdomba $ + * @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->getHiglightConfig($options))); + return $highlighter; + } + + /** + * Generates the config for the highlighter. + * @param string $options user-entered options + * @return array the highlighter config + */ + public function getHiglightConfig($options) + { + $config['use_language'] = true; + if( $this->getInlineOption('showLineNumbers', $options, false) ) + $config['numbers'] = HL_NUMBERS_LI; + $config['tabsize'] = $this->getInlineOption('tabSize', $options, 4); + return $config; + } + + /** + * 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; + } +} diff --git a/framework/utils/CPropertyValue.php b/framework/utils/CPropertyValue.php new file mode 100644 index 0000000..03e9ba2 --- /dev/null +++ b/framework/utils/CPropertyValue.php @@ -0,0 +1,158 @@ +<?php +/** + * CPropertyValue class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 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> + * @version $Id: CPropertyValue.php 2799 2011-01-01 19:31:13Z qiang.xue $ + * @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())))); + } +} diff --git a/framework/utils/CTimestamp.php b/framework/utils/CTimestamp.php new file mode 100644 index 0000000..d8f12ae --- /dev/null +++ b/framework/utils/CTimestamp.php @@ -0,0 +1,377 @@ +<?php +/** + * CTimestamp class file. + * + * @author Wei Zhuo <weizhuo[at]gamil[dot]com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 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> + * @version $Id: CTimestamp.php 3515 2011-12-28 12:29:24Z mdomba $ + * @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 + else if ($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'; + else if ($d10 == 2 && $day != 12) $dates .= 'nd'; + else if ($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); + } +} diff --git a/framework/utils/CVarDumper.php b/framework/utils/CVarDumper.php new file mode 100644 index 0000000..c9b0d18 --- /dev/null +++ b/framework/utils/CVarDumper.php @@ -0,0 +1,140 @@ +<?php +/** + * CVarDumper class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 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> + * @version $Id: CVarDumper.php 2799 2011-01-01 19:31:13Z qiang.xue $ + * @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(...)'; + else if(empty($var)) + self::$_output.='array()'; + else + { + $keys=array_keys($var); + $spaces=str_repeat(' ',$level*4); + self::$_output.="array\n".$spaces.'('; + foreach($keys as $key) + { + $key2=str_replace("'","\\'",$key); + self::$_output.="\n".$spaces." '$key2' => "; + 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).'(...)'; + else if(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; + } + } +} diff --git a/framework/utils/mimeTypes.php b/framework/utils/mimeTypes.php new file mode 100644 index 0000000..c077c02 --- /dev/null +++ b/framework/utils/mimeTypes.php @@ -0,0 +1,178 @@ +<?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 Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + * @version $Id: mimeTypes.php 3181 2011-04-15 01:26:52Z alexander.makarow $ + */ + +return array( + 'ai'=>'application/postscript', + 'aif'=>'audio/x-aiff', + 'aifc'=>'audio/x-aiff', + 'aiff'=>'audio/x-aiff', + 'asc'=>'text/plain', + 'au'=>'audio/basic', + 'avi'=>'video/x-msvideo', + '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', + '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', + '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', + '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', + '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', + 'xwd'=>'image/x-xwindowdump', + 'xyz'=>'chemical/x-pdb', + 'zip'=>'application/zip', +); |
