From 72ff81f73dc264a35517905feb803c5ddc60b957 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sat, 1 Sep 2012 22:42:43 -0400 Subject: [PATCH] Web WIP --- framework/base/Component.php | 4 +- framework/util/FileHelper.php | 47 ++++ framework/util/mimeTypes.php | 187 +++++++++++++ framework/web/Cookie.php | 39 ++- framework/web/Pagination.php | 79 +++--- framework/web/Request.php | 638 ++++++++++++++++++++---------------------- framework/web/Response.php | 144 ++++++++++ framework/web/Sort.php | 253 +++++++++-------- 8 files changed, 881 insertions(+), 510 deletions(-) create mode 100644 framework/util/mimeTypes.php create mode 100644 framework/web/Response.php diff --git a/framework/base/Component.php b/framework/base/Component.php index f3f2f73..b4d379e 100644 --- a/framework/base/Component.php +++ b/framework/base/Component.php @@ -308,7 +308,7 @@ class Component extends \yii\base\Object * where `$event` is an [[Event]] object which includes parameters associated with the event. * * @param string $name the event name - * @param callback $handler the event handler + * @param string|array|\Closure $handler the event handler * @see off */ public function on($name, $handler) @@ -320,7 +320,7 @@ class Component extends \yii\base\Object * Detaches an existing event handler. * This method is the opposite of [[on]]. * @param string $name event name - * @param callback $handler the event handler to be removed + * @param string|array|\Closure $handler the event handler to be removed * @return boolean if a handler is found and detached * @see on */ diff --git a/framework/util/FileHelper.php b/framework/util/FileHelper.php index 7b15089..faabbed 100644 --- a/framework/util/FileHelper.php +++ b/framework/util/FileHelper.php @@ -87,4 +87,51 @@ class FileHelper $desiredFile = dirname($file) . DIRECTORY_SEPARATOR . $sourceLanguage . DIRECTORY_SEPARATOR . basename($file); return is_file($desiredFile) ? $desiredFile : $file; } + + /** + * Determines the MIME type of the specified file. + * This method will first try to determine the MIME type based on + * [finfo_open](http://php.net/manual/en/function.finfo-open.php). If this doesn't work, it will + * fall back to [[getMimeTypeByExtension()]]. + * @param string $file the file name. + * @param string $magicFile name of the optional magic database file, usually something like `/path/to/magic.mime`. + * This will be passed as the second parameter to [finfo_open](http://php.net/manual/en/function.finfo-open.php). + * @param boolean $checkExtension whether to use the file extension to determine the MIME type in case + * `finfo_open()` cannot determine it. + * @return string the MIME type (e.g. `text/plain`). Null is returned if the MIME type cannot be determined. + */ + public static function getMimeType($file, $magicFile = null, $checkExtension = true) + { + if (function_exists('finfo_open')) { + $info = finfo_open(FILEINFO_MIME_TYPE, $magicFile); + if ($info && ($result = finfo_file($info, $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 names and MIME types. + * @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 file aliased by `@yii/util/mimeTypes.php` will be used. + * @return string the MIME type. Null is returned if the MIME type cannot be determined. + */ + public static function getMimeTypeByExtension($file, $magicFile = null) + { + if ($magicFile === null) { + $magicFile = \Yii::getAlias('@yii/util/mimeTypes.php'); + } + $mimeTypes = require($magicFile); + if (($ext = pathinfo($file, PATHINFO_EXTENSION)) !== '') { + $ext = strtolower($ext); + if (isset($mimeTypes[$ext])) { + return $mimeTypes[$ext]; + } + } + return null; + } } diff --git a/framework/util/mimeTypes.php b/framework/util/mimeTypes.php new file mode 100644 index 0000000..be4bb3a --- /dev/null +++ b/framework/util/mimeTypes.php @@ -0,0 +1,187 @@ + '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', + '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', +); diff --git a/framework/web/Cookie.php b/framework/web/Cookie.php index abb0e00..f48a34f 100644 --- a/framework/web/Cookie.php +++ b/framework/web/Cookie.php @@ -1,22 +1,19 @@ * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2011 Yii Software LLC + * @copyright Copyright © 2008-2012 Yii Software LLC * @license http://www.yiiframework.com/license/ */ /** - * A CHttpCookie instance stores a single cookie, including the cookie name, value, domain, path, expire, and secure. + * Cookie represents information related with a cookie, such as [[name]], [[value]], [[domain]], etc. * * @author Qiang Xue - * @version $Id$ - * @package system.web - * @since 1.0 + * @since 2.0 */ -class CHttpCookie extends CComponent +class Cookie extends \yii\base\Object { /** * @var string name of the cookie @@ -25,39 +22,41 @@ class CHttpCookie extends CComponent /** * @var string value of the cookie */ - public $value=''; + public $value = ''; /** * @var string domain of the cookie */ - public $domain=''; + public $domain = ''; /** - * @var integer the timestamp at which the cookie expires. This is the server timestamp. Defaults to 0, meaning "until the browser is closed". + * @var integer the timestamp at which the cookie expires. This is the server timestamp. + * Defaults to 0, meaning "until the browser is closed". */ - public $expire=0; + public $expire = 0; /** * @var string the path on the server in which the cookie will be available on. The default is '/'. */ - public $path='/'; + public $path = '/'; /** * @var boolean whether cookie should be sent via secure connection */ - public $secure=false; + public $secure = false; /** * @var boolean whether the cookie should be accessible only through the HTTP protocol. * By setting this property to true, the cookie will not be accessible by scripting languages, - * such as JavaScript, which can effectly help to reduce identity theft through XSS attacks. - * Note, this property is only effective for PHP 5.2.0 or above. + * such as JavaScript, which can effectively help to reduce identity theft through XSS attacks. */ - public $httpOnly=false; + public $httpOnly = false; /** * Constructor. * @param string $name name of this cookie * @param string $value value of this cookie + * @param array $config name-value pairs that will be used to initialize the object properties */ - public function __construct($name,$value) + public function __construct($name, $value, $config = array()) { - $this->name=$name; - $this->value=$value; + $this->name = $name; + $this->value = $value; + parent::__construct($config); } } diff --git a/framework/web/Pagination.php b/framework/web/Pagination.php index 7a05b73..26d670e 100644 --- a/framework/web/Pagination.php +++ b/framework/web/Pagination.php @@ -70,16 +70,16 @@ class CPagination extends CComponent /** * The default page size. */ - const DEFAULT_PAGE_SIZE=10; + const DEFAULT_PAGE_SIZE = 10; /** * @var string name of the GET variable storing the current page index. Defaults to 'page'. */ - public $pageVar='page'; + public $pageVar = 'page'; /** * @var string the route (controller ID and action ID) for displaying the paged contents. * Defaults to empty string, meaning using the current route. */ - public $route=''; + public $route = ''; /** * @var array of parameters (name=>value) that should be used instead of GET when generating pagination URLs. * Defaults to null, meaning using the currently available GET parameters. @@ -95,17 +95,17 @@ class CPagination extends CComponent * Defaults to true. * @since 1.1.4 */ - public $validateCurrentPage=true; + public $validateCurrentPage = true; - private $_pageSize=self::DEFAULT_PAGE_SIZE; - private $_itemCount=0; + private $_pageSize = self::DEFAULT_PAGE_SIZE; + private $_itemCount = 0; private $_currentPage; /** * Constructor. * @param integer $itemCount total number of items. */ - public function __construct($itemCount=0) + public function __construct($itemCount = 0) { $this->setItemCount($itemCount); } @@ -123,8 +123,9 @@ class CPagination extends CComponent */ public function setPageSize($value) { - if(($this->_pageSize=$value)<=0) - $this->_pageSize=self::DEFAULT_PAGE_SIZE; + if (($this->_pageSize = $value) <= 0) { + $this->_pageSize = self::DEFAULT_PAGE_SIZE; + } } /** @@ -140,8 +141,9 @@ class CPagination extends CComponent */ public function setItemCount($value) { - if(($this->_itemCount=$value)<0) - $this->_itemCount=0; + if (($this->_itemCount = $value) < 0) { + $this->_itemCount = 0; + } } /** @@ -149,31 +151,30 @@ class CPagination extends CComponent */ public function getPageCount() { - return (int)(($this->_itemCount+$this->_pageSize-1)/$this->_pageSize); + return (int)(($this->_itemCount + $this->_pageSize - 1) / $this->_pageSize); } /** * @param boolean $recalculate whether to recalculate the current page based on the page size and item count. * @return integer the zero-based index of the current page. Defaults to 0. */ - public function getCurrentPage($recalculate=true) + public function getCurrentPage($recalculate = true) { - if($this->_currentPage===null || $recalculate) - { - if(isset($_GET[$this->pageVar])) - { - $this->_currentPage=(int)$_GET[$this->pageVar]-1; - if($this->validateCurrentPage) - { - $pageCount=$this->getPageCount(); - if($this->_currentPage>=$pageCount) - $this->_currentPage=$pageCount-1; + if ($this->_currentPage === null || $recalculate) { + if (isset($_GET[$this->pageVar])) { + $this->_currentPage = (int)$_GET[$this->pageVar] - 1; + if ($this->validateCurrentPage) { + $pageCount = $this->getPageCount(); + if ($this->_currentPage >= $pageCount) { + $this->_currentPage = $pageCount - 1; + } } - if($this->_currentPage<0) - $this->_currentPage=0; + if ($this->_currentPage < 0) { + $this->_currentPage = 0; + } + } else { + $this->_currentPage = 0; } - else - $this->_currentPage=0; } return $this->_currentPage; } @@ -183,8 +184,8 @@ class CPagination extends CComponent */ public function setCurrentPage($value) { - $this->_currentPage=$value; - $_GET[$this->pageVar]=$value+1; + $this->_currentPage = $value; + $_GET[$this->pageVar] = $value + 1; } /** @@ -198,14 +199,16 @@ class CPagination extends CComponent * @param integer $page the page that the URL should point to. This is a zero-based index. * @return string the created URL */ - public function createPageUrl($controller,$page) + public function createPageUrl($controller, $page) { - $params=$this->params===null ? $_GET : $this->params; - if($page>0) // page 0 is the default - $params[$this->pageVar]=$page+1; - else + $params = $this->params === null ? $_GET : $this->params; + if ($page > 0) // page 0 is the default + { + $params[$this->pageVar] = $page + 1; + } else { unset($params[$this->pageVar]); - return $controller->createUrl($this->route,$params); + } + return $controller->createUrl($this->route, $params); } /** @@ -214,8 +217,8 @@ class CPagination extends CComponent */ public function applyLimit($criteria) { - $criteria->limit=$this->getLimit(); - $criteria->offset=$this->getOffset(); + $criteria->limit = $this->getLimit(); + $criteria->offset = $this->getOffset(); } /** @@ -225,7 +228,7 @@ class CPagination extends CComponent */ public function getOffset() { - return $this->getCurrentPage()*$this->getPageSize(); + return $this->getCurrentPage() * $this->getPageSize(); } /** diff --git a/framework/web/Request.php b/framework/web/Request.php index 08bc202..e1ed9d1 100644 --- a/framework/web/Request.php +++ b/framework/web/Request.php @@ -1,69 +1,24 @@ * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2011 Yii Software LLC + * @copyright Copyright © 2008-2012 Yii Software LLC * @license http://www.yiiframework.com/license/ */ +namespace yii\web; /** - * CHttpRequest encapsulates the $_SERVER variable and resolves its inconsistency among different Web servers. - * - * CHttpRequest also manages the cookies sent from and sent to the user. - * By setting {@link enableCookieValidation} to true, - * cookies sent from the user will be validated to see if they are tampered. - * The property {@link getCookies cookies} returns the collection of cookies. - * For more details, see {@link CCookieCollection}. - * - * CHttpRequest is a default application component loaded by {@link CWebApplication}. It can be - * accessed via {@link CWebApplication::getRequest()}. - * - * @property string $url Part of the request URL after the host info. - * @property string $hostInfo Schema and hostname part (with port number if needed) of the request URL (e.g. http://www.yiiframework.com). - * @property string $baseUrl The relative URL for the application. - * @property string $scriptUrl The relative URL of the entry script. - * @property string $pathInfo Part of the request URL that is after the entry script and before the question mark. - * Note, the returned pathinfo is decoded starting from 1.1.4. - * Prior to 1.1.4, whether it is decoded or not depends on the server configuration - * (in most cases it is not decoded). - * @property string $requestUri The request URI portion for the currently requested URL. - * @property string $queryString Part of the request URL that is after the question mark. - * @property boolean $isSecureConnection If the request is sent via secure channel (https). - * @property string $requestType Request type, such as GET, POST, HEAD, PUT, DELETE. - * @property boolean $isPostRequest Whether this is a POST request. - * @property boolean $isDeleteRequest Whether this is a DELETE request. - * @property boolean $isPutRequest Whether this is a PUT request. - * @property boolean $isAjaxRequest Whether this is an AJAX (XMLHttpRequest) request. - * @property boolean $isFlashRequest Whether this is an Adobe Flash or Adobe Flex request. - * @property string $serverName Server name. - * @property integer $serverPort Server port number. - * @property string $urlReferrer URL referrer, null if not present. - * @property string $userAgent User agent, null if not present. - * @property string $userHostAddress User IP address. - * @property string $userHost User host name, null if cannot be determined. - * @property string $scriptFile Entry script file path (processed w/ realpath()). - * @property array $browser User browser capabilities. - * @property string $acceptTypes User browser accept types, null if not present. - * @property integer $port Port number for insecure requests. - * @property integer $securePort Port number for secure requests. - * @property CCookieCollection $cookies The cookie collection. - * @property string $preferredLanguage The user preferred language. - * @property string $csrfToken The random token for CSRF validation. - * * @author Qiang Xue - * @version $Id$ - * @package system.web - * @since 1.0 + * @since 2.0 */ -class CHttpRequest extends CApplicationComponent +class Request extends \yii\base\Request { /** * @var boolean whether cookies should be validated to ensure they are not tampered. Defaults to false. */ - public $enableCookieValidation=false; + public $enableCookieValidation = false; /** * @var boolean whether to enable CSRF (Cross-Site Request Forgery) validation. Defaults to false. * By setting this property to true, forms submitted to an Yii Web application must be originated @@ -73,12 +28,12 @@ class CHttpRequest extends CApplicationComponent * the needed HTML forms in your pages. * @see http://seclab.stanford.edu/websec/csrf/csrf.pdf */ - public $enableCsrfValidation=false; + public $enableCsrfValidation = false; /** * @var string the name of the token used to prevent CSRF. Defaults to 'YII_CSRF_TOKEN'. - * This property is effectively only when {@link enableCsrfValidation} is true. + * This property is effective only when {@link enableCsrfValidation} is true. */ - public $csrfTokenName='YII_CSRF_TOKEN'; + public $csrfTokenName = 'YII_CSRF_TOKEN'; /** * @var array the property values (in name-value pairs) used to initialize the CSRF cookie. * Any property of {@link CHttpCookie} may be initialized. @@ -116,33 +71,35 @@ class CHttpRequest extends CApplicationComponent */ protected function normalizeRequest() { - // normalize request - if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) - { - if(isset($_GET)) - $_GET=$this->stripSlashes($_GET); - if(isset($_POST)) - $_POST=$this->stripSlashes($_POST); - if(isset($_REQUEST)) - $_REQUEST=$this->stripSlashes($_REQUEST); - if(isset($_COOKIE)) - $_COOKIE=$this->stripSlashes($_COOKIE); + if (get_magic_quotes_gpc()) { + if (isset($_GET)) { + $_GET = $this->stripSlashes($_GET); + } + if (isset($_POST)) { + $_POST = $this->stripSlashes($_POST); + } + if (isset($_REQUEST)) { + $_REQUEST = $this->stripSlashes($_REQUEST); + } + if (isset($_COOKIE)) { + $_COOKIE = $this->stripSlashes($_COOKIE); + } } - if($this->enableCsrfValidation) - \Yii::$application->attachEventHandler('onBeginRequest',array($this,'validateCsrfToken')); + if ($this->enableCsrfValidation) { + \Yii::$application->on('beginRequest', array($this, 'validateCsrfToken')); + } } - /** * Strips slashes from input data. * This method is applied when magic quotes is enabled. * @param mixed $data input data to be processed * @return mixed processed data */ - public function stripSlashes(&$data) + public function stripSlashes($data) { - return is_array($data)?array_map(array($this,'stripSlashes'),$data):stripslashes($data); + return is_array($data) ? array_map(array($this, 'stripSlashes'), $data) : stripslashes($data); } /** @@ -155,7 +112,7 @@ class CHttpRequest extends CApplicationComponent * @see getQuery * @see getPost */ - public function getParam($name,$defaultValue=null) + public function getParam($name, $defaultValue = null) { return isset($_GET[$name]) ? $_GET[$name] : (isset($_POST[$name]) ? $_POST[$name] : $defaultValue); } @@ -169,7 +126,7 @@ class CHttpRequest extends CApplicationComponent * @see getPost * @see getParam */ - public function getQuery($name,$defaultValue=null) + public function getQuery($name, $defaultValue = null) { return isset($_GET[$name]) ? $_GET[$name] : $defaultValue; } @@ -183,7 +140,7 @@ class CHttpRequest extends CApplicationComponent * @see getParam * @see getQuery */ - public function getPost($name,$defaultValue=null) + public function getPost($name, $defaultValue = null) { return isset($_POST[$name]) ? $_POST[$name] : $defaultValue; } @@ -199,13 +156,15 @@ class CHttpRequest extends CApplicationComponent * @return mixed the DELETE parameter value * @since 1.1.7 */ - public function getDelete($name,$defaultValue=null) + public function getDelete($name, $defaultValue = null) { - if($this->getIsDeleteViaPostRequest()) + if ($this->getIsDeleteViaPostRequest()) { return $this->getPost($name, $defaultValue); + } - if($this->_deleteParams===null) - $this->_deleteParams=$this->getIsDeleteRequest() ? $this->getRestParams() : array(); + if ($this->_deleteParams === null) { + $this->_deleteParams = $this->getIsDeleteRequest() ? $this->getRestParams() : array(); + } return isset($this->_deleteParams[$name]) ? $this->_deleteParams[$name] : $defaultValue; } @@ -220,13 +179,15 @@ class CHttpRequest extends CApplicationComponent * @return mixed the PUT parameter value * @since 1.1.7 */ - public function getPut($name,$defaultValue=null) + public function getPut($name, $defaultValue = null) { - if($this->getIsPutViaPostReqest()) + if ($this->getIsPutViaPostReqest()) { return $this->getPost($name, $defaultValue); + } - if($this->_putParams===null) - $this->_putParams=$this->getIsPutRequest() ? $this->getRestParams() : array(); + if ($this->_putParams === null) { + $this->_putParams = $this->getIsPutRequest() ? $this->getRestParams() : array(); + } return isset($this->_putParams[$name]) ? $this->_putParams[$name] : $defaultValue; } @@ -237,11 +198,12 @@ class CHttpRequest extends CApplicationComponent */ protected function getRestParams() { - $result=array(); - if(function_exists('mb_parse_str')) + $result = array(); + if (function_exists('mb_parse_str')) { mb_parse_str(file_get_contents('php://input'), $result); - else + } else { parse_str(file_get_contents('php://input'), $result); + } return $result; } @@ -264,41 +226,42 @@ class CHttpRequest extends CApplicationComponent * @return string schema and hostname part (with port number if needed) of the request URL (e.g. http://www.yiiframework.com) * @see setHostInfo */ - public function getHostInfo($schema='') + public function getHostInfo($schema = '') { - if($this->_hostInfo===null) - { - if($secure=$this->getIsSecureConnection()) - $http='https'; - else - $http='http'; - if(isset($_SERVER['HTTP_HOST'])) - $this->_hostInfo=$http.'://'.$_SERVER['HTTP_HOST']; - else - { - $this->_hostInfo=$http.'://'.$_SERVER['SERVER_NAME']; - $port=$secure ? $this->getSecurePort() : $this->getPort(); - if(($port!==80 && !$secure) || ($port!==443 && $secure)) - $this->_hostInfo.=':'.$port; + if ($this->_hostInfo === null) { + if ($secure = $this->getIsSecureConnection()) { + $http = 'https'; + } else { + $http = 'http'; + } + if (isset($_SERVER['HTTP_HOST'])) { + $this->_hostInfo = $http . '://' . $_SERVER['HTTP_HOST']; + } else { + $this->_hostInfo = $http . '://' . $_SERVER['SERVER_NAME']; + $port = $secure ? $this->getSecurePort() : $this->getPort(); + if (($port !== 80 && !$secure) || ($port !== 443 && $secure)) { + $this->_hostInfo .= ':' . $port; + } } } - if($schema!=='') - { - $secure=$this->getIsSecureConnection(); - if($secure && $schema==='https' || !$secure && $schema==='http') + if ($schema !== '') { + $secure = $this->getIsSecureConnection(); + if ($secure && $schema === 'https' || !$secure && $schema === 'http') { return $this->_hostInfo; + } - $port=$schema==='https' ? $this->getSecurePort() : $this->getPort(); - if($port!==80 && $schema==='http' || $port!==443 && $schema==='https') - $port=':'.$port; - else - $port=''; + $port = $schema === 'https' ? $this->getSecurePort() : $this->getPort(); + if ($port !== 80 && $schema === 'http' || $port !== 443 && $schema === 'https') { + $port = ':' . $port; + } else { + $port = ''; + } - $pos=strpos($this->_hostInfo,':'); - return $schema.substr($this->_hostInfo,$pos,strcspn($this->_hostInfo,':',$pos+1)+1).$port; - } - else + $pos = strpos($this->_hostInfo, ':'); + return $schema . substr($this->_hostInfo, $pos, strcspn($this->_hostInfo, ':', $pos + 1) + 1) . $port; + } else { return $this->_hostInfo; + } } /** @@ -309,7 +272,7 @@ class CHttpRequest extends CApplicationComponent */ public function setHostInfo($value) { - $this->_hostInfo=rtrim($value,'/'); + $this->_hostInfo = rtrim($value, '/'); } /** @@ -320,10 +283,11 @@ class CHttpRequest extends CApplicationComponent * @return string the relative URL for the application * @see setScriptUrl */ - public function getBaseUrl($absolute=false) + public function getBaseUrl($absolute = false) { - if($this->_baseUrl===null) - $this->_baseUrl=rtrim(dirname($this->getScriptUrl()),'\\/'); + if ($this->_baseUrl === null) { + $this->_baseUrl = rtrim(dirname($this->getScriptUrl()), '\\/'); + } return $absolute ? $this->getHostInfo() . $this->_baseUrl : $this->_baseUrl; } @@ -335,7 +299,7 @@ class CHttpRequest extends CApplicationComponent */ public function setBaseUrl($value) { - $this->_baseUrl=$value; + $this->_baseUrl = $value; } /** @@ -345,21 +309,29 @@ class CHttpRequest extends CApplicationComponent */ public function getScriptUrl() { - if($this->_scriptUrl===null) - { - $scriptName=basename($_SERVER['SCRIPT_FILENAME']); - if(basename($_SERVER['SCRIPT_NAME'])===$scriptName) - $this->_scriptUrl=$_SERVER['SCRIPT_NAME']; - else if(basename($_SERVER['PHP_SELF'])===$scriptName) - $this->_scriptUrl=$_SERVER['PHP_SELF']; - else if(isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME'])===$scriptName) - $this->_scriptUrl=$_SERVER['ORIG_SCRIPT_NAME']; - else if(($pos=strpos($_SERVER['PHP_SELF'],'/'.$scriptName))!==false) - $this->_scriptUrl=substr($_SERVER['SCRIPT_NAME'],0,$pos).'/'.$scriptName; - else if(isset($_SERVER['DOCUMENT_ROOT']) && strpos($_SERVER['SCRIPT_FILENAME'],$_SERVER['DOCUMENT_ROOT'])===0) - $this->_scriptUrl=str_replace('\\','/',str_replace($_SERVER['DOCUMENT_ROOT'],'',$_SERVER['SCRIPT_FILENAME'])); - else - throw new CException(Yii::t('yii','CHttpRequest is unable to determine the entry script URL.')); + if ($this->_scriptUrl === null) { + $scriptName = basename($_SERVER['SCRIPT_FILENAME']); + if (basename($_SERVER['SCRIPT_NAME']) === $scriptName) { + $this->_scriptUrl = $_SERVER['SCRIPT_NAME']; + } else { + if (basename($_SERVER['PHP_SELF']) === $scriptName) { + $this->_scriptUrl = $_SERVER['PHP_SELF']; + } else { + if (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $scriptName) { + $this->_scriptUrl = $_SERVER['ORIG_SCRIPT_NAME']; + } else { + if (($pos = strpos($_SERVER['PHP_SELF'], '/' . $scriptName)) !== false) { + $this->_scriptUrl = substr($_SERVER['SCRIPT_NAME'], 0, $pos) . '/' . $scriptName; + } else { + if (isset($_SERVER['DOCUMENT_ROOT']) && strpos($_SERVER['SCRIPT_FILENAME'], $_SERVER['DOCUMENT_ROOT']) === 0) { + $this->_scriptUrl = str_replace('\\', '/', str_replace($_SERVER['DOCUMENT_ROOT'], '', $_SERVER['SCRIPT_FILENAME'])); + } else { + throw new CException(Yii::t('yii', 'CHttpRequest is unable to determine the entry script URL.')); + } + } + } + } + } } return $this->_scriptUrl; } @@ -372,7 +344,7 @@ class CHttpRequest extends CApplicationComponent */ public function setScriptUrl($value) { - $this->_scriptUrl='/'.trim($value,'/'); + $this->_scriptUrl = '/' . trim($value, '/'); } /** @@ -387,27 +359,32 @@ class CHttpRequest extends CApplicationComponent */ public function getPathInfo() { - if($this->_pathInfo===null) - { - $pathInfo=$this->getRequestUri(); - - if(($pos=strpos($pathInfo,'?'))!==false) - $pathInfo=substr($pathInfo,0,$pos); - - $pathInfo=$this->decodePathInfo($pathInfo); - - $scriptUrl=$this->getScriptUrl(); - $baseUrl=$this->getBaseUrl(); - if(strpos($pathInfo,$scriptUrl)===0) - $pathInfo=substr($pathInfo,strlen($scriptUrl)); - else if($baseUrl==='' || strpos($pathInfo,$baseUrl)===0) - $pathInfo=substr($pathInfo,strlen($baseUrl)); - else if(strpos($_SERVER['PHP_SELF'],$scriptUrl)===0) - $pathInfo=substr($_SERVER['PHP_SELF'],strlen($scriptUrl)); - else - throw new CException(Yii::t('yii','CHttpRequest is unable to determine the path info of the request.')); - - $this->_pathInfo=trim($pathInfo,'/'); + if ($this->_pathInfo === null) { + $pathInfo = $this->getRequestUri(); + + if (($pos = strpos($pathInfo, '?')) !== false) { + $pathInfo = substr($pathInfo, 0, $pos); + } + + $pathInfo = $this->decodePathInfo($pathInfo); + + $scriptUrl = $this->getScriptUrl(); + $baseUrl = $this->getBaseUrl(); + if (strpos($pathInfo, $scriptUrl) === 0) { + $pathInfo = substr($pathInfo, strlen($scriptUrl)); + } else { + if ($baseUrl === '' || strpos($pathInfo, $baseUrl) === 0) { + $pathInfo = substr($pathInfo, strlen($baseUrl)); + } else { + if (strpos($_SERVER['PHP_SELF'], $scriptUrl) === 0) { + $pathInfo = substr($_SERVER['PHP_SELF'], strlen($scriptUrl)); + } else { + throw new CException(Yii::t('yii', 'CHttpRequest is unable to determine the path info of the request.')); + } + } + } + + $this->_pathInfo = trim($pathInfo, '/'); } return $this->_pathInfo; } @@ -426,7 +403,7 @@ class CHttpRequest extends CApplicationComponent // is it UTF-8? // http://w3.org/International/questions/qa-forms-utf-8.html - if(preg_match('%^(?: + if (preg_match('%^(?: [\x09\x0A\x0D\x20-\x7E] # ASCII | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs @@ -435,12 +412,10 @@ class CHttpRequest extends CApplicationComponent | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 - )*$%xs', $pathInfo)) - { + )*$%xs', $pathInfo) + ) { return $pathInfo; - } - else - { + } else { return utf8_encode($pathInfo); } } @@ -455,29 +430,32 @@ class CHttpRequest extends CApplicationComponent */ public function getRequestUri() { - if($this->_requestUri===null) - { - if(isset($_SERVER['HTTP_X_REWRITE_URL'])) // IIS - $this->_requestUri=$_SERVER['HTTP_X_REWRITE_URL']; - else if(isset($_SERVER['REQUEST_URI'])) + if ($this->_requestUri === null) { + if (isset($_SERVER['HTTP_X_REWRITE_URL'])) // IIS { - $this->_requestUri=$_SERVER['REQUEST_URI']; - if(!empty($_SERVER['HTTP_HOST'])) - { - if(strpos($this->_requestUri,$_SERVER['HTTP_HOST'])!==false) - $this->_requestUri=preg_replace('/^\w+:\/\/[^\/]+/','',$this->_requestUri); + $this->_requestUri = $_SERVER['HTTP_X_REWRITE_URL']; + } else { + if (isset($_SERVER['REQUEST_URI'])) { + $this->_requestUri = $_SERVER['REQUEST_URI']; + if (!empty($_SERVER['HTTP_HOST'])) { + if (strpos($this->_requestUri, $_SERVER['HTTP_HOST']) !== false) { + $this->_requestUri = preg_replace('/^\w+:\/\/[^\/]+/', '', $this->_requestUri); + } + } else { + $this->_requestUri = preg_replace('/^(http|https):\/\/[^\/]+/i', '', $this->_requestUri); + } + } else { + if (isset($_SERVER['ORIG_PATH_INFO'])) // IIS 5.0 CGI + { + $this->_requestUri = $_SERVER['ORIG_PATH_INFO']; + if (!empty($_SERVER['QUERY_STRING'])) { + $this->_requestUri .= '?' . $_SERVER['QUERY_STRING']; + } + } else { + throw new CException(Yii::t('yii', 'CHttpRequest is unable to determine the request URI.')); + } } - else - $this->_requestUri=preg_replace('/^(http|https):\/\/[^\/]+/i','',$this->_requestUri); } - else if(isset($_SERVER['ORIG_PATH_INFO'])) // IIS 5.0 CGI - { - $this->_requestUri=$_SERVER['ORIG_PATH_INFO']; - if(!empty($_SERVER['QUERY_STRING'])) - $this->_requestUri.='?'.$_SERVER['QUERY_STRING']; - } - else - throw new CException(Yii::t('yii','CHttpRequest is unable to determine the request URI.')); } return $this->_requestUri; @@ -489,7 +467,7 @@ class CHttpRequest extends CApplicationComponent */ public function getQueryString() { - return isset($_SERVER['QUERY_STRING'])?$_SERVER['QUERY_STRING']:''; + return isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : ''; } /** @@ -498,22 +476,23 @@ class CHttpRequest extends CApplicationComponent */ public function getIsSecureConnection() { - return isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'],'on'); + return isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'], 'on'); } /** * Returns the request type, such as GET, POST, HEAD, PUT, DELETE. - * Request type can be manually set in POST requests with a parameter named _method. Useful - * for RESTful request from older browsers which do not support PUT or DELETE + * Request type can be manually set in POST requests with a parameter named _method. Useful + * for RESTful request from older browsers which do not support PUT or DELETE * natively (available since version 1.1.11). * @return string request type, such as GET, POST, HEAD, PUT, DELETE. */ public function getRequestType() { - if(isset($_POST['_method'])) + if (isset($_POST['_method'])) { return strtoupper($_POST['_method']); + } - return strtoupper(isset($_SERVER['REQUEST_METHOD'])?$_SERVER['REQUEST_METHOD']:'GET'); + return strtoupper(isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET'); } /** @@ -522,7 +501,7 @@ class CHttpRequest extends CApplicationComponent */ public function getIsPostRequest() { - return isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'],'POST'); + return isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'], 'POST'); } /** @@ -532,7 +511,7 @@ class CHttpRequest extends CApplicationComponent */ public function getIsDeleteRequest() { - return (isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'],'DELETE')) || $this->getIsDeleteViaPostRequest(); + return (isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'], 'DELETE')) || $this->getIsDeleteViaPostRequest(); } /** @@ -542,7 +521,7 @@ class CHttpRequest extends CApplicationComponent */ protected function getIsDeleteViaPostRequest() { - return isset($_POST['_method']) && !strcasecmp($_POST['_method'],'DELETE'); + return isset($_POST['_method']) && !strcasecmp($_POST['_method'], 'DELETE'); } /** @@ -552,17 +531,17 @@ class CHttpRequest extends CApplicationComponent */ public function getIsPutRequest() { - return (isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'],'PUT')) || $this->getIsPutViaPostReqest(); + return (isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'], 'PUT')) || $this->getIsPutViaPostReqest(); } /** * Returns whether this is a PUT request which was tunneled through POST. * @return boolean whether this is a PUT request tunneled through POST. * @since 1.1.11 - */ + */ protected function getIsPutViaPostReqest() { - return isset($_POST['_method']) && !strcasecmp($_POST['_method'],'PUT'); + return isset($_POST['_method']) && !strcasecmp($_POST['_method'], 'PUT'); } /** @@ -571,7 +550,7 @@ class CHttpRequest extends CApplicationComponent */ public function getIsAjaxRequest() { - return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest'; + return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest'; } /** @@ -581,7 +560,7 @@ class CHttpRequest extends CApplicationComponent */ public function getIsFlashRequest() { - return isset($_SERVER['HTTP_USER_AGENT']) && (stripos($_SERVER['HTTP_USER_AGENT'],'Shockwave')!==false || stripos($_SERVER['HTTP_USER_AGENT'],'Flash')!==false); + return isset($_SERVER['HTTP_USER_AGENT']) && (stripos($_SERVER['HTTP_USER_AGENT'], 'Shockwave') !== false || stripos($_SERVER['HTTP_USER_AGENT'], 'Flash') !== false); } /** @@ -608,7 +587,7 @@ class CHttpRequest extends CApplicationComponent */ public function getUrlReferrer() { - return isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:null; + return isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null; } /** @@ -617,7 +596,7 @@ class CHttpRequest extends CApplicationComponent */ public function getUserAgent() { - return isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:null; + return isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null; } /** @@ -626,7 +605,7 @@ class CHttpRequest extends CApplicationComponent */ public function getUserHostAddress() { - return isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:'127.0.0.1'; + return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1'; } /** @@ -635,7 +614,7 @@ class CHttpRequest extends CApplicationComponent */ public function getUserHost() { - return isset($_SERVER['REMOTE_HOST'])?$_SERVER['REMOTE_HOST']:null; + return isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : null; } /** @@ -644,10 +623,11 @@ class CHttpRequest extends CApplicationComponent */ public function getScriptFile() { - if($this->_scriptFile!==null) + if ($this->_scriptFile !== null) { return $this->_scriptFile; - else - return $this->_scriptFile=realpath($_SERVER['SCRIPT_FILENAME']); + } else { + return $this->_scriptFile = realpath($_SERVER['SCRIPT_FILENAME']); + } } /** @@ -657,9 +637,9 @@ class CHttpRequest extends CApplicationComponent * @return array user browser capabilities. * @see http://www.php.net/manual/en/function.get-browser.php */ - public function getBrowser($userAgent=null) + public function getBrowser($userAgent = null) { - return get_browser($userAgent,true); + return get_browser($userAgent, true); } /** @@ -668,12 +648,12 @@ class CHttpRequest extends CApplicationComponent */ public function getAcceptTypes() { - return isset($_SERVER['HTTP_ACCEPT'])?$_SERVER['HTTP_ACCEPT']:null; + return isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : null; } private $_port; - /** + /** * Returns the port to use for insecure requests. * Defaults to 80, or the port specified by the server if the current * request is insecure. @@ -684,8 +664,9 @@ class CHttpRequest extends CApplicationComponent */ public function getPort() { - if($this->_port===null) - $this->_port=!$this->getIsSecureConnection() && isset($_SERVER['SERVER_PORT']) ? (int)$_SERVER['SERVER_PORT'] : 80; + if ($this->_port === null) { + $this->_port = !$this->getIsSecureConnection() && isset($_SERVER['SERVER_PORT']) ? (int)$_SERVER['SERVER_PORT'] : 80; + } return $this->_port; } @@ -698,8 +679,8 @@ class CHttpRequest extends CApplicationComponent */ public function setPort($value) { - $this->_port=(int)$value; - $this->_hostInfo=null; + $this->_port = (int)$value; + $this->_hostInfo = null; } private $_securePort; @@ -715,8 +696,9 @@ class CHttpRequest extends CApplicationComponent */ public function getSecurePort() { - if($this->_securePort===null) - $this->_securePort=$this->getIsSecureConnection() && isset($_SERVER['SERVER_PORT']) ? (int)$_SERVER['SERVER_PORT'] : 443; + if ($this->_securePort === null) { + $this->_securePort = $this->getIsSecureConnection() && isset($_SERVER['SERVER_PORT']) ? (int)$_SERVER['SERVER_PORT'] : 443; + } return $this->_securePort; } @@ -729,8 +711,8 @@ class CHttpRequest extends CApplicationComponent */ public function setSecurePort($value) { - $this->_securePort=(int)$value; - $this->_hostInfo=null; + $this->_securePort = (int)$value; + $this->_hostInfo = null; } /** @@ -742,10 +724,11 @@ class CHttpRequest extends CApplicationComponent */ public function getCookies() { - if($this->_cookies!==null) + if ($this->_cookies !== null) { return $this->_cookies; - else - return $this->_cookies=new CCookieCollection($this); + } else { + return $this->_cookies = new CCookieCollection($this); + } } /** @@ -756,13 +739,15 @@ class CHttpRequest extends CApplicationComponent * @param integer $statusCode the HTTP status code. Defaults to 302. See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} * for details about HTTP status code. */ - public function redirect($url,$terminate=true,$statusCode=302) + public function redirect($url, $terminate = true, $statusCode = 302) { - if(strpos($url,'/')===0) - $url=$this->getHostInfo().$url; - header('Location: '.$url, true, $statusCode); - if($terminate) + if (strpos($url, '/') === 0) { + $url = $this->getHostInfo() . $url; + } + header('Location: ' . $url, true, $statusCode); + if ($terminate) { \Yii::$application->end(); + } } /** @@ -773,18 +758,18 @@ class CHttpRequest extends CApplicationComponent */ public function getPreferredLanguage() { - if($this->_preferredLanguage===null) - { - if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && ($n=preg_match_all('/([\w\-_]+)\s*(;\s*q\s*=\s*(\d*\.\d*))?/',$_SERVER['HTTP_ACCEPT_LANGUAGE'],$matches))>0) - { - $languages=array(); - for($i=0;$i<$n;++$i) - $languages[$matches[1][$i]]=empty($matches[3][$i]) ? 1.0 : floatval($matches[3][$i]); + if ($this->_preferredLanguage === null) { + if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && ($n = preg_match_all('/([\w\-_]+)\s*(;\s*q\s*=\s*(\d*\.\d*))?/', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches)) > 0) { + $languages = array(); + for ($i = 0; $i < $n; ++$i) { + $languages[$matches[1][$i]] = empty($matches[3][$i]) ? 1.0 : floatval($matches[3][$i]); + } arsort($languages); - foreach($languages as $language=>$pref) - return $this->_preferredLanguage=CLocale::getCanonicalID($language); + foreach ($languages as $language => $pref) { + return $this->_preferredLanguage = CLocale::getCanonicalID($language); + } } - return $this->_preferredLanguage=false; + return $this->_preferredLanguage = false; } return $this->_preferredLanguage; } @@ -796,32 +781,32 @@ class CHttpRequest extends CApplicationComponent * @param string $mimeType mime type of the content. If null, it will be guessed automatically based on the given file name. * @param boolean $terminate whether to terminate the current application after calling this method */ - public function sendFile($fileName,$content,$mimeType=null,$terminate=true) + public function sendFile($fileName, $content, $mimeType = null, $terminate = true) { - if($mimeType===null) - { - if(($mimeType=CFileHelper::getMimeTypeByExtension($fileName))===null) - $mimeType='text/plain'; + if ($mimeType === null) { + if (($mimeType = CFileHelper::getMimeTypeByExtension($fileName)) === null) { + $mimeType = 'text/plain'; + } } header('Pragma: public'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header("Content-type: $mimeType"); - if(ob_get_length()===false) - header('Content-Length: '.(function_exists('mb_strlen') ? mb_strlen($content,'8bit') : strlen($content))); + if (ob_get_length() === false) { + header('Content-Length: ' . (function_exists('mb_strlen') ? mb_strlen($content, '8bit') : strlen($content))); + } header("Content-Disposition: attachment; filename=\"$fileName\""); header('Content-Transfer-Encoding: binary'); - if($terminate) - { + if ($terminate) { // clean up the application first because the file downloading could take long time // which may cause timeout of some resources (such as DB connection) - \Yii::$application->end(0,false); + \Yii::$application->end(0, false); echo $content; exit(0); - } - else + } else { echo $content; + } } /** @@ -876,37 +861,42 @@ class CHttpRequest extends CApplicationComponent *
  • addHeaders: an array of additional http headers in header-value pairs (available since version 1.1.10)
  • * */ - public function xSendFile($filePath, $options=array()) + public function xSendFile($filePath, $options = array()) { - if(!isset($options['forceDownload']) || $options['forceDownload']) - $disposition='attachment'; - else - $disposition='inline'; - - if(!isset($options['saveName'])) - $options['saveName']=basename($filePath); - - if(!isset($options['mimeType'])) - { - if(($options['mimeType']=CFileHelper::getMimeTypeByExtension($filePath))===null) - $options['mimeType']='text/plain'; + if (!isset($options['forceDownload']) || $options['forceDownload']) { + $disposition = 'attachment'; + } else { + $disposition = 'inline'; } - if(!isset($options['xHeader'])) - $options['xHeader']='X-Sendfile'; + if (!isset($options['saveName'])) { + $options['saveName'] = basename($filePath); + } - if($options['mimeType'] !== null) - header('Content-type: '.$options['mimeType']); - header('Content-Disposition: '.$disposition.'; filename="'.$options['saveName'].'"'); - if(isset($options['addHeaders'])) - { - foreach($options['addHeaders'] as $header=>$value) - header($header.': '.$value); + if (!isset($options['mimeType'])) { + if (($options['mimeType'] = CFileHelper::getMimeTypeByExtension($filePath)) === null) { + $options['mimeType'] = 'text/plain'; + } } - header(trim($options['xHeader']).': '.$filePath); - if(!isset($options['terminate']) || $options['terminate']) + if (!isset($options['xHeader'])) { + $options['xHeader'] = 'X-Sendfile'; + } + + if ($options['mimeType'] !== null) { + header('Content-type: ' . $options['mimeType']); + } + header('Content-Disposition: ' . $disposition . '; filename="' . $options['saveName'] . '"'); + if (isset($options['addHeaders'])) { + foreach ($options['addHeaders'] as $header => $value) { + header($header . ': ' . $value); + } + } + header(trim($options['xHeader']) . ': ' . $filePath); + + if (!isset($options['terminate']) || $options['terminate']) { \Yii::$application->end(); + } } /** @@ -918,14 +908,12 @@ class CHttpRequest extends CApplicationComponent */ public function getCsrfToken() { - if($this->_csrfToken===null) - { - $cookie=$this->getCookies()->itemAt($this->csrfTokenName); - if(!$cookie || ($this->_csrfToken=$cookie->value)==null) - { - $cookie=$this->createCsrfCookie(); - $this->_csrfToken=$cookie->value; - $this->getCookies()->add($cookie->name,$cookie); + if ($this->_csrfToken === null) { + $cookie = $this->getCookies()->itemAt($this->csrfTokenName); + if (!$cookie || ($this->_csrfToken = $cookie->value) == null) { + $cookie = $this->createCsrfCookie(); + $this->_csrfToken = $cookie->value; + $this->getCookies()->add($cookie->name, $cookie); } } @@ -941,11 +929,11 @@ class CHttpRequest extends CApplicationComponent */ protected function createCsrfCookie() { - $cookie=new CHttpCookie($this->csrfTokenName,sha1(uniqid(mt_rand(),true))); - if(is_array($this->csrfCookie)) - { - foreach($this->csrfCookie as $name=>$value) - $cookie->$name=$value; + $cookie = new CHttpCookie($this->csrfTokenName, sha1(uniqid(mt_rand(), true))); + if (is_array($this->csrfCookie)) { + foreach ($this->csrfCookie as $name => $value) { + $cookie->$name = $value; + } } return $cookie; } @@ -960,20 +948,19 @@ class CHttpRequest extends CApplicationComponent */ public function validateCsrfToken($event) { - if($this->getIsPostRequest()) - { + if ($this->getIsPostRequest()) { // only validate POST requests - $cookies=$this->getCookies(); - if($cookies->contains($this->csrfTokenName) && isset($_POST[$this->csrfTokenName])) - { - $tokenFromCookie=$cookies->itemAt($this->csrfTokenName)->value; - $tokenFromPost=$_POST[$this->csrfTokenName]; - $valid=$tokenFromCookie===$tokenFromPost; + $cookies = $this->getCookies(); + if ($cookies->contains($this->csrfTokenName) && isset($_POST[$this->csrfTokenName])) { + $tokenFromCookie = $cookies->itemAt($this->csrfTokenName)->value; + $tokenFromPost = $_POST[$this->csrfTokenName]; + $valid = $tokenFromCookie === $tokenFromPost; + } else { + $valid = false; + } + if (!$valid) { + throw new CHttpException(400, Yii::t('yii', 'The CSRF token could not be verified.')); } - else - $valid=false; - if(!$valid) - throw new CHttpException(400,Yii::t('yii','The CSRF token could not be verified.')); } } } @@ -1000,7 +987,7 @@ class CHttpRequest extends CApplicationComponent class CCookieCollection extends CMap { private $_request; - private $_initialized=false; + private $_initialized = false; /** * Constructor. @@ -1008,9 +995,9 @@ class CCookieCollection extends CMap */ public function __construct(CHttpRequest $request) { - $this->_request=$request; + $this->_request = $request; $this->copyfrom($this->getCookies()); - $this->_initialized=true; + $this->_initialized = true; } /** @@ -1026,20 +1013,18 @@ class CCookieCollection extends CMap */ protected function getCookies() { - $cookies=array(); - if($this->_request->enableCookieValidation) - { - $sm=\Yii::$application->getSecurityManager(); - foreach($_COOKIE as $name=>$value) - { - if(is_string($value) && ($value=$sm->validateData($value))!==false) - $cookies[$name]=new CHttpCookie($name,@unserialize($value)); + $cookies = array(); + if ($this->_request->enableCookieValidation) { + $sm = \Yii::$application->getSecurityManager(); + foreach ($_COOKIE as $name => $value) { + if (is_string($value) && ($value = $sm->validateData($value)) !== false) { + $cookies[$name] = new CHttpCookie($name, @unserialize($value)); + } + } + } else { + foreach ($_COOKIE as $name => $value) { + $cookies[$name] = new CHttpCookie($name, $value); } - } - else - { - foreach($_COOKIE as $name=>$value) - $cookies[$name]=new CHttpCookie($name,$value); } return $cookies; } @@ -1052,17 +1037,17 @@ class CCookieCollection extends CMap * @param CHttpCookie $cookie Cookie object. * @throws CException if the item to be inserted is not a CHttpCookie object. */ - public function add($name,$cookie) + public function add($name, $cookie) { - if($cookie instanceof CHttpCookie) - { + if ($cookie instanceof CHttpCookie) { $this->remove($name); - parent::add($name,$cookie); - if($this->_initialized) + parent::add($name, $cookie); + if ($this->_initialized) { $this->addCookie($cookie); + } + } else { + throw new CException(Yii::t('yii', 'CHttpCookieCollection can only hold CHttpCookie objects.')); } - else - throw new CException(Yii::t('yii','CHttpCookieCollection can only hold CHttpCookie objects.')); } /** @@ -1074,10 +1059,10 @@ class CCookieCollection extends CMap */ public function remove($name) { - if(($cookie=parent::remove($name))!==null) - { - if($this->_initialized) + if (($cookie = parent::remove($name)) !== null) { + if ($this->_initialized) { $this->removeCookie($cookie); + } } return $cookie; } @@ -1088,13 +1073,11 @@ class CCookieCollection extends CMap */ protected function addCookie($cookie) { - $value=$cookie->value; - if($this->_request->enableCookieValidation) - $value=\Yii::$application->getSecurityManager()->hashData(serialize($value)); - if(version_compare(PHP_VERSION,'5.2.0','>=')) - setcookie($cookie->name,$value,$cookie->expire,$cookie->path,$cookie->domain,$cookie->secure,$cookie->httpOnly); - else - setcookie($cookie->name,$value,$cookie->expire,$cookie->path,$cookie->domain,$cookie->secure); + $value = $cookie->value; + if ($this->_request->enableCookieValidation) { + $value = \Yii::$application->getSecurityManager()->hashData(serialize($value)); + } + setcookie($cookie->name, $value, $cookie->expire, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly); } /** @@ -1103,9 +1086,6 @@ class CCookieCollection extends CMap */ protected function removeCookie($cookie) { - if(version_compare(PHP_VERSION,'5.2.0','>=')) - setcookie($cookie->name,null,0,$cookie->path,$cookie->domain,$cookie->secure,$cookie->httpOnly); - else - setcookie($cookie->name,null,0,$cookie->path,$cookie->domain,$cookie->secure); + setcookie($cookie->name, null, 0, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly); } } diff --git a/framework/web/Response.php b/framework/web/Response.php new file mode 100644 index 0000000..221e217 --- /dev/null +++ b/framework/web/Response.php @@ -0,0 +1,144 @@ + + * @since 2.0 + */ +class Response extends \yii\base\Response +{ + /** + * Sends a file to user. + * @param string $fileName file name + * @param string $content content to be set. + * @param string $mimeType mime type of the content. If null, it will be guessed automatically based on the given file name. + * @param boolean $terminate whether to terminate the current application after calling this method + * @todo + */ + public function sendFile($fileName, $content, $mimeType = null, $terminate = true) + { + if ($mimeType === null && ($mimeType = FileHelper::getMimeType($fileName)) === null) { + $mimeType = 'application/octet-stream'; + } + header('Pragma: public'); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header("Content-type: $mimeType"); + if (ob_get_length() === false) { + header('Content-Length: ' . (function_exists('mb_strlen') ? mb_strlen($content, '8bit') : strlen($content))); + } + header("Content-Disposition: attachment; filename=\"$fileName\""); + header('Content-Transfer-Encoding: binary'); + + if ($terminate) { + // clean up the application first because the file downloading could take long time + // which may cause timeout of some resources (such as DB connection) + Yii::app()->end(0, false); + echo $content; + exit(0); + } else { + echo $content; + } + } + + /** + * Sends existing file to a browser as a download using x-sendfile. + * + * X-Sendfile is a feature allowing a web application to redirect the request for a file to the webserver + * that in turn processes the request, this way eliminating the need to perform tasks like reading the file + * and sending it to the user. When dealing with a lot of files (or very big files) this can lead to a great + * increase in performance as the web application is allowed to terminate earlier while the webserver is + * handling the request. + * + * The request is sent to the server through a special non-standard HTTP-header. + * When the web server encounters the presence of such header it will discard all output and send the file + * specified by that header using web server internals including all optimizations like caching-headers. + * + * As this header directive is non-standard different directives exists for different web servers applications: + *
      + *
    • Apache: {@link http://tn123.org/mod_xsendfile X-Sendfile}
    • + *
    • Lighttpd v1.4: {@link http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file X-LIGHTTPD-send-file}
    • + *
    • Lighttpd v1.5: {@link http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file X-Sendfile}
    • + *
    • Nginx: {@link http://wiki.nginx.org/XSendfile X-Accel-Redirect}
    • + *
    • Cherokee: {@link http://www.cherokee-project.com/doc/other_goodies.html#x-sendfile X-Sendfile and X-Accel-Redirect}
    • + *
    + * So for this method to work the X-SENDFILE option/module should be enabled by the web server and + * a proper xHeader should be sent. + * + * Note: + * This option allows to download files that are not under web folders, and even files that are otherwise protected (deny from all) like .htaccess + * + * Side effects: + * If this option is disabled by the web server, when this method is called a download configuration dialog + * will open but the downloaded file will have 0 bytes. + * + * Example: + *
    +	 * request->xSendFile('/home/user/Pictures/picture1.jpg',array(
    +	 *        'saveName'=>'image1.jpg',
    +	 *        'mimeType'=>'image/jpeg',
    +	 *        'terminate'=>false,
    +	 *    ));
    +	 * ?>
    +	 * 
    + * @param string $filePath file name with full path + * @param array $options additional options: + *
      + *
    • saveName: file name shown to the user, if not set real file name will be used
    • + *
    • mimeType: mime type of the file, if not set it will be guessed automatically based on the file name, if set to null no content-type header will be sent.
    • + *
    • xHeader: appropriate x-sendfile header, defaults to "X-Sendfile"
    • + *
    • terminate: whether to terminate the current application after calling this method, defaults to true
    • + *
    • forceDownload: specifies whether the file will be downloaded or shown inline, defaults to true. (Since version 1.1.9.)
    • + *
    • addHeaders: an array of additional http headers in header-value pairs (available since version 1.1.10)
    • + *
    + * @todo + */ + public function xSendFile($filePath, $options = array()) + { + if (!isset($options['forceDownload']) || $options['forceDownload']) { + $disposition = 'attachment'; + } else { + $disposition = 'inline'; + } + + if (!isset($options['saveName'])) { + $options['saveName'] = basename($filePath); + } + + if (!isset($options['mimeType'])) { + if (($options['mimeType'] = CFileHelper::getMimeTypeByExtension($filePath)) === null) { + $options['mimeType'] = 'text/plain'; + } + } + + if (!isset($options['xHeader'])) { + $options['xHeader'] = 'X-Sendfile'; + } + + if ($options['mimeType'] !== null) { + header('Content-type: ' . $options['mimeType']); + } + header('Content-Disposition: ' . $disposition . '; filename="' . $options['saveName'] . '"'); + if (isset($options['addHeaders'])) { + foreach ($options['addHeaders'] as $header => $value) { + header($header . ': ' . $value); + } + } + header(trim($options['xHeader']) . ': ' . $filePath); + + if (!isset($options['terminate']) || $options['terminate']) { + Yii::app()->end(); + } + } +} diff --git a/framework/web/Sort.php b/framework/web/Sort.php index ea20f22..1b6ba63 100644 --- a/framework/web/Sort.php +++ b/framework/web/Sort.php @@ -64,7 +64,7 @@ class CSort extends CComponent * @var boolean whether the sorting can be applied to multiple attributes simultaneously. * Defaults to false, which means each time the data can only be sorted by one attribute. */ - public $multiSort=false; + public $multiSort = false; /** * @var string the name of the model class whose attributes can be sorted. * The model class must be a child class of {@link CActiveRecord}. @@ -143,17 +143,17 @@ class CSort extends CComponent * element is the first element in the array, the model attribute takes precedence; and if the star * element is the last one, the virtual attribute takes precedence. */ - public $attributes=array(); + public $attributes = array(); /** * @var string the name of the GET parameter that specifies which attributes to be sorted * in which direction. Defaults to 'sort'. */ - public $sortVar='sort'; + public $sortVar = 'sort'; /** * @var string the tag appeared in the GET parameter that indicates the attribute should be sorted * in descending order. Defaults to 'desc'. */ - public $descTag='desc'; + public $descTag = 'desc'; /** * @var mixed the default order that should be applied to the query criteria when * the current request does not specify any sort. For example, 'name, create_time DESC' or @@ -180,14 +180,14 @@ class CSort extends CComponent * @var string the route (controller ID and action ID) for generating the sorted contents. * Defaults to empty string, meaning using the currently requested route. */ - public $route=''; + public $route = ''; /** * @var array separators used in the generated URL. This must be an array consisting of * two elements. The first element specifies the character separating different * attributes, while the second element specifies the character separating attribute name * and the corresponding sort direction. Defaults to array('-','.'). */ - public $separators=array('-','.'); + public $separators = array('-', '.'); /** * @var array the additional GET parameters (name=>value) that should be used when generating sort URLs. * Defaults to null, meaning using the currently available GET parameters. @@ -201,9 +201,9 @@ class CSort extends CComponent * @param string $modelClass the class name of data models that need to be sorted. * This should be a child class of {@link CActiveRecord}. */ - public function __construct($modelClass=null) + public function __construct($modelClass = null) { - $this->modelClass=$modelClass; + $this->modelClass = $modelClass; } /** @@ -215,12 +215,12 @@ class CSort extends CComponent */ public function applyOrder($criteria) { - $order=$this->getOrderBy(); - if(!empty($order)) - { - if(!empty($criteria->order)) - $criteria->order.=', '; - $criteria->order.=$order; + $order = $this->getOrderBy(); + if (!empty($order)) { + if (!empty($criteria->order)) { + $criteria->order .= ', '; + } + $criteria->order .= $order; } } @@ -231,38 +231,37 @@ class CSort extends CComponent */ public function getOrderBy() { - $directions=$this->getDirections(); - if(empty($directions)) + $directions = $this->getDirections(); + if (empty($directions)) { return is_string($this->defaultOrder) ? $this->defaultOrder : ''; - else - { - if($this->modelClass!==null) - $schema=CActiveRecord::model($this->modelClass)->getDbConnection()->getSchema(); - $orders=array(); - foreach($directions as $attribute=>$descending) - { - $definition=$this->resolveAttribute($attribute); - if(is_array($definition)) - { - if($descending) - $orders[]=isset($definition['desc']) ? $definition['desc'] : $attribute.' DESC'; - else - $orders[]=isset($definition['asc']) ? $definition['asc'] : $attribute; - } - else if($definition!==false) - { - $attribute=$definition; - if(isset($schema)) - { - if(($pos=strpos($attribute,'.'))!==false) - $attribute=$schema->quoteTableName(substr($attribute,0,$pos)).'.'.$schema->quoteColumnName(substr($attribute,$pos+1)); - else - $attribute=CActiveRecord::model($this->modelClass)->getTableAlias(true).'.'.$schema->quoteColumnName($attribute); + } else { + if ($this->modelClass !== null) { + $schema = CActiveRecord::model($this->modelClass)->getDbConnection()->getSchema(); + } + $orders = array(); + foreach ($directions as $attribute => $descending) { + $definition = $this->resolveAttribute($attribute); + if (is_array($definition)) { + if ($descending) { + $orders[] = isset($definition['desc']) ? $definition['desc'] : $attribute . ' DESC'; + } else { + $orders[] = isset($definition['asc']) ? $definition['asc'] : $attribute; + } + } else { + if ($definition !== false) { + $attribute = $definition; + if (isset($schema)) { + if (($pos = strpos($attribute, '.')) !== false) { + $attribute = $schema->quoteTableName(substr($attribute, 0, $pos)) . '.' . $schema->quoteColumnName(substr($attribute, $pos + 1)); + } else { + $attribute = CActiveRecord::model($this->modelClass)->getTableAlias(true) . '.' . $schema->quoteColumnName($attribute); + } + } + $orders[] = $descending ? $attribute . ' DESC' : $attribute; } - $orders[]=$descending?$attribute.' DESC':$attribute; } } - return implode(', ',$orders); + return implode(', ', $orders); } } @@ -276,36 +275,41 @@ class CSort extends CComponent * @param array $htmlOptions additional HTML attributes for the hyperlink tag * @return string the generated hyperlink */ - public function link($attribute,$label=null,$htmlOptions=array()) + public function link($attribute, $label = null, $htmlOptions = array()) { - if($label===null) - $label=$this->resolveLabel($attribute); - if(($definition=$this->resolveAttribute($attribute))===false) + if ($label === null) { + $label = $this->resolveLabel($attribute); + } + if (($definition = $this->resolveAttribute($attribute)) === false) { return $label; - $directions=$this->getDirections(); - if(isset($directions[$attribute])) - { - $class=$directions[$attribute] ? 'desc' : 'asc'; - if(isset($htmlOptions['class'])) - $htmlOptions['class'].=' '.$class; - else - $htmlOptions['class']=$class; - $descending=!$directions[$attribute]; + } + $directions = $this->getDirections(); + if (isset($directions[$attribute])) { + $class = $directions[$attribute] ? 'desc' : 'asc'; + if (isset($htmlOptions['class'])) { + $htmlOptions['class'] .= ' ' . $class; + } else { + $htmlOptions['class'] = $class; + } + $descending = !$directions[$attribute]; unset($directions[$attribute]); + } else { + if (is_array($definition) && isset($definition['default'])) { + $descending = $definition['default'] === 'desc'; + } else { + $descending = false; + } } - else if(is_array($definition) && isset($definition['default'])) - $descending=$definition['default']==='desc'; - else - $descending=false; - if($this->multiSort) - $directions=array_merge(array($attribute=>$descending),$directions); - else - $directions=array($attribute=>$descending); + if ($this->multiSort) { + $directions = array_merge(array($attribute => $descending), $directions); + } else { + $directions = array($attribute => $descending); + } - $url=$this->createUrl(\Yii::$application->getController(),$directions); + $url = $this->createUrl(\Yii::$application->getController(), $directions); - return $this->createLink($attribute,$label,$url,$htmlOptions); + return $this->createLink($attribute, $label, $url, $htmlOptions); } /** @@ -318,18 +322,21 @@ class CSort extends CComponent */ public function resolveLabel($attribute) { - $definition=$this->resolveAttribute($attribute); - if(is_array($definition)) - { - if(isset($definition['label'])) + $definition = $this->resolveAttribute($attribute); + if (is_array($definition)) { + if (isset($definition['label'])) { return $definition['label']; + } + } else { + if (is_string($definition)) { + $attribute = $definition; + } } - else if(is_string($definition)) - $attribute=$definition; - if($this->modelClass!==null) + if ($this->modelClass !== null) { return CActiveRecord::model($this->modelClass)->getAttributeLabel($attribute); - else + } else { return $attribute; + } } /** @@ -340,33 +347,31 @@ class CSort extends CComponent */ public function getDirections() { - if($this->_directions===null) - { - $this->_directions=array(); - if(isset($_GET[$this->sortVar]) && is_string($_GET[$this->sortVar])) - { - $attributes=explode($this->separators[0],$_GET[$this->sortVar]); - foreach($attributes as $attribute) - { - if(($pos=strrpos($attribute,$this->separators[1]))!==false) - { - $descending=substr($attribute,$pos+1)===$this->descTag; - if($descending) - $attribute=substr($attribute,0,$pos); + if ($this->_directions === null) { + $this->_directions = array(); + if (isset($_GET[$this->sortVar]) && is_string($_GET[$this->sortVar])) { + $attributes = explode($this->separators[0], $_GET[$this->sortVar]); + foreach ($attributes as $attribute) { + if (($pos = strrpos($attribute, $this->separators[1])) !== false) { + $descending = substr($attribute, $pos + 1) === $this->descTag; + if ($descending) { + $attribute = substr($attribute, 0, $pos); + } + } else { + $descending = false; } - else - $descending=false; - if(($this->resolveAttribute($attribute))!==false) - { - $this->_directions[$attribute]=$descending; - if(!$this->multiSort) + if (($this->resolveAttribute($attribute)) !== false) { + $this->_directions[$attribute] = $descending; + if (!$this->multiSort) { return $this->_directions; + } } } } - if($this->_directions===array() && is_array($this->defaultOrder)) - $this->_directions=$this->defaultOrder; + if ($this->_directions === array() && is_array($this->defaultOrder)) { + $this->_directions = $this->defaultOrder; + } } return $this->_directions; } @@ -392,14 +397,15 @@ class CSort extends CComponent * CSort::SORT_DESC for descending order. * @return string the URL for sorting */ - public function createUrl($controller,$directions) + public function createUrl($controller, $directions) { - $sorts=array(); - foreach($directions as $attribute=>$descending) - $sorts[]=$descending ? $attribute.$this->separators[1].$this->descTag : $attribute; - $params=$this->params===null ? $_GET : $this->params; - $params[$this->sortVar]=implode($this->separators[0],$sorts); - return $controller->createUrl($this->route,$params); + $sorts = array(); + foreach ($directions as $attribute => $descending) { + $sorts[] = $descending ? $attribute . $this->separators[1] . $this->descTag : $attribute; + } + $params = $this->params === null ? $_GET : $this->params; + $params[$this->sortVar] = implode($this->separators[0], $sorts); + return $controller->createUrl($this->route, $params); } /** @@ -419,26 +425,31 @@ class CSort extends CComponent */ public function resolveAttribute($attribute) { - if($this->attributes!==array()) - $attributes=$this->attributes; - else if($this->modelClass!==null) - $attributes=CActiveRecord::model($this->modelClass)->attributeNames(); - else - return false; - foreach($attributes as $name=>$definition) - { - if(is_string($name)) - { - if($name===$attribute) - return $definition; + if ($this->attributes !== array()) { + $attributes = $this->attributes; + } else { + if ($this->modelClass !== null) { + $attributes = CActiveRecord::model($this->modelClass)->attributeNames(); + } else { + return false; } - else if($definition==='*') - { - if($this->modelClass!==null && CActiveRecord::model($this->modelClass)->hasAttribute($attribute)) - return $attribute; + } + foreach ($attributes as $name => $definition) { + if (is_string($name)) { + if ($name === $attribute) { + return $definition; + } + } else { + if ($definition === '*') { + if ($this->modelClass !== null && CActiveRecord::model($this->modelClass)->hasAttribute($attribute)) { + return $attribute; + } + } else { + if ($definition === $attribute) { + return $attribute; + } + } } - else if($definition===$attribute) - return $attribute; } return false; } @@ -452,8 +463,8 @@ class CSort extends CComponent * @param array $htmlOptions additional HTML options * @return string the generated hyperlink */ - protected function createLink($attribute,$label,$url,$htmlOptions) + protected function createLink($attribute, $label, $url, $htmlOptions) { - return CHtml::link($label,$url,$htmlOptions); + return CHtml::link($label, $url, $htmlOptions); } } \ No newline at end of file