From de021710e1c0dae732e61ecb42a9ac60440f55ee Mon Sep 17 00:00:00 2001 From: "godzilla80@gmx.net" <> Date: Thu, 19 Mar 2009 21:20:47 +0000 Subject: replace is_null() function calls with native native language constuct --- framework/Web/THttpResponse.php | 1174 ++++++++-------- .../UI/ActiveControls/TActiveControlAdapter.php | 20 +- .../UI/ActiveControls/TActiveCustomValidator.php | 4 +- .../Web/UI/ActiveControls/TActivePageAdapter.php | 738 +++++----- framework/Web/UI/ActiveControls/TAutoComplete.php | 4 +- .../Web/UI/ActiveControls/TBaseActiveControl.php | 10 +- .../UI/ActiveControls/TCallbackClientScript.php | 138 +- .../Web/UI/ActiveControls/TCallbackClientSide.php | 20 +- .../Web/UI/ActiveControls/TCallbackOptions.php | 4 +- .../Web/UI/ActiveControls/TInPlaceTextBox.php | 44 +- framework/Web/UI/WebControls/TBaseValidator.php | 1466 ++++++++++---------- framework/Web/UI/WebControls/TColorPicker.php | 2 +- framework/Web/UI/WebControls/TDatePicker.php | 6 +- framework/Web/UI/WebControls/THtmlArea.php | 4 +- framework/Web/UI/WebControls/TListControl.php | 2 +- framework/Web/UI/WebControls/TStyle.php | 6 +- .../Web/UI/WebControls/TValidationSummary.php | 6 +- 17 files changed, 1824 insertions(+), 1824 deletions(-) (limited to 'framework/Web') diff --git a/framework/Web/THttpResponse.php b/framework/Web/THttpResponse.php index 81087ef7..e3373855 100644 --- a/framework/Web/THttpResponse.php +++ b/framework/Web/THttpResponse.php @@ -1,587 +1,587 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Web - */ - -/** - * Includes the THttpResponse adapter. - */ -Prado::using('System.Web.THttpResponseAdapter'); - -/** - * THttpResponse class - * - * THttpResponse implements the mechanism for sending output to client users. - * - * To output a string to client, use {@link write()}. By default, the output is - * buffered until {@link flush()} is called or the application ends. The output in - * the buffer can also be cleaned by {@link clear()}. To disable output buffering, - * set BufferOutput property to false. - * - * To send cookies to client, use {@link getCookies()}. - * To redirect client browser to a new URL, use {@link redirect()}. - * To send a file to client, use {@link writeFile()}. - * - * By default, THttpResponse is registered with {@link TApplication} as the - * response module. It can be accessed via {@link TApplication::getResponse()}. - * - * THttpResponse may be configured in application configuration file as follows - * - * - * - * where {@link getCacheExpire CacheExpire}, {@link getCacheControl CacheControl} - * and {@link getBufferOutput BufferOutput} are optional properties of THttpResponse. - * - * THttpResponse sends charset header if either {@link setCharset() Charset} - * or {@link TGlobalization::setCharset() TGlobalization.Charset} is set. - * - * Since 3.1.2, HTTP status code can be set with the {@link setStatusCode StatusCode} property. - * - * Note: Some HTTP Status codes can require additional header or body information. So, if you use {@link setStatusCode StatusCode} - * in your application, be sure to add theses informations. - * E.g : to make an http authentication : - * - * public function clickAuth ($sender, $param) - * { - * $response=$this->getResponse(); - * $response->setStatusCode(401); - * $response->appendHeader('WWW-Authenticate: Basic realm="Test"'); - * } - * - * - * This event handler will sent the 401 status code (Unauthorized) to the browser, with the WWW-Authenticate header field. This - * will force the browser to ask for a username and a password. - * - * @author Qiang Xue - * @version $Id$ - * @package System.Web - * @since 3.0 - */ -class THttpResponse extends TModule implements ITextWriter -{ - /** - * @var The differents defined status code by RFC 2616 {@link http://www.faqs.org/rfcs/rfc2616} - */ - private static $HTTP_STATUS_CODES = array( - 100 => 'Continue', 101 => 'Switching Protocols', - 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', - 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', - 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', - 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported' - ); - - /** - * @var boolean whether to buffer output - */ - private $_bufferOutput=true; - /** - * @var boolean if the application is initialized - */ - private $_initialized=false; - /** - * @var THttpCookieCollection list of cookies to return - */ - private $_cookies=null; - /** - * @var integer response status code - */ - private $_status=200; - /** - * @var string reason correspond to status code - */ - private $_reason='OK'; - /** - * @var string HTML writer type - */ - private $_htmlWriterType='System.Web.UI.THtmlWriter'; - /** - * @var string content type - */ - private $_contentType=null; - /** - * @var string character set, e.g. UTF-8 - */ - private $_charset=''; - /** - * @var THttpResponseAdapter adapter. - */ - private $_adapter; - - /** - * Destructor. - * Flushes any existing content in buffer. - */ - public function __destruct() - { - //if($this->_bufferOutput) - // @ob_end_flush(); - } - - /** - * @param THttpResponseAdapter response adapter - */ - public function setAdapter(THttpResponseAdapter $adapter) - { - $this->_adapter=$adapter; - } - - /** - * @return THttpResponseAdapter response adapter, null if not exist. - */ - public function getAdapter() - { - return $this->_adapter; - } - - /** - * @return boolean true if adapter exists, false otherwise. - */ - public function getHasAdapter() - { - return !is_null($this->_adapter); - } - - /** - * Initializes the module. - * This method is required by IModule and is invoked by application. - * It starts output buffer if it is enabled. - * @param TXmlElement module configuration - */ - public function init($config) - { - if($this->_bufferOutput) - ob_start(); - $this->_initialized=true; - $this->getApplication()->setResponse($this); - } - - /** - * @return integer time-to-live for cached session pages in minutes, this has no effect for nocache limiter. Defaults to 180. - */ - public function getCacheExpire() - { - return session_cache_expire(); - } - - /** - * @param integer time-to-live for cached session pages in minutes, this has no effect for nocache limiter. - */ - public function setCacheExpire($value) - { - session_cache_expire(TPropertyValue::ensureInteger($value)); - } - - /** - * @return string cache control method to use for session pages - */ - public function getCacheControl() - { - return session_cache_limiter(); - } - - /** - * @param string cache control method to use for session pages. Valid values - * include none/nocache/private/private_no_expire/public - */ - public function setCacheControl($value) - { - session_cache_limiter(TPropertyValue::ensureEnum($value,array('none','nocache','private','private_no_expire','public'))); - } - - /** - * @return string content type, default is text/html - */ - public function setContentType($type) - { - $this->_contentType = $type; - } - - /** - * @return string current content type - */ - public function getContentType() - { - return $this->_contentType; - } - - /** - * @return string output charset. - */ - public function getCharset() - { - return $this->_charset; - } - - /** - * @param string output charset. - */ - public function setCharset($charset) - { - $this->_charset = $charset; - } - - /** - * @return boolean whether to enable output buffer - */ - public function getBufferOutput() - { - return $this->_bufferOutput; - } - - /** - * @param boolean whether to enable output buffer - * @throws TInvalidOperationException if session is started already - */ - public function setBufferOutput($value) - { - if($this->_initialized) - throw new TInvalidOperationException('httpresponse_bufferoutput_unchangeable'); - else - $this->_bufferOutput=TPropertyValue::ensureBoolean($value); - } - - /** - * @return integer HTTP status code, defaults to 200 - */ - public function getStatusCode() - { - return $this->_status; - } - - /** - * Set the HTTP status code for the response. - * The code and its reason will be sent to client using the currently requested http protocol version (see {@link THttpRequest::getHttpProtocolVersion}) - * Keep in mind that HTTP/1.0 clients might not understand all status codes from HTTP/1.1 - * - * @param integer HTTP status code - * @param string HTTP status reason, defaults to standard HTTP reasons - */ - public function setStatusCode($status, $reason=null) - { - $status=TPropertyValue::ensureInteger($status); - if(isset(self::$HTTP_STATUS_CODES[$status])) { - $this->_reason=self::$HTTP_STATUS_CODES[$status]; - }else{ - if($reason===null || $reason==='') { - throw new TInvalidDataValueException("response_status_reason_missing"); - } - $reason=TPropertyValue::ensureString($reason); - if(strpos($reason, "\r")!=false || strpos($reason, "\n")!=false) { - throw new TInvalidDataValueException("response_status_reason_barchars"); - } - $this->_reason=$reason; - } - $this->_status=$status; - } - - /** - * @param string HTTP status reason - */ - public function getStatusReason() { - return $this->_reason; - } - - /** - * @return THttpCookieCollection list of output cookies - */ - public function getCookies() - { - if($this->_cookies===null) - $this->_cookies=new THttpCookieCollection($this); - return $this->_cookies; - } - - /** - * Outputs a string. - * It may not be sent back to user immediately if output buffer is enabled. - * @param string string to be output - */ - public function write($str) - { - echo $str; - } - - /** - * Sends a file back to user. - * Make sure not to output anything else after calling this method. - * @param string file name - * @param string content to be set. If null, the content will be read from the server file pointed to by $fileName. - * @param string mime type of the content. - * @param array list of headers to be sent. Each array element represents a header string (e.g. 'Content-Type: text/plain'). - * @throws TInvalidDataValueException if the file cannot be found - */ - public function writeFile($fileName,$content=null,$mimeType=null,$headers=null) - { - static $defaultMimeTypes=array( - 'css'=>'text/css', - 'gif'=>'image/gif', - 'jpg'=>'image/jpeg', - 'jpeg'=>'image/jpeg', - 'htm'=>'text/html', - 'html'=>'text/html', - 'js'=>'javascript/js', - 'pdf'=>'application/pdf', - 'xls'=>'application/vnd.ms-excel', - ); - - if($mimeType===null) - { - $mimeType='text/plain'; - if(function_exists('mime_content_type')) - $mimeType=mime_content_type($fileName); - else if(($ext=strrchr($fileName,'.'))!==false) - { - $ext=substr($ext,1); - if(isset($defaultMimeTypes[$ext])) - $mimeType=$defaultMimeTypes[$ext]; - } - } - $fn=basename($fileName); - $this->sendHttpHeader(); - if(is_array($headers)) - { - foreach($headers as $h) - header($h); - } - else - { - header('Pragma: public'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - } - header("Content-type: $mimeType"); - header('Content-Length: '.($content===null?filesize($fileName):strlen($content))); - header("Content-Disposition: attachment; filename=\"$fn\""); - header('Content-Transfer-Encoding: binary'); - if($content===null) - readfile($fileName); - else - echo $content; - } - - /** - * Redirects the browser to the specified URL. - * The current application will be terminated after this method is invoked. - * @param string URL to be redirected to. If the URL is a relative one, the base URL of - * the current request will be inserted at the beginning. - */ - public function redirect($url) - { - if($this->getHasAdapter()) - $this->_adapter->httpRedirect($url); - else - $this->httpRedirect($url); - } - - /** - * Redirect the browser to another URL and exists the current application. - * This method is used internally. Please use {@link redirect} instead. - * - * @since 3.1.5 - * You can set the set {@link setStatusCode StatusCode} to a value between 300 and 399 before - * calling this function to change the type of redirection. - * If not specified, StatusCode will be 302 (Found) by default - * - * @param string URL to be redirected to. If the URL is a relative one, the base URL of - * the current request will be inserted at the beginning. - */ - public function httpRedirect($url) - { - if(!$this->getApplication()->getRequestCompleted()) - $this->getApplication()->onEndRequest(); - if($url[0]==='/') - $url=$this->getRequest()->getBaseUrl().$url; - if ($this->_status >= 300 && $this->_status < 400) - // The status code has been modified to a valid redirection status, send it - header('Location: '.str_replace('&','&',$url), true, $this->_status); - else - header('Location: '.str_replace('&','&',$url)); - - exit(); - } - - /** - * Reloads the current page. - * The effect of this method call is the same as user pressing the - * refresh button on his browser (without post data). - **/ - public function reload() - { - $this->redirect($this->getRequest()->getRequestUri()); - } - - /** - * Flush the response contents and headers. - */ - public function flush() - { - if($this->getHasAdapter()) - $this->_adapter->flushContent(); - else - $this->flushContent(); - } - - /** - * Outputs the buffered content, sends content-type and charset header. - * This method is used internally. Please use {@link flush} instead. - */ - public function flushContent() - { - Prado::trace("Flushing output",'System.Web.THttpResponse'); - $this->sendHttpHeader(); - $this->sendContentTypeHeader(); - if($this->_bufferOutput) - ob_flush(); - } - - /** - * Send the HTTP header with the status code (defaults to 200) and status reason (defaults to OK) - */ - protected function sendHttpHeader () - { - if (($version=$this->getRequest()->getHttpProtocolVersion())==='') - header (' ', true, $this->_status); - else - header($version.' '.$this->_status.' '.$this->_reason, true, $this->_status); - } - - /** - * Sends content type header if charset is not empty. - */ - protected function sendContentTypeHeader() - { - $charset=$this->getCharset(); - if($charset==='' && ($globalization=$this->getApplication()->getGlobalization(false))!==null) - $charset=$globalization->getCharset(); - if($charset!=='') - { - $contentType=$this->_contentType===null?'text/html':$this->_contentType; - $this->appendHeader('Content-Type: '.$contentType.';charset='.$charset); - } - else if($this->_contentType!==null) - $this->appendHeader('Content-Type: '.$this->_contentType.';charset=UTF-8'); - } - - /** - * Returns the content in the output buffer. - * The buffer will NOT be cleared after calling this method. - * Use {@link clear()} is you want to clear the buffer. - * @return string output that is in the buffer. - */ - public function getContents() - { - Prado::trace("Retrieving output",'System.Web.THttpResponse'); - return $this->_bufferOutput?ob_get_contents():''; - } - - /** - * Clears any existing buffered content. - */ - public function clear() - { - if($this->_bufferOutput) - ob_clean(); - Prado::trace("Clearing output",'System.Web.THttpResponse'); - } - - /** - * Sends a header. - * @param string header - */ - public function appendHeader($value) - { - Prado::trace("Sending header '$value'",'System.Web.THttpResponse'); - header($value); - } - - /** - * Writes a log message into error log. - * This method is simple wrapper of PHP function error_log. - * @param string The error message that should be logged - * @param integer where the error should go - * @param string The destination. Its meaning depends on the message parameter as described above - * @param string The extra headers. It's used when the message parameter is set to 1. This message type uses the same internal function as mail() does. - * @see http://us2.php.net/manual/en/function.error-log.php - */ - public function appendLog($message,$messageType=0,$destination='',$extraHeaders='') - { - error_log($message,$messageType,$destination,$extraHeaders); - } - - /** - * Sends a cookie. - * Do not call this method directly. Operate with the result of {@link getCookies} instead. - * @param THttpCookie cook to be sent - */ - public function addCookie($cookie) - { - $request=$this->getRequest(); - if($request->getEnableCookieValidation()) - { - $value=$this->getApplication()->getSecurityManager()->hashData($cookie->getValue()); - setcookie($cookie->getName(),$value,$cookie->getExpire(),$cookie->getPath(),$cookie->getDomain(),$cookie->getSecure()); - } - else - setcookie($cookie->getName(),$cookie->getValue(),$cookie->getExpire(),$cookie->getPath(),$cookie->getDomain(),$cookie->getSecure()); - } - - /** - * Deletes a cookie. - * Do not call this method directly. Operate with the result of {@link getCookies} instead. - * @param THttpCookie cook to be deleted - */ - public function removeCookie($cookie) - { - setcookie($cookie->getName(),null,0,$cookie->getPath(),$cookie->getDomain(),$cookie->getSecure()); - } - - /** - * @return string the type of HTML writer to be used, defaults to THtmlWriter - */ - public function getHtmlWriterType() - { - return $this->_htmlWriterType; - } - - /** - * @param string the type of HTML writer to be used, may be the class name or the namespace - */ - public function setHtmlWriterType($value) - { - $this->_htmlWriterType=$value; - } - - /** - * Creates a new instance of HTML writer. - * If the type of the HTML writer is not supplied, {@link getHtmlWriterType HtmlWriterType} will be assumed. - * @param string type of the HTML writer to be created. If null, {@link getHtmlWriterType HtmlWriterType} will be assumed. - */ - public function createHtmlWriter($type=null) - { - if($type===null) - $type=$this->getHtmlWriterType(); - if($this->getHasAdapter()) - return $this->_adapter->createNewHtmlWriter($type, $this); - else - return $this->createNewHtmlWriter($type, $this); - } - - /** - * Create a new html writer instance. - * This method is used internally. Please use {@link createHtmlWriter} instead. - * @param string type of HTML writer to be created. - * @param ITextWriter text writer holding the contents. - */ - public function createNewHtmlWriter($type, $writer) - { - return Prado::createComponent($type, $writer); - } -} - + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2008 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web + */ + +/** + * Includes the THttpResponse adapter. + */ +Prado::using('System.Web.THttpResponseAdapter'); + +/** + * THttpResponse class + * + * THttpResponse implements the mechanism for sending output to client users. + * + * To output a string to client, use {@link write()}. By default, the output is + * buffered until {@link flush()} is called or the application ends. The output in + * the buffer can also be cleaned by {@link clear()}. To disable output buffering, + * set BufferOutput property to false. + * + * To send cookies to client, use {@link getCookies()}. + * To redirect client browser to a new URL, use {@link redirect()}. + * To send a file to client, use {@link writeFile()}. + * + * By default, THttpResponse is registered with {@link TApplication} as the + * response module. It can be accessed via {@link TApplication::getResponse()}. + * + * THttpResponse may be configured in application configuration file as follows + * + * + * + * where {@link getCacheExpire CacheExpire}, {@link getCacheControl CacheControl} + * and {@link getBufferOutput BufferOutput} are optional properties of THttpResponse. + * + * THttpResponse sends charset header if either {@link setCharset() Charset} + * or {@link TGlobalization::setCharset() TGlobalization.Charset} is set. + * + * Since 3.1.2, HTTP status code can be set with the {@link setStatusCode StatusCode} property. + * + * Note: Some HTTP Status codes can require additional header or body information. So, if you use {@link setStatusCode StatusCode} + * in your application, be sure to add theses informations. + * E.g : to make an http authentication : + * + * public function clickAuth ($sender, $param) + * { + * $response=$this->getResponse(); + * $response->setStatusCode(401); + * $response->appendHeader('WWW-Authenticate: Basic realm="Test"'); + * } + * + * + * This event handler will sent the 401 status code (Unauthorized) to the browser, with the WWW-Authenticate header field. This + * will force the browser to ask for a username and a password. + * + * @author Qiang Xue + * @version $Id$ + * @package System.Web + * @since 3.0 + */ +class THttpResponse extends TModule implements ITextWriter +{ + /** + * @var The differents defined status code by RFC 2616 {@link http://www.faqs.org/rfcs/rfc2616} + */ + private static $HTTP_STATUS_CODES = array( + 100 => 'Continue', 101 => 'Switching Protocols', + 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', + 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', + 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', + 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported' + ); + + /** + * @var boolean whether to buffer output + */ + private $_bufferOutput=true; + /** + * @var boolean if the application is initialized + */ + private $_initialized=false; + /** + * @var THttpCookieCollection list of cookies to return + */ + private $_cookies=null; + /** + * @var integer response status code + */ + private $_status=200; + /** + * @var string reason correspond to status code + */ + private $_reason='OK'; + /** + * @var string HTML writer type + */ + private $_htmlWriterType='System.Web.UI.THtmlWriter'; + /** + * @var string content type + */ + private $_contentType=null; + /** + * @var string character set, e.g. UTF-8 + */ + private $_charset=''; + /** + * @var THttpResponseAdapter adapter. + */ + private $_adapter; + + /** + * Destructor. + * Flushes any existing content in buffer. + */ + public function __destruct() + { + //if($this->_bufferOutput) + // @ob_end_flush(); + } + + /** + * @param THttpResponseAdapter response adapter + */ + public function setAdapter(THttpResponseAdapter $adapter) + { + $this->_adapter=$adapter; + } + + /** + * @return THttpResponseAdapter response adapter, null if not exist. + */ + public function getAdapter() + { + return $this->_adapter; + } + + /** + * @return boolean true if adapter exists, false otherwise. + */ + public function getHasAdapter() + { + return $this->_adapter!==null; + } + + /** + * Initializes the module. + * This method is required by IModule and is invoked by application. + * It starts output buffer if it is enabled. + * @param TXmlElement module configuration + */ + public function init($config) + { + if($this->_bufferOutput) + ob_start(); + $this->_initialized=true; + $this->getApplication()->setResponse($this); + } + + /** + * @return integer time-to-live for cached session pages in minutes, this has no effect for nocache limiter. Defaults to 180. + */ + public function getCacheExpire() + { + return session_cache_expire(); + } + + /** + * @param integer time-to-live for cached session pages in minutes, this has no effect for nocache limiter. + */ + public function setCacheExpire($value) + { + session_cache_expire(TPropertyValue::ensureInteger($value)); + } + + /** + * @return string cache control method to use for session pages + */ + public function getCacheControl() + { + return session_cache_limiter(); + } + + /** + * @param string cache control method to use for session pages. Valid values + * include none/nocache/private/private_no_expire/public + */ + public function setCacheControl($value) + { + session_cache_limiter(TPropertyValue::ensureEnum($value,array('none','nocache','private','private_no_expire','public'))); + } + + /** + * @return string content type, default is text/html + */ + public function setContentType($type) + { + $this->_contentType = $type; + } + + /** + * @return string current content type + */ + public function getContentType() + { + return $this->_contentType; + } + + /** + * @return string output charset. + */ + public function getCharset() + { + return $this->_charset; + } + + /** + * @param string output charset. + */ + public function setCharset($charset) + { + $this->_charset = $charset; + } + + /** + * @return boolean whether to enable output buffer + */ + public function getBufferOutput() + { + return $this->_bufferOutput; + } + + /** + * @param boolean whether to enable output buffer + * @throws TInvalidOperationException if session is started already + */ + public function setBufferOutput($value) + { + if($this->_initialized) + throw new TInvalidOperationException('httpresponse_bufferoutput_unchangeable'); + else + $this->_bufferOutput=TPropertyValue::ensureBoolean($value); + } + + /** + * @return integer HTTP status code, defaults to 200 + */ + public function getStatusCode() + { + return $this->_status; + } + + /** + * Set the HTTP status code for the response. + * The code and its reason will be sent to client using the currently requested http protocol version (see {@link THttpRequest::getHttpProtocolVersion}) + * Keep in mind that HTTP/1.0 clients might not understand all status codes from HTTP/1.1 + * + * @param integer HTTP status code + * @param string HTTP status reason, defaults to standard HTTP reasons + */ + public function setStatusCode($status, $reason=null) + { + $status=TPropertyValue::ensureInteger($status); + if(isset(self::$HTTP_STATUS_CODES[$status])) { + $this->_reason=self::$HTTP_STATUS_CODES[$status]; + }else{ + if($reason===null || $reason==='') { + throw new TInvalidDataValueException("response_status_reason_missing"); + } + $reason=TPropertyValue::ensureString($reason); + if(strpos($reason, "\r")!=false || strpos($reason, "\n")!=false) { + throw new TInvalidDataValueException("response_status_reason_barchars"); + } + $this->_reason=$reason; + } + $this->_status=$status; + } + + /** + * @param string HTTP status reason + */ + public function getStatusReason() { + return $this->_reason; + } + + /** + * @return THttpCookieCollection list of output cookies + */ + public function getCookies() + { + if($this->_cookies===null) + $this->_cookies=new THttpCookieCollection($this); + return $this->_cookies; + } + + /** + * Outputs a string. + * It may not be sent back to user immediately if output buffer is enabled. + * @param string string to be output + */ + public function write($str) + { + echo $str; + } + + /** + * Sends a file back to user. + * Make sure not to output anything else after calling this method. + * @param string file name + * @param string content to be set. If null, the content will be read from the server file pointed to by $fileName. + * @param string mime type of the content. + * @param array list of headers to be sent. Each array element represents a header string (e.g. 'Content-Type: text/plain'). + * @throws TInvalidDataValueException if the file cannot be found + */ + public function writeFile($fileName,$content=null,$mimeType=null,$headers=null) + { + static $defaultMimeTypes=array( + 'css'=>'text/css', + 'gif'=>'image/gif', + 'jpg'=>'image/jpeg', + 'jpeg'=>'image/jpeg', + 'htm'=>'text/html', + 'html'=>'text/html', + 'js'=>'javascript/js', + 'pdf'=>'application/pdf', + 'xls'=>'application/vnd.ms-excel', + ); + + if($mimeType===null) + { + $mimeType='text/plain'; + if(function_exists('mime_content_type')) + $mimeType=mime_content_type($fileName); + else if(($ext=strrchr($fileName,'.'))!==false) + { + $ext=substr($ext,1); + if(isset($defaultMimeTypes[$ext])) + $mimeType=$defaultMimeTypes[$ext]; + } + } + $fn=basename($fileName); + $this->sendHttpHeader(); + if(is_array($headers)) + { + foreach($headers as $h) + header($h); + } + else + { + header('Pragma: public'); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + } + header("Content-type: $mimeType"); + header('Content-Length: '.($content===null?filesize($fileName):strlen($content))); + header("Content-Disposition: attachment; filename=\"$fn\""); + header('Content-Transfer-Encoding: binary'); + if($content===null) + readfile($fileName); + else + echo $content; + } + + /** + * Redirects the browser to the specified URL. + * The current application will be terminated after this method is invoked. + * @param string URL to be redirected to. If the URL is a relative one, the base URL of + * the current request will be inserted at the beginning. + */ + public function redirect($url) + { + if($this->getHasAdapter()) + $this->_adapter->httpRedirect($url); + else + $this->httpRedirect($url); + } + + /** + * Redirect the browser to another URL and exists the current application. + * This method is used internally. Please use {@link redirect} instead. + * + * @since 3.1.5 + * You can set the set {@link setStatusCode StatusCode} to a value between 300 and 399 before + * calling this function to change the type of redirection. + * If not specified, StatusCode will be 302 (Found) by default + * + * @param string URL to be redirected to. If the URL is a relative one, the base URL of + * the current request will be inserted at the beginning. + */ + public function httpRedirect($url) + { + if(!$this->getApplication()->getRequestCompleted()) + $this->getApplication()->onEndRequest(); + if($url[0]==='/') + $url=$this->getRequest()->getBaseUrl().$url; + if ($this->_status >= 300 && $this->_status < 400) + // The status code has been modified to a valid redirection status, send it + header('Location: '.str_replace('&','&',$url), true, $this->_status); + else + header('Location: '.str_replace('&','&',$url)); + + exit(); + } + + /** + * Reloads the current page. + * The effect of this method call is the same as user pressing the + * refresh button on his browser (without post data). + **/ + public function reload() + { + $this->redirect($this->getRequest()->getRequestUri()); + } + + /** + * Flush the response contents and headers. + */ + public function flush() + { + if($this->getHasAdapter()) + $this->_adapter->flushContent(); + else + $this->flushContent(); + } + + /** + * Outputs the buffered content, sends content-type and charset header. + * This method is used internally. Please use {@link flush} instead. + */ + public function flushContent() + { + Prado::trace("Flushing output",'System.Web.THttpResponse'); + $this->sendHttpHeader(); + $this->sendContentTypeHeader(); + if($this->_bufferOutput) + ob_flush(); + } + + /** + * Send the HTTP header with the status code (defaults to 200) and status reason (defaults to OK) + */ + protected function sendHttpHeader () + { + if (($version=$this->getRequest()->getHttpProtocolVersion())==='') + header (' ', true, $this->_status); + else + header($version.' '.$this->_status.' '.$this->_reason, true, $this->_status); + } + + /** + * Sends content type header if charset is not empty. + */ + protected function sendContentTypeHeader() + { + $charset=$this->getCharset(); + if($charset==='' && ($globalization=$this->getApplication()->getGlobalization(false))!==null) + $charset=$globalization->getCharset(); + if($charset!=='') + { + $contentType=$this->_contentType===null?'text/html':$this->_contentType; + $this->appendHeader('Content-Type: '.$contentType.';charset='.$charset); + } + else if($this->_contentType!==null) + $this->appendHeader('Content-Type: '.$this->_contentType.';charset=UTF-8'); + } + + /** + * Returns the content in the output buffer. + * The buffer will NOT be cleared after calling this method. + * Use {@link clear()} is you want to clear the buffer. + * @return string output that is in the buffer. + */ + public function getContents() + { + Prado::trace("Retrieving output",'System.Web.THttpResponse'); + return $this->_bufferOutput?ob_get_contents():''; + } + + /** + * Clears any existing buffered content. + */ + public function clear() + { + if($this->_bufferOutput) + ob_clean(); + Prado::trace("Clearing output",'System.Web.THttpResponse'); + } + + /** + * Sends a header. + * @param string header + */ + public function appendHeader($value) + { + Prado::trace("Sending header '$value'",'System.Web.THttpResponse'); + header($value); + } + + /** + * Writes a log message into error log. + * This method is simple wrapper of PHP function error_log. + * @param string The error message that should be logged + * @param integer where the error should go + * @param string The destination. Its meaning depends on the message parameter as described above + * @param string The extra headers. It's used when the message parameter is set to 1. This message type uses the same internal function as mail() does. + * @see http://us2.php.net/manual/en/function.error-log.php + */ + public function appendLog($message,$messageType=0,$destination='',$extraHeaders='') + { + error_log($message,$messageType,$destination,$extraHeaders); + } + + /** + * Sends a cookie. + * Do not call this method directly. Operate with the result of {@link getCookies} instead. + * @param THttpCookie cook to be sent + */ + public function addCookie($cookie) + { + $request=$this->getRequest(); + if($request->getEnableCookieValidation()) + { + $value=$this->getApplication()->getSecurityManager()->hashData($cookie->getValue()); + setcookie($cookie->getName(),$value,$cookie->getExpire(),$cookie->getPath(),$cookie->getDomain(),$cookie->getSecure()); + } + else + setcookie($cookie->getName(),$cookie->getValue(),$cookie->getExpire(),$cookie->getPath(),$cookie->getDomain(),$cookie->getSecure()); + } + + /** + * Deletes a cookie. + * Do not call this method directly. Operate with the result of {@link getCookies} instead. + * @param THttpCookie cook to be deleted + */ + public function removeCookie($cookie) + { + setcookie($cookie->getName(),null,0,$cookie->getPath(),$cookie->getDomain(),$cookie->getSecure()); + } + + /** + * @return string the type of HTML writer to be used, defaults to THtmlWriter + */ + public function getHtmlWriterType() + { + return $this->_htmlWriterType; + } + + /** + * @param string the type of HTML writer to be used, may be the class name or the namespace + */ + public function setHtmlWriterType($value) + { + $this->_htmlWriterType=$value; + } + + /** + * Creates a new instance of HTML writer. + * If the type of the HTML writer is not supplied, {@link getHtmlWriterType HtmlWriterType} will be assumed. + * @param string type of the HTML writer to be created. If null, {@link getHtmlWriterType HtmlWriterType} will be assumed. + */ + public function createHtmlWriter($type=null) + { + if($type===null) + $type=$this->getHtmlWriterType(); + if($this->getHasAdapter()) + return $this->_adapter->createNewHtmlWriter($type, $this); + else + return $this->createNewHtmlWriter($type, $this); + } + + /** + * Create a new html writer instance. + * This method is used internally. Please use {@link createHtmlWriter} instead. + * @param string type of HTML writer to be created. + * @param ITextWriter text writer holding the contents. + */ + public function createNewHtmlWriter($type, $writer) + { + return Prado::createComponent($type, $writer); + } +} + diff --git a/framework/Web/UI/ActiveControls/TActiveControlAdapter.php b/framework/Web/UI/ActiveControls/TActiveControlAdapter.php index 34872f98..8c6ba430 100644 --- a/framework/Web/UI/ActiveControls/TActiveControlAdapter.php +++ b/framework/Web/UI/ActiveControls/TActiveControlAdapter.php @@ -64,7 +64,7 @@ class TActiveControlAdapter extends TControlAdapter */ protected function setBaseControlClass($type) { - if(is_null($type)) + if($type===null) { if($this->getControl() instanceof ICallbackEventHandler) $this->_activeControlType = 'TBaseActiveCallbackControl'; @@ -117,7 +117,7 @@ class TActiveControlAdapter extends TControlAdapter */ public function getBaseActiveControl() { - if(is_null($this->_baseActiveControl)) + if($this->_baseActiveControl===null) { $type = $this->_activeControlType; $this->_baseActiveControl = new $type($this->getControl()); @@ -161,7 +161,7 @@ class TActiveControlAdapter extends TControlAdapter */ public function saveState() { - if(!is_null($this->_stateTracker) + if(($this->_stateTracker!==null) && $this->getControl()->getActiveControl()->canUpdateClientSide()) { $this->_stateTracker->respondToChanges(); @@ -353,7 +353,7 @@ class TCallbackPageStateTracker */ protected function updateStyle($style) { - if(!is_null($style['CssClass'])) + if($style['CssClass']!==null) $this->client()->setAttribute($this->_control, 'class', $style['CssClass']); if(count($style['Style']) > 0) $this->client()->setStyle($this->_control, $style['Style']); @@ -487,9 +487,9 @@ class TStyleDiff extends TViewStateDiff */ protected function getCssClassDiff() { - if(is_null($this->_old)) + if($this->_old===null) { - return !is_null($this->_new) && $this->_new->hasCssClass() + return ($this->_new!==null) && $this->_new->hasCssClass() ? $this->_new->getCssClass() : null; } else @@ -515,13 +515,13 @@ class TStyleDiff extends TViewStateDiff */ public function getDifference() { - if(is_null($this->_new)) + if($this->_new===null) return $this->_null; else { $css = $this->getCssClassDiff(); $style = $this->getStyleDiff(); - if(!is_null($css) || !is_null($style)) + if(($css!==null) || ($style!==null)) return array('CssClass' => $css, 'Style' => $style); else $this->_null; @@ -546,9 +546,9 @@ class TMapCollectionDiff extends TViewStateDiff */ public function getDifference() { - if(is_null($this->_old)) + if($this->_old===null) { - return !is_null($this->_new) ? $this->_new->toArray() : $this->_null; + return ($this->_new!==null) ? $this->_new->toArray() : $this->_null; } else { diff --git a/framework/Web/UI/ActiveControls/TActiveCustomValidator.php b/framework/Web/UI/ActiveControls/TActiveCustomValidator.php index 6c74aa7d..1f719bf6 100644 --- a/framework/Web/UI/ActiveControls/TActiveCustomValidator.php +++ b/framework/Web/UI/ActiveControls/TActiveCustomValidator.php @@ -4,7 +4,7 @@ * * @author Wei Zhuo * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft * @license http://www.pradosoft.com/license/ * @version $Id$ * @package System.Web.UI.ActiveControls @@ -236,6 +236,6 @@ class TActiveCustomValidatorClientSide extends TCallbackClientSide public function getObserveChanges() { $changes = $this->getOption('ObserveChanges'); - return is_null($changes) ? true : $changes; + return ($changes===null) ? true : $changes; } } diff --git a/framework/Web/UI/ActiveControls/TActivePageAdapter.php b/framework/Web/UI/ActiveControls/TActivePageAdapter.php index c52f0775..90eed970 100644 --- a/framework/Web/UI/ActiveControls/TActivePageAdapter.php +++ b/framework/Web/UI/ActiveControls/TActivePageAdapter.php @@ -1,369 +1,369 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Web.UI.ActiveControls - */ - -/** - * Load callback response adapter class. - */ -Prado::using('System.Web.UI.ActiveControls.TCallbackResponseAdapter'); -Prado::using('System.Web.UI.ActiveControls.TCallbackClientScript'); -Prado::using('System.Web.UI.ActiveControls.TCallbackEventParameter'); - -/** - * TActivePageAdapter class. - * - * Callback request handler. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Web.UI.ActiveControls - * @since 3.1 - */ -class TActivePageAdapter extends TControlAdapter -{ - /** - * Callback response data header name. - */ - const CALLBACK_DATA_HEADER = 'X-PRADO-DATA'; - /** - * Callback response client-side action header name. - */ - const CALLBACK_ACTION_HEADER = 'X-PRADO-ACTIONS'; - /** - * Callback error header name. - */ - const CALLBACK_ERROR_HEADER = 'X-PRADO-ERROR'; - /** - * Callback page state header name. - */ - const CALLBACK_PAGESTATE_HEADER = 'X-PRADO-PAGESTATE'; - - /** - * Callback redirect url header name. - */ - const CALLBACK_REDIRECT = 'X-PRADO-REDIRECT'; - - /** - * @var ICallbackEventHandler callback event handler. - */ - private $_callbackEventTarget; - /** - * @var mixed callback event parameter. - */ - private $_callbackEventParameter; - /** - * @var TCallbackClientScript callback client script handler - */ - private $_callbackClient; - - private $_controlsToRender=array(); - - /** - * Constructor, trap errors and exception to let the callback response - * handle them. - */ - public function __construct(TPage $control) - { - parent::__construct($control); - - //TODO: can this be done later? - $response = $this->getApplication()->getResponse(); - $response->setAdapter(new TCallbackResponseAdapter($response)); - - $this->trapCallbackErrorsExceptions(); - } - - /** - * Process the callback request. - * @param THtmlWriter html content writer. - */ - public function processCallbackEvent($writer) - { - Prado::trace("ActivePage raiseCallbackEvent()",'System.Web.UI.ActiveControls.TActivePageAdapter'); - $this->raiseCallbackEvent(); - } - - /** - * Register a control for defered render() call. - * @param TControl control for defered rendering - * @param THtmlWriter the renderer - */ - public function registerControlToRender($control,$writer) - { - $id = $control->getUniqueID(); - if(!isset($this->_controlsToRender[$id])) - $this->_controlsToRender[$id] = array($control,$writer); - } - - /** - * Trap errors and exceptions to be handled by TCallbackErrorHandler. - */ - protected function trapCallbackErrorsExceptions() - { - $this->getApplication()->setErrorHandler(new TCallbackErrorHandler); - } - - /** - * Render the callback response. - * @param THtmlWriter html content writer. - */ - public function renderCallbackResponse($writer) - { - Prado::trace("ActivePage renderCallbackResponse()",'System.Web.UI.ActiveControls.TActivePageAdapter'); - if(($url = $this->getResponse()->getAdapter()->getRedirectedUrl())===null) - $this->renderResponse($writer); - else - $this->redirect($url); - } - - /** - * Redirect url on the client-side using javascript. - * @param string new url to load. - */ - protected function redirect($url) - { - Prado::trace("ActivePage redirect()",'System.Web.UI.ActiveControls.TActivePageAdapter'); - $this->appendContentPart($this->getResponse(), self::CALLBACK_REDIRECT, $url); - //$this->getResponse()->appendHeader(self::CALLBACK_REDIRECT.': '.$url); - } - - /** - * Renders the callback response by adding additional callback data and - * javascript actions in the header and page state if required. - * @param THtmlWriter html content writer. - */ - protected function renderResponse($writer) - { - Prado::trace("ActivePage renderResponse()",'System.Web.UI.ActiveControls.TActivePageAdapter'); - //renders all the defered render() calls. - foreach($this->_controlsToRender as $rid => $forRender) - $forRender[0]->render($forRender[1]); - - $response = $this->getResponse(); - - //send response data in header - if($response->getHasAdapter()) - { - $responseData = $response->getAdapter()->getResponseData(); - if(!is_null($responseData)) - { - $data = TJavaScript::jsonEncode($responseData); - - $this->appendContentPart($response, self::CALLBACK_DATA_HEADER, $data); - //$response->appendHeader(self::CALLBACK_DATA_HEADER.': '.$data); - } - } - - //sends page state in header - if(($handler = $this->getCallbackEventTarget()) !== null) - { - if($handler->getActiveControl()->getClientSide()->getEnablePageStateUpdate()) - { - $pagestate = $this->getPage()->getClientState(); - $this->appendContentPart($response, self::CALLBACK_PAGESTATE_HEADER, $pagestate); - //$response->appendHeader(self::CALLBACK_PAGESTATE_HEADER.': '.$pagestate); - } - } - - //safari must receive at least 1 byte of data. - $writer->write(" "); - - //output the end javascript - if($this->getPage()->getClientScript()->hasEndScripts()) - { - $writer = $response->createHtmlWriter(); - $this->getPage()->getClientScript()->renderEndScripts($writer); - $this->getPage()->getCallbackClient()->evaluateScript($writer); - } - - //output the actions - $executeJavascript = $this->getCallbackClientHandler()->getClientFunctionsToExecute(); - $actions = TJavaScript::jsonEncode($executeJavascript); - $this->appendContentPart($response, self::CALLBACK_ACTION_HEADER, $actions); - //$response->appendHeader(self::CALLBACK_ACTION_HEADER.': '.$actions); - } - - /** - * Appends data or javascript code to the body content surrounded with delimiters - */ - private function appendContentPart($response, $delimiter, $data) - { - $content = $response->createHtmlWriter(); - $content->getWriter()->setBoundary($delimiter); - $content->write($data); - } - - /** - * Trys to find the callback event handler and raise its callback event. - * @throws TInvalidCallbackException if call back target is not found. - * @throws TInvalidCallbackException if the requested target does not - * implement ICallbackEventHandler. - */ - private function raiseCallbackEvent() - { - if(($callbackHandler=$this->getCallbackEventTarget())!==null) - { - if($callbackHandler instanceof ICallbackEventHandler) - { - $param = $this->getCallbackEventParameter(); - $result = new TCallbackEventParameter($this->getResponse(), $param); - $callbackHandler->raiseCallbackEvent($result); - } - else - { - throw new TInvalidCallbackException( - 'callback_invalid_handler', $callbackHandler->getUniqueID()); - } - } - else - { - $target = $this->getRequest()->itemAt(TPage::FIELD_CALLBACK_TARGET); - throw new TInvalidCallbackException('callback_invalid_target', $target); - } - } - - /** - * @return TControl the control responsible for the current callback event, - * null if nonexistent - */ - public function getCallbackEventTarget() - { - if($this->_callbackEventTarget===null) - { - $eventTarget=$this->getRequest()->itemAt(TPage::FIELD_CALLBACK_TARGET); - if(!empty($eventTarget)) - $this->_callbackEventTarget=$this->getPage()->findControl($eventTarget); - } - return $this->_callbackEventTarget; - } - - /** - * Registers a control to raise callback event in the current request. - * @param TControl control registered to raise callback event. - */ - public function setCallbackEventTarget(TControl $control) - { - $this->_callbackEventTarget=$control; - } - - /** - * Gets callback parameter. JSON encoding is assumed. - * @return string postback event parameter - */ - public function getCallbackEventParameter() - { - if($this->_callbackEventParameter===null) - { - $param = $this->getRequest()->itemAt(TPage::FIELD_CALLBACK_PARAMETER); - if(strlen($param) > 0) - $this->_callbackEventParameter=TJavaScript::jsonDecode((string)$param); - } - return $this->_callbackEventParameter; - } - - /** - * @param mixed postback event parameter - */ - public function setCallbackEventParameter($value) - { - $this->_callbackEventParameter=$value; - } - - /** - * Gets the callback client script handler. It handlers the javascript functions - * to be executed during the callback response. - * @return TCallbackClientScript callback client handler. - */ - public function getCallbackClientHandler() - { - if(is_null($this->_callbackClient)) - $this->_callbackClient = new TCallbackClientScript; - return $this->_callbackClient; - } -} - -/** - * TCallbackErrorHandler class. - * - * Captures errors and exceptions and send them back during callback response. - * When the application is in debug mode, the error and exception stack trace - * are shown. A TJavascriptLogger must be present on the client-side to view - * the error stack trace. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Web.UI.ActiveControls - * @since 3.1 - */ -class TCallbackErrorHandler extends TErrorHandler -{ - /** - * Displays the exceptions to the client-side TJavascriptLogger. - * A HTTP 500 status code is sent and the stack trace is sent as JSON encoded. - * @param Exception exception details. - */ - protected function displayException($exception) - { - if($this->getApplication()->getMode()===TApplication::STATE_DEBUG) - { - $response = $this->getApplication()->getResponse(); - $trace = TJavaScript::jsonEncode($this->getExceptionStackTrace($exception)); - $response->appendHeader('HTTP/1.0 500 Internal Error'); - $response->appendHeader(TActivePageAdapter::CALLBACK_ERROR_HEADER.': '.$trace); - } - else - { - error_log("Error happened while processing an existing error:\n".$exception->__toString()); - header('HTTP/1.0 500 Internal Error'); - } - $this->getApplication()->getResponse()->flush(); - } - - /** - * @param Exception exception details. - * @return array exception stack trace details. - */ - private function getExceptionStackTrace($exception) - { - $data['code']=$exception->getCode() > 0 ? $exception->getCode() : 500; - $data['file']=$exception->getFile(); - $data['line']=$exception->getLine(); - $data['trace']=$exception->getTrace(); - if($exception instanceof TPhpErrorException) - { - // if PHP exception, we want to show the 2nd stack level context - // because the 1st stack level is of little use (it's in error handler) - if(isset($trace[0]) && isset($trace[0]['file']) && isset($trace[0]['line'])) - { - $data['file']=$trace[0]['file']; - $data['line']=$trace[0]['line']; - } - } - $data['type']=get_class($exception); - $data['message']=$exception->getMessage(); - $data['version']=$_SERVER['SERVER_SOFTWARE'].' '.Prado::getVersion(); - $data['time']=@strftime('%Y-%m-%d %H:%M',time()); - return $data; - } -} - -/** - * TInvalidCallbackException class. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Web.UI.ActiveControls - * @since 3.1 - */ -class TInvalidCallbackException extends TException -{ -} - + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2008 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.ActiveControls + */ + +/** + * Load callback response adapter class. + */ +Prado::using('System.Web.UI.ActiveControls.TCallbackResponseAdapter'); +Prado::using('System.Web.UI.ActiveControls.TCallbackClientScript'); +Prado::using('System.Web.UI.ActiveControls.TCallbackEventParameter'); + +/** + * TActivePageAdapter class. + * + * Callback request handler. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Web.UI.ActiveControls + * @since 3.1 + */ +class TActivePageAdapter extends TControlAdapter +{ + /** + * Callback response data header name. + */ + const CALLBACK_DATA_HEADER = 'X-PRADO-DATA'; + /** + * Callback response client-side action header name. + */ + const CALLBACK_ACTION_HEADER = 'X-PRADO-ACTIONS'; + /** + * Callback error header name. + */ + const CALLBACK_ERROR_HEADER = 'X-PRADO-ERROR'; + /** + * Callback page state header name. + */ + const CALLBACK_PAGESTATE_HEADER = 'X-PRADO-PAGESTATE'; + + /** + * Callback redirect url header name. + */ + const CALLBACK_REDIRECT = 'X-PRADO-REDIRECT'; + + /** + * @var ICallbackEventHandler callback event handler. + */ + private $_callbackEventTarget; + /** + * @var mixed callback event parameter. + */ + private $_callbackEventParameter; + /** + * @var TCallbackClientScript callback client script handler + */ + private $_callbackClient; + + private $_controlsToRender=array(); + + /** + * Constructor, trap errors and exception to let the callback response + * handle them. + */ + public function __construct(TPage $control) + { + parent::__construct($control); + + //TODO: can this be done later? + $response = $this->getApplication()->getResponse(); + $response->setAdapter(new TCallbackResponseAdapter($response)); + + $this->trapCallbackErrorsExceptions(); + } + + /** + * Process the callback request. + * @param THtmlWriter html content writer. + */ + public function processCallbackEvent($writer) + { + Prado::trace("ActivePage raiseCallbackEvent()",'System.Web.UI.ActiveControls.TActivePageAdapter'); + $this->raiseCallbackEvent(); + } + + /** + * Register a control for defered render() call. + * @param TControl control for defered rendering + * @param THtmlWriter the renderer + */ + public function registerControlToRender($control,$writer) + { + $id = $control->getUniqueID(); + if(!isset($this->_controlsToRender[$id])) + $this->_controlsToRender[$id] = array($control,$writer); + } + + /** + * Trap errors and exceptions to be handled by TCallbackErrorHandler. + */ + protected function trapCallbackErrorsExceptions() + { + $this->getApplication()->setErrorHandler(new TCallbackErrorHandler); + } + + /** + * Render the callback response. + * @param THtmlWriter html content writer. + */ + public function renderCallbackResponse($writer) + { + Prado::trace("ActivePage renderCallbackResponse()",'System.Web.UI.ActiveControls.TActivePageAdapter'); + if(($url = $this->getResponse()->getAdapter()->getRedirectedUrl())===null) + $this->renderResponse($writer); + else + $this->redirect($url); + } + + /** + * Redirect url on the client-side using javascript. + * @param string new url to load. + */ + protected function redirect($url) + { + Prado::trace("ActivePage redirect()",'System.Web.UI.ActiveControls.TActivePageAdapter'); + $this->appendContentPart($this->getResponse(), self::CALLBACK_REDIRECT, $url); + //$this->getResponse()->appendHeader(self::CALLBACK_REDIRECT.': '.$url); + } + + /** + * Renders the callback response by adding additional callback data and + * javascript actions in the header and page state if required. + * @param THtmlWriter html content writer. + */ + protected function renderResponse($writer) + { + Prado::trace("ActivePage renderResponse()",'System.Web.UI.ActiveControls.TActivePageAdapter'); + //renders all the defered render() calls. + foreach($this->_controlsToRender as $rid => $forRender) + $forRender[0]->render($forRender[1]); + + $response = $this->getResponse(); + + //send response data in header + if($response->getHasAdapter()) + { + $responseData = $response->getAdapter()->getResponseData(); + if($responseData!==null) + { + $data = TJavaScript::jsonEncode($responseData); + + $this->appendContentPart($response, self::CALLBACK_DATA_HEADER, $data); + //$response->appendHeader(self::CALLBACK_DATA_HEADER.': '.$data); + } + } + + //sends page state in header + if(($handler = $this->getCallbackEventTarget()) !== null) + { + if($handler->getActiveControl()->getClientSide()->getEnablePageStateUpdate()) + { + $pagestate = $this->getPage()->getClientState(); + $this->appendContentPart($response, self::CALLBACK_PAGESTATE_HEADER, $pagestate); + //$response->appendHeader(self::CALLBACK_PAGESTATE_HEADER.': '.$pagestate); + } + } + + //safari must receive at least 1 byte of data. + $writer->write(" "); + + //output the end javascript + if($this->getPage()->getClientScript()->hasEndScripts()) + { + $writer = $response->createHtmlWriter(); + $this->getPage()->getClientScript()->renderEndScripts($writer); + $this->getPage()->getCallbackClient()->evaluateScript($writer); + } + + //output the actions + $executeJavascript = $this->getCallbackClientHandler()->getClientFunctionsToExecute(); + $actions = TJavaScript::jsonEncode($executeJavascript); + $this->appendContentPart($response, self::CALLBACK_ACTION_HEADER, $actions); + //$response->appendHeader(self::CALLBACK_ACTION_HEADER.': '.$actions); + } + + /** + * Appends data or javascript code to the body content surrounded with delimiters + */ + private function appendContentPart($response, $delimiter, $data) + { + $content = $response->createHtmlWriter(); + $content->getWriter()->setBoundary($delimiter); + $content->write($data); + } + + /** + * Trys to find the callback event handler and raise its callback event. + * @throws TInvalidCallbackException if call back target is not found. + * @throws TInvalidCallbackException if the requested target does not + * implement ICallbackEventHandler. + */ + private function raiseCallbackEvent() + { + if(($callbackHandler=$this->getCallbackEventTarget())!==null) + { + if($callbackHandler instanceof ICallbackEventHandler) + { + $param = $this->getCallbackEventParameter(); + $result = new TCallbackEventParameter($this->getResponse(), $param); + $callbackHandler->raiseCallbackEvent($result); + } + else + { + throw new TInvalidCallbackException( + 'callback_invalid_handler', $callbackHandler->getUniqueID()); + } + } + else + { + $target = $this->getRequest()->itemAt(TPage::FIELD_CALLBACK_TARGET); + throw new TInvalidCallbackException('callback_invalid_target', $target); + } + } + + /** + * @return TControl the control responsible for the current callback event, + * null if nonexistent + */ + public function getCallbackEventTarget() + { + if($this->_callbackEventTarget===null) + { + $eventTarget=$this->getRequest()->itemAt(TPage::FIELD_CALLBACK_TARGET); + if(!empty($eventTarget)) + $this->_callbackEventTarget=$this->getPage()->findControl($eventTarget); + } + return $this->_callbackEventTarget; + } + + /** + * Registers a control to raise callback event in the current request. + * @param TControl control registered to raise callback event. + */ + public function setCallbackEventTarget(TControl $control) + { + $this->_callbackEventTarget=$control; + } + + /** + * Gets callback parameter. JSON encoding is assumed. + * @return string postback event parameter + */ + public function getCallbackEventParameter() + { + if($this->_callbackEventParameter===null) + { + $param = $this->getRequest()->itemAt(TPage::FIELD_CALLBACK_PARAMETER); + if(strlen($param) > 0) + $this->_callbackEventParameter=TJavaScript::jsonDecode((string)$param); + } + return $this->_callbackEventParameter; + } + + /** + * @param mixed postback event parameter + */ + public function setCallbackEventParameter($value) + { + $this->_callbackEventParameter=$value; + } + + /** + * Gets the callback client script handler. It handlers the javascript functions + * to be executed during the callback response. + * @return TCallbackClientScript callback client handler. + */ + public function getCallbackClientHandler() + { + if($this->_callbackClient===null) + $this->_callbackClient = new TCallbackClientScript; + return $this->_callbackClient; + } +} + +/** + * TCallbackErrorHandler class. + * + * Captures errors and exceptions and send them back during callback response. + * When the application is in debug mode, the error and exception stack trace + * are shown. A TJavascriptLogger must be present on the client-side to view + * the error stack trace. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Web.UI.ActiveControls + * @since 3.1 + */ +class TCallbackErrorHandler extends TErrorHandler +{ + /** + * Displays the exceptions to the client-side TJavascriptLogger. + * A HTTP 500 status code is sent and the stack trace is sent as JSON encoded. + * @param Exception exception details. + */ + protected function displayException($exception) + { + if($this->getApplication()->getMode()===TApplication::STATE_DEBUG) + { + $response = $this->getApplication()->getResponse(); + $trace = TJavaScript::jsonEncode($this->getExceptionStackTrace($exception)); + $response->appendHeader('HTTP/1.0 500 Internal Error'); + $response->appendHeader(TActivePageAdapter::CALLBACK_ERROR_HEADER.': '.$trace); + } + else + { + error_log("Error happened while processing an existing error:\n".$exception->__toString()); + header('HTTP/1.0 500 Internal Error'); + } + $this->getApplication()->getResponse()->flush(); + } + + /** + * @param Exception exception details. + * @return array exception stack trace details. + */ + private function getExceptionStackTrace($exception) + { + $data['code']=$exception->getCode() > 0 ? $exception->getCode() : 500; + $data['file']=$exception->getFile(); + $data['line']=$exception->getLine(); + $data['trace']=$exception->getTrace(); + if($exception instanceof TPhpErrorException) + { + // if PHP exception, we want to show the 2nd stack level context + // because the 1st stack level is of little use (it's in error handler) + if(isset($trace[0]) && isset($trace[0]['file']) && isset($trace[0]['line'])) + { + $data['file']=$trace[0]['file']; + $data['line']=$trace[0]['line']; + } + } + $data['type']=get_class($exception); + $data['message']=$exception->getMessage(); + $data['version']=$_SERVER['SERVER_SOFTWARE'].' '.Prado::getVersion(); + $data['time']=@strftime('%Y-%m-%d %H:%M',time()); + return $data; + } +} + +/** + * TInvalidCallbackException class. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Web.UI.ActiveControls + * @since 3.1 + */ +class TInvalidCallbackException extends TException +{ +} + diff --git a/framework/Web/UI/ActiveControls/TAutoComplete.php b/framework/Web/UI/ActiveControls/TAutoComplete.php index 5a3633ec..13200e51 100644 --- a/framework/Web/UI/ActiveControls/TAutoComplete.php +++ b/framework/Web/UI/ActiveControls/TAutoComplete.php @@ -235,7 +235,7 @@ class TAutoComplete extends TActiveTextBox implements INamingContainer */ public function getResultPanel() { - if(is_null($this->_resultPanel)) + if($this->_resultPanel===null) $this->_resultPanel = $this->createResultPanel(); return $this->_resultPanel; } @@ -256,7 +256,7 @@ class TAutoComplete extends TActiveTextBox implements INamingContainer */ public function getSuggestions() { - if(is_null($this->_repeater)) + if($this->_repeater===null) $this->_repeater = $this->createRepeater(); return $this->_repeater; } diff --git a/framework/Web/UI/ActiveControls/TBaseActiveControl.php b/framework/Web/UI/ActiveControls/TBaseActiveControl.php index 8f55e27b..f301f2c3 100644 --- a/framework/Web/UI/ActiveControls/TBaseActiveControl.php +++ b/framework/Web/UI/ActiveControls/TBaseActiveControl.php @@ -58,8 +58,8 @@ class TBaseActiveControl extends TComponent */ protected function setOption($name,$value,$default=null) { - $value = is_null($value) ? $default : $value; - if(!is_null($value)) + $value = ($value===null) ? $default : $value; + if($value!==null) $this->_options->add($name,$value); } @@ -73,7 +73,7 @@ class TBaseActiveControl extends TComponent protected function getOption($name,$default=null) { $item = $this->_options->itemAt($name); - return is_null($item) ? $default : $item; + return ($item===null) ? $default : $item; } /** @@ -168,7 +168,7 @@ class TBaseActiveCallbackControl extends TBaseActiveControl */ public function getClientSide() { - if(is_null($client = $this->getOption('ClientSide'))) + if(($client = $this->getOption('ClientSide'))===null) { $client = $this->createClientSide(); $this->setOption('ClientSide', $client); @@ -182,7 +182,7 @@ class TBaseActiveCallbackControl extends TBaseActiveControl */ public function setClientSide($client) { - if(is_null($this->getOption('ClientSide'))) + if( $this->getOption('ClientSide')===null) $this->setOption('ClientSide', $client); else throw new TConfigurationException( diff --git a/framework/Web/UI/ActiveControls/TCallbackClientScript.php b/framework/Web/UI/ActiveControls/TCallbackClientScript.php index 8f275ef8..1b9f1ca6 100644 --- a/framework/Web/UI/ActiveControls/TCallbackClientScript.php +++ b/framework/Web/UI/ActiveControls/TCallbackClientScript.php @@ -4,7 +4,7 @@ * * @author Wei Zhuo * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft * @license http://www.pradosoft.com/license/ * @version $Id$ * @package System.Web.UI.ActiveControls @@ -104,7 +104,7 @@ class TCallbackClientScript extends TApplicationComponent { $method = TPropertyValue::ensureEnum($method, 'Value', 'Index', 'Clear', 'Indices', 'Values', 'All', 'Invert'); - $type = is_null($type) ? $this->getSelectionControlType($control) : $type; + $type = ($type===null) ? $this->getSelectionControlType($control) : $type; $total = $this->getSelectionControlIsListType($control) ? $control->getItemCount() : 1; $this->callClientFunction('Prado.Element.select', array($control, $type.$method, $value, $total)); @@ -164,8 +164,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function setAttribute($control, $name, $value) { - if ($control instanceof ISurroundable) - $control=$control->getSurroundingTagID(); + if ($control instanceof ISurroundable) + $control=$control->getSurroundingTagID(); $this->callClientFunction('Prado.Element.setAttribute',array($control, $name, $value)); } @@ -193,8 +193,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function show($element) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->callClientFunction('Element.show', $element); } @@ -204,8 +204,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function hide($element) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->callClientFunction('Element.hide', $element); } @@ -217,8 +217,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function toggle($element, $effect=null, $options=array()) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->callClientFunction('Element.toggle', array($element,$effect,$options)); } @@ -228,8 +228,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function remove($element) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->callClientFunction('Element.remove', $element); } @@ -246,8 +246,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function update($element, $content) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->replace($element, $content, 'Element.update'); } @@ -258,8 +258,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function addCssClass($element, $cssClass) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->callClientFunction('Element.addClassName', array($element, $cssClass)); } @@ -270,8 +270,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function removeCssClass($element, $cssClass) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->callClientFunction('Element.removeClassName', array($element, $cssClass)); } @@ -292,8 +292,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function scrollTo($element) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->callClientFunction('Element.scrollTo', $element); } @@ -313,9 +313,9 @@ class TCallbackClientScript extends TApplicationComponent * @param array list of key-value pairs as style property and style value. */ public function setStyle($element, $styles) - { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + { + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->callClientFunction('Prado.Element.setStyle', array($element, $styles)); } @@ -326,8 +326,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function appendContent($element, $content) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->replace($element, $content, 'Prado.Element.Insert.append'); } @@ -338,8 +338,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function prependContent($element, $content) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->replace($element, $content, 'Prado.Element.Insert.prepend'); } @@ -350,8 +350,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function insertContentAfter($element, $content) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->replace($element, $content, 'Prado.Element.Insert.after'); } @@ -362,8 +362,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function insertContentBefore($element, $content) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->replace($element, $content, 'Prado.Element.Insert.before'); } @@ -406,8 +406,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function replaceContent($element,$content) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->replace($element, $content); } @@ -458,8 +458,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function visualEffect($type, $element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->callClientFunction($type, array($element, $options)); } @@ -470,8 +470,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function appear($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.Appear', $element, $options); } @@ -482,8 +482,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function blindDown($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.BlindDown', $element, $options); } @@ -494,8 +494,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function blindUp($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.BlindUp', $element, $options); } @@ -507,8 +507,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function dropOut($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.DropOut', $element, $options); } @@ -519,8 +519,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function fade($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.Fade', $element, $options); } @@ -531,8 +531,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function fold($element, $options = null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.Fold', $element, $options); } @@ -543,8 +543,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function grow($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.Grow', $element, $options); } @@ -555,8 +555,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function puff($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.Puff', $element, $options); } @@ -567,8 +567,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function pulsate($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.Pulsate', $element, $options); } @@ -579,8 +579,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function shake($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.Shake', $element, $options); } @@ -591,8 +591,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function shrink($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.Shrink', $element, $options); } @@ -603,8 +603,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function slideDown($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.SlideDown', $element, $options); } @@ -615,8 +615,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function slideUp($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.SlideUp', $element, $options); } @@ -627,8 +627,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function squish($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.Squish', $element, $options); } @@ -639,8 +639,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function switchOff($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Effect.SwitchOff', $element, $options); } @@ -651,8 +651,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function highlight($element, $options=null) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $this->visualEffect('Prado.Effect.Highlight', $element, $options); } @@ -663,8 +663,8 @@ class TCallbackClientScript extends TApplicationComponent */ public function setOpacity($element, $value) { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable) + $element=$element->getSurroundingTagID(); $value = TPropertyValue::ensureFloat($value); $this->callClientFunction('Element.setOpacity', array($element,$value)); } diff --git a/framework/Web/UI/ActiveControls/TCallbackClientSide.php b/framework/Web/UI/ActiveControls/TCallbackClientSide.php index 57436278..31b806c3 100644 --- a/framework/Web/UI/ActiveControls/TCallbackClientSide.php +++ b/framework/Web/UI/ActiveControls/TCallbackClientSide.php @@ -4,7 +4,7 @@ * * @author Wei Zhuo * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft * @license http://www.pradosoft.com/license/ * @version $Id$ * @package System.Web.UI.ActiveControls @@ -22,13 +22,13 @@ * - onLoaded* executed when callback request begins. * - onInteractive executed when callback request is in progress. * - onCompleteexecuted when callback response returns. - * - * * Note that theses 2 events are not fired correctly by Opera. To make - * them work in this browser, Prado will fire them just after onPreDispatch. - * - * In a general way, onUninitialized, onLoading, onLoaded and onInteractive events - * are not implemented consistently in all browsers.When cross browser compatibility is - * needed, it is best to avoid use them + * + * * Note that theses 2 events are not fired correctly by Opera. To make + * them work in this browser, Prado will fire them just after onPreDispatch. + * + * In a general way, onUninitialized, onLoading, onLoaded and onInteractive events + * are not implemented consistently in all browsers.When cross browser compatibility is + * needed, it is best to avoid use them * * The OnSuccess and OnFailure events are raised when the * response is returned. A successful request/response will raise @@ -247,7 +247,7 @@ class TCallbackClientSide extends TClientSideOptions public function getHasPriority() { $option = $this->getOption('HasPriority'); - return is_null($option) ? true : $option; + return ($option===null) ? true : $option; } /** @@ -284,7 +284,7 @@ class TCallbackClientSide extends TClientSideOptions public function getEnablePageStateUpdate() { $option = $this->getOption('EnablePageStateUpdate'); - return is_null($option) ? true : $option; + return ($option===null) ? true : $option; } /** diff --git a/framework/Web/UI/ActiveControls/TCallbackOptions.php b/framework/Web/UI/ActiveControls/TCallbackOptions.php index 7c48b795..c9b649d8 100644 --- a/framework/Web/UI/ActiveControls/TCallbackOptions.php +++ b/framework/Web/UI/ActiveControls/TCallbackOptions.php @@ -4,7 +4,7 @@ * * @author Wei Zhuo * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft * @license http://www.pradosoft.com/license/ * @version $Id$ * @package System.Web.UI.ActiveControls @@ -37,7 +37,7 @@ class TCallbackOptions extends TControl */ public function getClientSide() { - if(is_null($this->_clientSide)) + if($this->_clientSide===null) $this->_clientSide = $this->createClientSide(); return $this->_clientSide; } diff --git a/framework/Web/UI/ActiveControls/TInPlaceTextBox.php b/framework/Web/UI/ActiveControls/TInPlaceTextBox.php index 6e1c6b7a..b8dd666b 100644 --- a/framework/Web/UI/ActiveControls/TInPlaceTextBox.php +++ b/framework/Web/UI/ActiveControls/TInPlaceTextBox.php @@ -4,7 +4,7 @@ * * @author Wei Zhuo * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft * @license http://www.pradosoft.com/license/ * @version $Id$ * @package System.Web.UI.ActiveControls @@ -35,9 +35,9 @@ Prado::using('System.Web.UI.ActiveControls.TActiveTextBox'); * After the callback request returns sucessfully, the textbox is enabled. * If the {@link setAutoHideTextBox AutoHideTextBox} property is true, then * the textbox will be hidden and the label is then shown. - * - * Since 3.1.2, you can set the {@link setReadOnly ReadOnly} property to make - * the control not editable. This property can be also changed on callback + * + * Since 3.1.2, you can set the {@link setReadOnly ReadOnly} property to make + * the control not editable. This property can be also changed on callback * * @author Wei Zhuo * @version $Id$ @@ -124,7 +124,7 @@ class TInPlaceTextBox extends TActiveTextBox protected function getExternalControlID() { $extID = $this->getEditTriggerControlID(); - if(is_null($extID)) return ''; + if($extID===null) return ''; if(($control = $this->findControl($extID))!==null) return $control->getClientID(); return $extID; @@ -144,21 +144,21 @@ class TInPlaceTextBox extends TActiveTextBox $client->update($this->getLabelClientID(), $value); $client->setValue($this, $value); } - } - - /** - * Update ClientSide Readonly property - * @param boolean value - * @since 3.1.2 - */ - public function setReadOnly ($value) - { - $value=TPropertyValue::ensureBoolean($value); - TTextBox::setReadOnly($value); - if ($this->getActiveControl()->canUpdateClientSide()) - { - $this->callClientFunction('setReadOnly', $value); - } + } + + /** + * Update ClientSide Readonly property + * @param boolean value + * @since 3.1.2 + */ + public function setReadOnly ($value) + { + $value=TPropertyValue::ensureBoolean($value); + TTextBox::setReadOnly($value); + if ($this->getActiveControl()->canUpdateClientSide()) + { + $this->callClientFunction('setReadOnly', $value); + } } /** @@ -231,8 +231,8 @@ class TInPlaceTextBox extends TActiveTextBox } if($this->hasEventHandler('OnLoadingText')) - $options['LoadTextOnEdit'] = true; - + $options['LoadTextOnEdit'] = true; + $options['ReadOnly']=$this->getReadOnly(); return $options; } diff --git a/framework/Web/UI/WebControls/TBaseValidator.php b/framework/Web/UI/WebControls/TBaseValidator.php index b418885c..e276bb55 100644 --- a/framework/Web/UI/WebControls/TBaseValidator.php +++ b/framework/Web/UI/WebControls/TBaseValidator.php @@ -1,733 +1,733 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Web.UI.WebControls - */ - -/** - * Using TLabel class - */ -Prado::using('System.Web.UI.WebControls.TLabel'); - -/** - * TBaseValidator class - * - * TBaseValidator serves as the base class for validator controls. - * - * Validation is performed when a postback control, such as a TButton, a TLinkButton - * or a TTextBox (under AutoPostBack mode) is submitting the page and - * its CausesValidation property is true. - * You can also manually perform validation by calling {@link TPage::validate()}. - * The input control to be validated is specified by {@link setControlToValidate ControlToValidate}. - * - * Validator controls always validate the associated input control on the serve side. - * In addition, if {@link getEnableClientScript EnableClientScript} is true, - * validation will also be performed on the client-side using javascript. - * Client-side validation will validate user input before it is sent to the server. - * The form data will not be submitted if any error is detected. This avoids - * the round-trip of information necessary for server-side validation. - * - * You can use multiple validator controls to validate a single input control, - * each responsible for validating against a different criteria. - * For example, on a user registration form, you may want to make sure the user - * enters a value in the username text box, and the input must consist of only word - * characters. You can use a {@link TRequiredFieldValidator} to ensure the input - * of username and a {@link TRegularExpressionValidator} to ensure the proper input. - * - * If an input control fails validation, the text specified by the {@link setErrorMessage ErrorMessage} - * property is displayed in the validation control. However, if the {@link setText Text} - * property is set, it will be displayed instead. If both {@link setErrorMessage ErrorMessage} - * and {@link setText Text} are empty, the body content of the validator will - * be displayed. Error display is controlled by {@link setDisplay Display} property. - * - * You can also customized the client-side behaviour by adding javascript - * code to the subproperties of the {@link getClientSide ClientSide} - * property. See quickstart documentation for further details. - * - * You can also place a {@link TValidationSummary} control on a page to display error messages - * from the validators together. In this case, only the {@link setErrorMessage ErrorMessage} - * property of the validators will be displayed in the {@link TValidationSummary} control. - * - * Validators can be partitioned into validation groups by setting their - * {@link setValidationGroup ValidationGroup} property. If the control causing the - * validation also sets its ValidationGroup property, only those validators having - * the same ValidationGroup value will do input validation. - * - * Note, the {@link TPage::getIsValid IsValid} property of the current {@link TPage} - * instance will be automatically updated by the validation process which occurs - * after {@link TPage::onLoad onLoad} of {@link TPage} and before the postback events. - * Therefore, if you use the {@link TPage::getIsValid()} property in - * the {@link TPage::onLoad()} method, you must first explicitly call - * the {@link TPage::validate()} method. - * - * Notes to Inheritors When you inherit from TBaseValidator, you must - * override the method {@link evaluateIsValid}. - * - * @author Qiang Xue - * @version $Id$ - * @package System.Web.UI.WebControls - * @since 3.0 - */ -abstract class TBaseValidator extends TLabel implements IValidator -{ - /** - * @var boolean whether the validation succeeds - */ - private $_isValid=true; - /** - * @var boolean whether the validator has been registered with the page - */ - private $_registered=false; - /** - * @var TValidatorClientSide validator client-script options. - */ - private $_clientSide; - /** - * Controls for which the client-side validation3.js file needs to handle - * them specially. - * @var array list of control class names - */ - private static $_clientClass = array('THtmlArea', 'TDatePicker', 'TListBox', 'TCheckBoxList'); - - /** - * Constructor. - * This method sets the foreground color to red. - */ - public function __construct() - { - parent::__construct(); - $this->setForeColor('red'); - } - - /** - * Registers the validator with page. - * @param mixed event parameter - */ - public function onInit($param) - { - parent::onInit($param); - $this->getPage()->getValidators()->add($this); - $this->_registered=true; - } - - /** - * Unregisters the validator from page. - * @param mixed event parameter - */ - public function onUnload($param) - { - if($this->_registered && ($page=$this->getPage())!==null) - $page->getValidators()->remove($this); - $this->_registered=false; - parent::onUnload($param); - } - - /** - * Adds attributes to renderer. Calls parent implementation and renders the - * client control scripts. - * @param THtmlWriter the renderer - */ - protected function addAttributesToRender($writer) - { - $display=$this->getDisplay(); - $visible=$this->getEnabled(true) && !$this->getIsValid(); - if($display===TValidatorDisplayStyle::None || (!$visible && $display===TValidatorDisplayStyle::Dynamic)) - $writer->addStyleAttribute('display','none'); - else if(!$visible) - $writer->addStyleAttribute('visibility','hidden'); - $writer->addAttribute('id',$this->getClientID()); - parent::addAttributesToRender($writer); - $this->renderClientControlScript($writer); - } - - /** - * Returns an array of javascript validator options. - * @return array javascript validator options. - */ - protected function getClientScriptOptions() - { - $control = $this->getValidationTarget(); - $options['ID'] = $this->getClientID(); - $options['FormID'] = $this->getPage()->getForm()->getClientID(); - $options['Display'] = $this->getDisplay(); - $options['ErrorMessage'] = $this->getErrorMessage(); - if($this->getFocusOnError()) - { - $options['FocusOnError'] = $this->getFocusOnError(); - $options['FocusElementID'] = $this->getFocusElementID(); - } - $options['ValidationGroup'] = $this->getValidationGroup(); - $options['ControlToValidate'] = $control->getClientID(); - $options['ControlCssClass'] = $this->getControlCssClass(); - - $options['ControlType'] = $this->getClientControlClass($control); - - //get date format from date picker target control - if($control instanceof TDatePicker) - $options['DateFormat'] = $control->getDateFormat(); - - $options = array_merge($options,$this->getClientSide()->getOptions()->toArray()); - - return $options; - } - - /** - * Gets the Control type for client-side validation. If new cases exists in - * TBaseValidator::$_clientClass, be sure to update the corresponding - * "Javascript/validation3.js" file as well. - * @param TControl control to validate. - * @return string control type for client-side validation. - */ - private function getClientControlClass($control) - { - foreach(self::$_clientClass as $type) - if($control instanceof $type) - return $type; - return get_class($control); - } - - /** - * Gets the TValidatorClientSide that allows modification of the client- - * side validator events. - * - * The client-side validator supports the following events. - * # OnValidate -- raised before client-side validation is - * executed. - * # OnValidationSuccess -- raised after client-side validation is completed - * and is successfull, overrides default validator error messages updates. - * # OnValidationError -- raised after client-side validation is completed - * and failed, overrides default validator error message updates. - * - * You can attach custom javascript code to each of these events - * - * @return TValidatorClientSide javascript validator event options. - */ - public function getClientSide() - { - if(is_null($this->_clientSide)) - $this->_clientSide = $this->createClientSide(); - return $this->_clientSide; - } - - /** - * @return TValidatorClientSide javascript validator event options. - */ - protected function createClientSide() - { - return new TValidatorClientSide; - } - - /** - * Renders the javascript code to the end script. - * If you override this method, be sure to call the parent implementation - * so that the event handlers can be invoked. - * @param THtmlWriter the renderer - */ - public function renderClientControlScript($writer) - { - $scripts = $this->getPage()->getClientScript(); - $formID=$this->getPage()->getForm()->getClientID(); - $scriptKey = "TBaseValidator:$formID"; - if($this->getEnableClientScript() && !$scripts->isEndScriptRegistered($scriptKey)) - { - $manager['FormID'] = $formID; - $options = TJavaScript::encode($manager); - $scripts->registerPradoScript('validator'); - $scripts->registerEndScript($scriptKey, "new Prado.ValidationManager({$options});"); - } - if($this->getEnableClientScript() & $this->getEnabled(true)) - $this->registerClientScriptValidator(); - } - - /** - * Override parent implementation to update the control CSS Class before - * the validated control is rendered - */ - public function onPreRender ($param) - { - parent::onPreRender($param); - $this->updateControlCssClass(); - } - - /** - * Update the ControlToValidate component's css class depending - * if the ControlCssClass property is set, and whether this is valid. - * @return boolean true if change, false otherwise. - */ - protected function updateControlCssClass() - { - if(($cssClass=$this->getControlCssClass())!=='') - { - $control=$this->getValidationTarget(); - if($control instanceof TWebControl) - { - $class = preg_replace ('/ '.preg_quote($cssClass).'/', '',$control->getCssClass()); - if(!$this->getIsValid()) - { - $class .= ' '.$cssClass; - $control->setCssClass($class); - } elseif ($control->getIsValid()) - $control->setCssClass($class); - } - } - } - - /** - * Registers the individual validator client-side javascript code. - */ - protected function registerClientScriptValidator() - { - $key = 'prado:'.$this->getClientID(); - if(!$this->getPage()->getClientScript()->isEndScriptRegistered($key)) - { - $options = TJavaScript::encode($this->getClientScriptOptions()); - $script = 'new '.$this->getClientClassName().'('.$options.');'; - $this->getPage()->getClientScript()->registerEndScript($key, $script); - } - } - - /** - * Gets the name of the javascript class responsible for performing validation for this control. - * This method overrides the parent implementation. - * @return string the javascript class name - */ - abstract protected function getClientClassName(); - - /** - * This method overrides the parent implementation to forbid setting ForControl. - * @param string the associated control ID - * @throws TNotSupportedException whenever this method is called - */ - public function setForControl($value) - { - throw new TNotSupportedException('basevalidator_forcontrol_unsupported',get_class($this)); - } - - /** - * This method overrides parent's implementation by setting {@link setIsValid IsValid} to true if disabled. - * @param boolean whether the validator is enabled. - */ - public function setEnabled($value) - { - $value=TPropertyValue::ensureBoolean($value); - parent::setEnabled($value); - if(!$value) - $this->_isValid=true; - } - - /** - * @return TValidatorDisplayStyle the style of displaying the error message. Defaults to TValidatorDisplayStyle::Fixed. - */ - public function getDisplay() - { - return $this->getViewState('Display',TValidatorDisplayStyle::Fixed); - } - - /** - * @param TValidatorDisplayStyle the style of displaying the error message - */ - public function setDisplay($value) - { - $this->setViewState('Display',TPropertyValue::ensureEnum($value,'TValidatorDisplayStyle'),TValidatorDisplayStyle::Fixed); - } - - /** - * @return boolean whether client-side validation is enabled. - */ - public function getEnableClientScript() - { - return $this->getViewState('EnableClientScript',true); - } - - /** - * @param boolean whether client-side validation is enabled. - */ - public function setEnableClientScript($value) - { - $this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true); - } - - /** - * @return string the text for the error message. - */ - public function getErrorMessage() - { - return $this->getViewState('ErrorMessage',''); - } - - /** - * Sets the text for the error message. - * @param string the error message - */ - public function setErrorMessage($value) - { - $this->setViewState('ErrorMessage',$value,''); - } - - /** - * @return string the ID path of the input control to validate - */ - public function getControlToValidate() - { - return $this->getViewState('ControlToValidate',''); - } - - /** - * Sets the ID path of the input control to validate. - * The ID path is the dot-connected IDs of the controls reaching from - * the validator's naming container to the target control. - * @param string the ID path - */ - public function setControlToValidate($value) - { - $this->setViewState('ControlToValidate',$value,''); - } - - /** - * @return boolean whether to set focus at the validating place if the validation fails. Defaults to false. - */ - public function getFocusOnError() - { - return $this->getViewState('FocusOnError',false); - } - - /** - * @param boolean whether to set focus at the validating place if the validation fails - */ - public function setFocusOnError($value) - { - $this->setViewState('FocusOnError',TPropertyValue::ensureBoolean($value),false); - } - - /** - * Gets the ID of the HTML element that will receive focus if validation fails and {@link getFocusOnError FocusOnError} is true. - * Defaults to the client ID of the {@link getControlToValidate ControlToValidate}. - * @return string the ID of the HTML element to receive focus - */ - public function getFocusElementID() - { - if(($id=$this->getViewState('FocusElementID',''))==='') - $id=$this->getValidationTarget()->getClientID(); - return $id; - } - - /** - * Sets the ID of the HTML element that will receive focus if validation fails and {@link getFocusOnError FocusOnError} is true. - * @param string the ID of the HTML element to receive focus - */ - public function setFocusElementID($value) - { - $this->setViewState('FocusElementID', $value, ''); - } - - /** - * @return string the group which this validator belongs to - */ - public function getValidationGroup() - { - return $this->getViewState('ValidationGroup',''); - } - - /** - * @param string the group which this validator belongs to - */ - public function setValidationGroup($value) - { - $this->setViewState('ValidationGroup',$value,''); - } - - /** - * @return boolean whether the validation succeeds - */ - public function getIsValid() - { - return $this->_isValid; - } - - /** - * Sets the value indicating whether the validation succeeds - * @param boolean whether the validation succeeds - */ - public function setIsValid($value) - { - $this->_isValid=TPropertyValue::ensureBoolean($value); - } - - /** - * @return TControl control to be validated. Null if no control is found. - * @throws TConfigurationException if {@link getControlToValidate - * ControlToValidate} is empty or does not point to a valid control - */ - protected function getValidationTarget() - { - if(($id=$this->getControlToValidate())!=='' && ($control=$this->findControl($id))!==null) - return $control; - else - throw new TConfigurationException('basevalidator_controltovalidate_invalid',get_class($this)); - } - - /** - * Retrieves the property value of the control being validated. - * @param TControl control being validated - * @return string property value to be validated - * @throws TInvalidDataTypeException if the control to be validated does not implement {@link IValidatable}. - */ - protected function getValidationValue($control) - { - if($control instanceof IValidatable) - return $control->getValidationPropertyValue(); - else - throw new TInvalidDataTypeException('basevalidator_validatable_required',get_class($this)); - } - - /** - * Validates the specified control. - * Do not override this method. Override {@link evaluateIsValid} instead. - * @return boolean whether the validation succeeds - */ - public function validate() - { - $this->setIsValid(true); - $this->onValidate(); - if($this->getVisible(true) && $this->getEnabled(true)) - { - // if the target is not a disabled web control - if(($target=$this->getValidationTarget())!==null && !($target instanceof TWebControl && !$target->getEnabled(true))) - { - if($this->evaluateIsValid()) - { - $this->setIsValid(true); - $this->onValidationSuccess(); - } - else - { - $target->setIsValid(false); - $this->setIsValid(false); - $this->onValidationError(); - } - } - else - { - $this->evaluateIsValid(); - $this->setIsValid(true); - $this->onValidationSuccess(); - } - } - return $this->getIsValid(); - } - - /** - * @return string the css class that is applied to the control being validated in case the validation fails - */ - public function getControlCssClass() - { - return $this->getViewState('ControlCssClass',''); - } - - /** - * @param string the css class that is applied to the control being validated in case the validation fails - */ - public function setControlCssClass($value) - { - $this->setViewState('ControlCssClass',$value,''); - } - - /** - * This is the major method for validation. - * Derived classes should implement this method to provide customized validation. - * @return boolean whether the validation succeeds - */ - abstract protected function evaluateIsValid(); - - /** - * This event is raised when the validator succeeds in validation. - */ - public function onValidationSuccess() - { - $this->raiseEvent('OnValidationSuccess',$this,null); - } - - /** - * This event is raised when the validator fails in validation. - */ - public function onValidationError() - { - $this->raiseEvent('OnValidationError',$this,null); - } - - /** - * This event is raised right before the validator starts to perform validation. - * You may use this event to change the behavior of validation. - * For example, you may disable the validator if certain condition is satisfied. - * Note, the event will NOT be raised if the validator is invisible. - */ - public function onValidate() - { - $this->raiseEvent('OnValidate',$this,null); - } - - /** - * Renders the validator control. - * @param THtmlWriter writer for the rendering purpose - */ - public function renderContents($writer) - { - if(($text=$this->getText())!=='') - $writer->write($text); - else if(($text=$this->getErrorMessage())!=='') - $writer->write($text); - else - parent::renderContents($writer); - } -} - -/** - * TValidatorClientSide class. - * - * Client-side validator events can be modified through the {@link - * TBaseValidator::getClientSide ClientSide} property of a validator. The - * subproperties of ClientSide are those of the TValidatorClientSide - * properties. The client-side validator supports the following events. - * - * The OnValidate event is raise before the validator validation - * functions are called. - * - * The OnValidationSuccess event is raised after the validator has successfully - * validate the control. - * - * The OnValidationError event is raised after the validator fails validation. - * - * See the quickstart documentation for further details. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Web.UI.WebControls - * @since 3.0 - */ -class TValidatorClientSide extends TClientSideOptions -{ - /** - * @return string javascript code for client-side OnValidate event. - */ - public function getOnValidate() - { - return $this->getOption('OnValidate'); - } - - /** - * Client-side OnValidate validator event is raise before the validators - * validation functions are called. - * @param string javascript code for client-side OnValidate event. - */ - public function setOnValidate($javascript) - { - $this->setFunction('OnValidate', $javascript); - } - - /** - * Client-side OnSuccess event is raise after validation is successfull. - * This will override the default client-side validator behaviour. - * @param string javascript code for client-side OnSuccess event. - */ - public function setOnValidationSuccess($javascript) - { - $this->setFunction('OnValidationSuccess', $javascript); - } - - /** - * @return string javascript code for client-side OnSuccess event. - */ - public function getOnValidationSuccess() - { - return $this->getOption('OnValidationSuccess'); - } - - /** - * Client-side OnError event is raised after validation failure. - * This will override the default client-side validator behaviour. - * @param string javascript code for client-side OnError event. - */ - public function setOnValidationError($javascript) - { - $this->setFunction('OnValidationError', $javascript); - } - - /** - * @return string javascript code for client-side OnError event. - */ - public function getOnValidationError() - { - return $this->getOption('OnValidationError'); - } - - /** - * @param boolean true to revalidate when the control to validate changes value. - */ - public function setObserveChanges($value) - { - $this->setOption('ObserveChanges', TPropertyValue::ensureBoolean($value)); - } - - /** - * @return boolean true to observe changes. - */ - public function getObserveChanges() - { - $changes = $this->getOption('ObserveChanges'); - return is_null($changes) ? true : $changes; - } -} - - -/** - * TValidatorDisplayStyle class. - * TValidatorDisplayStyle defines the enumerable type for the possible styles - * that a validator control can display the error message. - * - * The following enumerable values are defined: - * - None: the error message is not displayed - * - Dynamic: the error message dynamically appears when the validator fails validation - * - Fixed: Similar to Dynamic except that the error message physically occupies the page layout (even though it may not be visible) - * - * @author Qiang Xue - * @version $Id$ - * @package System.Web.UI.WebControls - * @since 3.0.4 - */ -class TValidatorDisplayStyle extends TEnumerable -{ - const None='None'; - const Dynamic='Dynamic'; - const Fixed='Fixed'; -} - -/** - * TValidationDataType class. - * TValidationDataType defines the enumerable type for the possible data types that - * a comparison validator can validate upon. - * - * The following enumerable values are defined: - * - Integer - * - Float - * - Date - * - String - * - * @author Qiang Xue - * @version $Id$ - * @package System.Web.UI.WebControls - * @since 3.0.4 - */ -class TValidationDataType extends TEnumerable -{ - const Integer='Integer'; - const Float='Float'; - const Date='Date'; - const String='String'; -} - + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2008 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Using TLabel class + */ +Prado::using('System.Web.UI.WebControls.TLabel'); + +/** + * TBaseValidator class + * + * TBaseValidator serves as the base class for validator controls. + * + * Validation is performed when a postback control, such as a TButton, a TLinkButton + * or a TTextBox (under AutoPostBack mode) is submitting the page and + * its CausesValidation property is true. + * You can also manually perform validation by calling {@link TPage::validate()}. + * The input control to be validated is specified by {@link setControlToValidate ControlToValidate}. + * + * Validator controls always validate the associated input control on the serve side. + * In addition, if {@link getEnableClientScript EnableClientScript} is true, + * validation will also be performed on the client-side using javascript. + * Client-side validation will validate user input before it is sent to the server. + * The form data will not be submitted if any error is detected. This avoids + * the round-trip of information necessary for server-side validation. + * + * You can use multiple validator controls to validate a single input control, + * each responsible for validating against a different criteria. + * For example, on a user registration form, you may want to make sure the user + * enters a value in the username text box, and the input must consist of only word + * characters. You can use a {@link TRequiredFieldValidator} to ensure the input + * of username and a {@link TRegularExpressionValidator} to ensure the proper input. + * + * If an input control fails validation, the text specified by the {@link setErrorMessage ErrorMessage} + * property is displayed in the validation control. However, if the {@link setText Text} + * property is set, it will be displayed instead. If both {@link setErrorMessage ErrorMessage} + * and {@link setText Text} are empty, the body content of the validator will + * be displayed. Error display is controlled by {@link setDisplay Display} property. + * + * You can also customized the client-side behaviour by adding javascript + * code to the subproperties of the {@link getClientSide ClientSide} + * property. See quickstart documentation for further details. + * + * You can also place a {@link TValidationSummary} control on a page to display error messages + * from the validators together. In this case, only the {@link setErrorMessage ErrorMessage} + * property of the validators will be displayed in the {@link TValidationSummary} control. + * + * Validators can be partitioned into validation groups by setting their + * {@link setValidationGroup ValidationGroup} property. If the control causing the + * validation also sets its ValidationGroup property, only those validators having + * the same ValidationGroup value will do input validation. + * + * Note, the {@link TPage::getIsValid IsValid} property of the current {@link TPage} + * instance will be automatically updated by the validation process which occurs + * after {@link TPage::onLoad onLoad} of {@link TPage} and before the postback events. + * Therefore, if you use the {@link TPage::getIsValid()} property in + * the {@link TPage::onLoad()} method, you must first explicitly call + * the {@link TPage::validate()} method. + * + * Notes to Inheritors When you inherit from TBaseValidator, you must + * override the method {@link evaluateIsValid}. + * + * @author Qiang Xue + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +abstract class TBaseValidator extends TLabel implements IValidator +{ + /** + * @var boolean whether the validation succeeds + */ + private $_isValid=true; + /** + * @var boolean whether the validator has been registered with the page + */ + private $_registered=false; + /** + * @var TValidatorClientSide validator client-script options. + */ + private $_clientSide; + /** + * Controls for which the client-side validation3.js file needs to handle + * them specially. + * @var array list of control class names + */ + private static $_clientClass = array('THtmlArea', 'TDatePicker', 'TListBox', 'TCheckBoxList'); + + /** + * Constructor. + * This method sets the foreground color to red. + */ + public function __construct() + { + parent::__construct(); + $this->setForeColor('red'); + } + + /** + * Registers the validator with page. + * @param mixed event parameter + */ + public function onInit($param) + { + parent::onInit($param); + $this->getPage()->getValidators()->add($this); + $this->_registered=true; + } + + /** + * Unregisters the validator from page. + * @param mixed event parameter + */ + public function onUnload($param) + { + if($this->_registered && ($page=$this->getPage())!==null) + $page->getValidators()->remove($this); + $this->_registered=false; + parent::onUnload($param); + } + + /** + * Adds attributes to renderer. Calls parent implementation and renders the + * client control scripts. + * @param THtmlWriter the renderer + */ + protected function addAttributesToRender($writer) + { + $display=$this->getDisplay(); + $visible=$this->getEnabled(true) && !$this->getIsValid(); + if($display===TValidatorDisplayStyle::None || (!$visible && $display===TValidatorDisplayStyle::Dynamic)) + $writer->addStyleAttribute('display','none'); + else if(!$visible) + $writer->addStyleAttribute('visibility','hidden'); + $writer->addAttribute('id',$this->getClientID()); + parent::addAttributesToRender($writer); + $this->renderClientControlScript($writer); + } + + /** + * Returns an array of javascript validator options. + * @return array javascript validator options. + */ + protected function getClientScriptOptions() + { + $control = $this->getValidationTarget(); + $options['ID'] = $this->getClientID(); + $options['FormID'] = $this->getPage()->getForm()->getClientID(); + $options['Display'] = $this->getDisplay(); + $options['ErrorMessage'] = $this->getErrorMessage(); + if($this->getFocusOnError()) + { + $options['FocusOnError'] = $this->getFocusOnError(); + $options['FocusElementID'] = $this->getFocusElementID(); + } + $options['ValidationGroup'] = $this->getValidationGroup(); + $options['ControlToValidate'] = $control->getClientID(); + $options['ControlCssClass'] = $this->getControlCssClass(); + + $options['ControlType'] = $this->getClientControlClass($control); + + //get date format from date picker target control + if($control instanceof TDatePicker) + $options['DateFormat'] = $control->getDateFormat(); + + $options = array_merge($options,$this->getClientSide()->getOptions()->toArray()); + + return $options; + } + + /** + * Gets the Control type for client-side validation. If new cases exists in + * TBaseValidator::$_clientClass, be sure to update the corresponding + * "Javascript/validation3.js" file as well. + * @param TControl control to validate. + * @return string control type for client-side validation. + */ + private function getClientControlClass($control) + { + foreach(self::$_clientClass as $type) + if($control instanceof $type) + return $type; + return get_class($control); + } + + /** + * Gets the TValidatorClientSide that allows modification of the client- + * side validator events. + * + * The client-side validator supports the following events. + * # OnValidate -- raised before client-side validation is + * executed. + * # OnValidationSuccess -- raised after client-side validation is completed + * and is successfull, overrides default validator error messages updates. + * # OnValidationError -- raised after client-side validation is completed + * and failed, overrides default validator error message updates. + * + * You can attach custom javascript code to each of these events + * + * @return TValidatorClientSide javascript validator event options. + */ + public function getClientSide() + { + if($this->_clientSide===null) + $this->_clientSide = $this->createClientSide(); + return $this->_clientSide; + } + + /** + * @return TValidatorClientSide javascript validator event options. + */ + protected function createClientSide() + { + return new TValidatorClientSide; + } + + /** + * Renders the javascript code to the end script. + * If you override this method, be sure to call the parent implementation + * so that the event handlers can be invoked. + * @param THtmlWriter the renderer + */ + public function renderClientControlScript($writer) + { + $scripts = $this->getPage()->getClientScript(); + $formID=$this->getPage()->getForm()->getClientID(); + $scriptKey = "TBaseValidator:$formID"; + if($this->getEnableClientScript() && !$scripts->isEndScriptRegistered($scriptKey)) + { + $manager['FormID'] = $formID; + $options = TJavaScript::encode($manager); + $scripts->registerPradoScript('validator'); + $scripts->registerEndScript($scriptKey, "new Prado.ValidationManager({$options});"); + } + if($this->getEnableClientScript() & $this->getEnabled(true)) + $this->registerClientScriptValidator(); + } + + /** + * Override parent implementation to update the control CSS Class before + * the validated control is rendered + */ + public function onPreRender ($param) + { + parent::onPreRender($param); + $this->updateControlCssClass(); + } + + /** + * Update the ControlToValidate component's css class depending + * if the ControlCssClass property is set, and whether this is valid. + * @return boolean true if change, false otherwise. + */ + protected function updateControlCssClass() + { + if(($cssClass=$this->getControlCssClass())!=='') + { + $control=$this->getValidationTarget(); + if($control instanceof TWebControl) + { + $class = preg_replace ('/ '.preg_quote($cssClass).'/', '',$control->getCssClass()); + if(!$this->getIsValid()) + { + $class .= ' '.$cssClass; + $control->setCssClass($class); + } elseif ($control->getIsValid()) + $control->setCssClass($class); + } + } + } + + /** + * Registers the individual validator client-side javascript code. + */ + protected function registerClientScriptValidator() + { + $key = 'prado:'.$this->getClientID(); + if(!$this->getPage()->getClientScript()->isEndScriptRegistered($key)) + { + $options = TJavaScript::encode($this->getClientScriptOptions()); + $script = 'new '.$this->getClientClassName().'('.$options.');'; + $this->getPage()->getClientScript()->registerEndScript($key, $script); + } + } + + /** + * Gets the name of the javascript class responsible for performing validation for this control. + * This method overrides the parent implementation. + * @return string the javascript class name + */ + abstract protected function getClientClassName(); + + /** + * This method overrides the parent implementation to forbid setting ForControl. + * @param string the associated control ID + * @throws TNotSupportedException whenever this method is called + */ + public function setForControl($value) + { + throw new TNotSupportedException('basevalidator_forcontrol_unsupported',get_class($this)); + } + + /** + * This method overrides parent's implementation by setting {@link setIsValid IsValid} to true if disabled. + * @param boolean whether the validator is enabled. + */ + public function setEnabled($value) + { + $value=TPropertyValue::ensureBoolean($value); + parent::setEnabled($value); + if(!$value) + $this->_isValid=true; + } + + /** + * @return TValidatorDisplayStyle the style of displaying the error message. Defaults to TValidatorDisplayStyle::Fixed. + */ + public function getDisplay() + { + return $this->getViewState('Display',TValidatorDisplayStyle::Fixed); + } + + /** + * @param TValidatorDisplayStyle the style of displaying the error message + */ + public function setDisplay($value) + { + $this->setViewState('Display',TPropertyValue::ensureEnum($value,'TValidatorDisplayStyle'),TValidatorDisplayStyle::Fixed); + } + + /** + * @return boolean whether client-side validation is enabled. + */ + public function getEnableClientScript() + { + return $this->getViewState('EnableClientScript',true); + } + + /** + * @param boolean whether client-side validation is enabled. + */ + public function setEnableClientScript($value) + { + $this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true); + } + + /** + * @return string the text for the error message. + */ + public function getErrorMessage() + { + return $this->getViewState('ErrorMessage',''); + } + + /** + * Sets the text for the error message. + * @param string the error message + */ + public function setErrorMessage($value) + { + $this->setViewState('ErrorMessage',$value,''); + } + + /** + * @return string the ID path of the input control to validate + */ + public function getControlToValidate() + { + return $this->getViewState('ControlToValidate',''); + } + + /** + * Sets the ID path of the input control to validate. + * The ID path is the dot-connected IDs of the controls reaching from + * the validator's naming container to the target control. + * @param string the ID path + */ + public function setControlToValidate($value) + { + $this->setViewState('ControlToValidate',$value,''); + } + + /** + * @return boolean whether to set focus at the validating place if the validation fails. Defaults to false. + */ + public function getFocusOnError() + { + return $this->getViewState('FocusOnError',false); + } + + /** + * @param boolean whether to set focus at the validating place if the validation fails + */ + public function setFocusOnError($value) + { + $this->setViewState('FocusOnError',TPropertyValue::ensureBoolean($value),false); + } + + /** + * Gets the ID of the HTML element that will receive focus if validation fails and {@link getFocusOnError FocusOnError} is true. + * Defaults to the client ID of the {@link getControlToValidate ControlToValidate}. + * @return string the ID of the HTML element to receive focus + */ + public function getFocusElementID() + { + if(($id=$this->getViewState('FocusElementID',''))==='') + $id=$this->getValidationTarget()->getClientID(); + return $id; + } + + /** + * Sets the ID of the HTML element that will receive focus if validation fails and {@link getFocusOnError FocusOnError} is true. + * @param string the ID of the HTML element to receive focus + */ + public function setFocusElementID($value) + { + $this->setViewState('FocusElementID', $value, ''); + } + + /** + * @return string the group which this validator belongs to + */ + public function getValidationGroup() + { + return $this->getViewState('ValidationGroup',''); + } + + /** + * @param string the group which this validator belongs to + */ + public function setValidationGroup($value) + { + $this->setViewState('ValidationGroup',$value,''); + } + + /** + * @return boolean whether the validation succeeds + */ + public function getIsValid() + { + return $this->_isValid; + } + + /** + * Sets the value indicating whether the validation succeeds + * @param boolean whether the validation succeeds + */ + public function setIsValid($value) + { + $this->_isValid=TPropertyValue::ensureBoolean($value); + } + + /** + * @return TControl control to be validated. Null if no control is found. + * @throws TConfigurationException if {@link getControlToValidate + * ControlToValidate} is empty or does not point to a valid control + */ + protected function getValidationTarget() + { + if(($id=$this->getControlToValidate())!=='' && ($control=$this->findControl($id))!==null) + return $control; + else + throw new TConfigurationException('basevalidator_controltovalidate_invalid',get_class($this)); + } + + /** + * Retrieves the property value of the control being validated. + * @param TControl control being validated + * @return string property value to be validated + * @throws TInvalidDataTypeException if the control to be validated does not implement {@link IValidatable}. + */ + protected function getValidationValue($control) + { + if($control instanceof IValidatable) + return $control->getValidationPropertyValue(); + else + throw new TInvalidDataTypeException('basevalidator_validatable_required',get_class($this)); + } + + /** + * Validates the specified control. + * Do not override this method. Override {@link evaluateIsValid} instead. + * @return boolean whether the validation succeeds + */ + public function validate() + { + $this->setIsValid(true); + $this->onValidate(); + if($this->getVisible(true) && $this->getEnabled(true)) + { + // if the target is not a disabled web control + if(($target=$this->getValidationTarget())!==null && !($target instanceof TWebControl && !$target->getEnabled(true))) + { + if($this->evaluateIsValid()) + { + $this->setIsValid(true); + $this->onValidationSuccess(); + } + else + { + $target->setIsValid(false); + $this->setIsValid(false); + $this->onValidationError(); + } + } + else + { + $this->evaluateIsValid(); + $this->setIsValid(true); + $this->onValidationSuccess(); + } + } + return $this->getIsValid(); + } + + /** + * @return string the css class that is applied to the control being validated in case the validation fails + */ + public function getControlCssClass() + { + return $this->getViewState('ControlCssClass',''); + } + + /** + * @param string the css class that is applied to the control being validated in case the validation fails + */ + public function setControlCssClass($value) + { + $this->setViewState('ControlCssClass',$value,''); + } + + /** + * This is the major method for validation. + * Derived classes should implement this method to provide customized validation. + * @return boolean whether the validation succeeds + */ + abstract protected function evaluateIsValid(); + + /** + * This event is raised when the validator succeeds in validation. + */ + public function onValidationSuccess() + { + $this->raiseEvent('OnValidationSuccess',$this,null); + } + + /** + * This event is raised when the validator fails in validation. + */ + public function onValidationError() + { + $this->raiseEvent('OnValidationError',$this,null); + } + + /** + * This event is raised right before the validator starts to perform validation. + * You may use this event to change the behavior of validation. + * For example, you may disable the validator if certain condition is satisfied. + * Note, the event will NOT be raised if the validator is invisible. + */ + public function onValidate() + { + $this->raiseEvent('OnValidate',$this,null); + } + + /** + * Renders the validator control. + * @param THtmlWriter writer for the rendering purpose + */ + public function renderContents($writer) + { + if(($text=$this->getText())!=='') + $writer->write($text); + else if(($text=$this->getErrorMessage())!=='') + $writer->write($text); + else + parent::renderContents($writer); + } +} + +/** + * TValidatorClientSide class. + * + * Client-side validator events can be modified through the {@link + * TBaseValidator::getClientSide ClientSide} property of a validator. The + * subproperties of ClientSide are those of the TValidatorClientSide + * properties. The client-side validator supports the following events. + * + * The OnValidate event is raise before the validator validation + * functions are called. + * + * The OnValidationSuccess event is raised after the validator has successfully + * validate the control. + * + * The OnValidationError event is raised after the validator fails validation. + * + * See the quickstart documentation for further details. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TValidatorClientSide extends TClientSideOptions +{ + /** + * @return string javascript code for client-side OnValidate event. + */ + public function getOnValidate() + { + return $this->getOption('OnValidate'); + } + + /** + * Client-side OnValidate validator event is raise before the validators + * validation functions are called. + * @param string javascript code for client-side OnValidate event. + */ + public function setOnValidate($javascript) + { + $this->setFunction('OnValidate', $javascript); + } + + /** + * Client-side OnSuccess event is raise after validation is successfull. + * This will override the default client-side validator behaviour. + * @param string javascript code for client-side OnSuccess event. + */ + public function setOnValidationSuccess($javascript) + { + $this->setFunction('OnValidationSuccess', $javascript); + } + + /** + * @return string javascript code for client-side OnSuccess event. + */ + public function getOnValidationSuccess() + { + return $this->getOption('OnValidationSuccess'); + } + + /** + * Client-side OnError event is raised after validation failure. + * This will override the default client-side validator behaviour. + * @param string javascript code for client-side OnError event. + */ + public function setOnValidationError($javascript) + { + $this->setFunction('OnValidationError', $javascript); + } + + /** + * @return string javascript code for client-side OnError event. + */ + public function getOnValidationError() + { + return $this->getOption('OnValidationError'); + } + + /** + * @param boolean true to revalidate when the control to validate changes value. + */ + public function setObserveChanges($value) + { + $this->setOption('ObserveChanges', TPropertyValue::ensureBoolean($value)); + } + + /** + * @return boolean true to observe changes. + */ + public function getObserveChanges() + { + $changes = $this->getOption('ObserveChanges'); + return ($changes===null) ? true : $changes; + } +} + + +/** + * TValidatorDisplayStyle class. + * TValidatorDisplayStyle defines the enumerable type for the possible styles + * that a validator control can display the error message. + * + * The following enumerable values are defined: + * - None: the error message is not displayed + * - Dynamic: the error message dynamically appears when the validator fails validation + * - Fixed: Similar to Dynamic except that the error message physically occupies the page layout (even though it may not be visible) + * + * @author Qiang Xue + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TValidatorDisplayStyle extends TEnumerable +{ + const None='None'; + const Dynamic='Dynamic'; + const Fixed='Fixed'; +} + +/** + * TValidationDataType class. + * TValidationDataType defines the enumerable type for the possible data types that + * a comparison validator can validate upon. + * + * The following enumerable values are defined: + * - Integer + * - Float + * - Date + * - String + * + * @author Qiang Xue + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TValidationDataType extends TEnumerable +{ + const Integer='Integer'; + const Float='Float'; + const Date='Date'; + const String='String'; +} + diff --git a/framework/Web/UI/WebControls/TColorPicker.php b/framework/Web/UI/WebControls/TColorPicker.php index 67a4ccfe..0fc7eef4 100644 --- a/framework/Web/UI/WebControls/TColorPicker.php +++ b/framework/Web/UI/WebControls/TColorPicker.php @@ -112,7 +112,7 @@ class TColorPicker extends TTextBox */ public function getClientSide() { - if(is_null($this->_clientSide)) + if($this->_clientSide===null) $this->_clientSide = $this->createClientSide(); return $this->_clientSide; } diff --git a/framework/Web/UI/WebControls/TDatePicker.php b/framework/Web/UI/WebControls/TDatePicker.php index 770099eb..e678b046 100644 --- a/framework/Web/UI/WebControls/TDatePicker.php +++ b/framework/Web/UI/WebControls/TDatePicker.php @@ -366,7 +366,7 @@ class TDatePicker extends TTextBox */ public function getClientSide() { - if(is_null($this->_clientScript)) + if($this->_clientScript===null) $this->_clientScript = $this->createClientScript(); return $this->_clientScript; } @@ -529,7 +529,7 @@ class TDatePicker extends TTextBox $options['PositionMode'] = $this->getPositionMode(); $options = array_merge($options, $this->getCulturalOptions()); - if(!is_null($this->_clientScript)) + if($this->_clientScript!==null) $options = array_merge($options, $this->_clientScript->getOptions()->toArray()); return $options; @@ -610,7 +610,7 @@ class TDatePicker extends TTextBox { $formatter = Prado::createComponent('System.Util.TSimpleDateFormatter', $this->getDateFormat()); - return !is_null($formatter->getDayPattern()); + return ($formatter->getDayPattern()!==null); } /** diff --git a/framework/Web/UI/WebControls/THtmlArea.php b/framework/Web/UI/WebControls/THtmlArea.php index 7e8bc370..ce789f38 100644 --- a/framework/Web/UI/WebControls/THtmlArea.php +++ b/framework/Web/UI/WebControls/THtmlArea.php @@ -451,10 +451,10 @@ class THtmlArea extends TTextBox protected function getLanguageSuffix($culture) { $app = $this->getApplication()->getGlobalization(); - if(empty($culture) && !is_null($app)) + if(empty($culture) && ($app!==null)) $culture = $app->getCulture(); $variants = array(); - if(!is_null($app)) + if($app!==null) $variants = $app->getCultureVariants($culture); foreach($variants as $variant) diff --git a/framework/Web/UI/WebControls/TListControl.php b/framework/Web/UI/WebControls/TListControl.php index 55b272c6..c69b387e 100644 --- a/framework/Web/UI/WebControls/TListControl.php +++ b/framework/Web/UI/WebControls/TListControl.php @@ -913,7 +913,7 @@ class TListItemCollection extends TList protected function createNewListItem($text=null) { $item = new TListItem; - if(!is_null($text)) + if($text!==null) $item->setText($text); return $item; } diff --git a/framework/Web/UI/WebControls/TStyle.php b/framework/Web/UI/WebControls/TStyle.php index 7cb1d8c8..1b94cc8e 100644 --- a/framework/Web/UI/WebControls/TStyle.php +++ b/framework/Web/UI/WebControls/TStyle.php @@ -4,7 +4,7 @@ * * @author Qiang Xue * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft * @license http://www.pradosoft.com/license/ * @version $Id$ * @package System.Web.UI.WebControls @@ -63,7 +63,7 @@ class TStyle extends TComponent */ public function __clone() { - if(!is_null($this->_font)) + if($this->_font!==null) $this->_font = clone($this->_font); } @@ -157,7 +157,7 @@ class TStyle extends TComponent */ public function hasCssClass() { - return !is_null($this->_class); + return ($this->_class!==null); } /** diff --git a/framework/Web/UI/WebControls/TValidationSummary.php b/framework/Web/UI/WebControls/TValidationSummary.php index 95679e15..e60a40db 100644 --- a/framework/Web/UI/WebControls/TValidationSummary.php +++ b/framework/Web/UI/WebControls/TValidationSummary.php @@ -4,7 +4,7 @@ * * @author Qiang Xue * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft * @license http://www.pradosoft.com/license/ * @version $Id$ * @package System.Web.UI.WebControls @@ -261,7 +261,7 @@ class TValidationSummary extends TWebControl $options['ValidationGroup'] = $this->getValidationGroup(); $options['Display'] = $this->getDisplay(); - if(!is_null($this->_clientSide)) + if($this->_clientSide!==null) $options = array_merge($options,$this->_clientSide->getOptions()->toArray()); return $options; @@ -273,7 +273,7 @@ class TValidationSummary extends TWebControl */ public function getClientSide() { - if(is_null($this->_clientSide)) + if($this->_clientSide===null) $this->_clientSide = $this->createClientScript(); return $this->_clientSide; } -- cgit v1.2.3