diff options
Diffstat (limited to 'framework')
-rw-r--r-- | framework/Exceptions/TErrorHandler.php | 3 | ||||
-rw-r--r-- | framework/Exceptions/messages.txt | 8 | ||||
-rw-r--r-- | framework/TApplication.php | 6 | ||||
-rw-r--r-- | framework/Web/Services/TPageService.php | 48 | ||||
-rw-r--r-- | framework/Web/TAssetManager.php | 2 | ||||
-rw-r--r-- | framework/Web/THiddenFieldPageStatePersister.php | 80 | ||||
-rw-r--r-- | framework/Web/TThemeManager.php | 15 | ||||
-rw-r--r-- | framework/Web/UI/TClientScriptManager.php | 174 | ||||
-rw-r--r-- | framework/Web/UI/TControl.php | 2 | ||||
-rw-r--r-- | framework/Web/UI/THiddenFieldPageStatePersister.php | 37 | ||||
-rw-r--r-- | framework/Web/UI/TPage.php | 567 | ||||
-rw-r--r-- | framework/Web/UI/WebControls/TButton.php | 2 | ||||
-rw-r--r-- | framework/Web/UI/WebControls/TCheckBox.php | 4 | ||||
-rw-r--r-- | framework/Web/UI/WebControls/TImageButton.php | 2 | ||||
-rw-r--r-- | framework/core.php | 24 |
15 files changed, 636 insertions, 338 deletions
diff --git a/framework/Exceptions/TErrorHandler.php b/framework/Exceptions/TErrorHandler.php index 8af92ecc..e9f48a2b 100644 --- a/framework/Exceptions/TErrorHandler.php +++ b/framework/Exceptions/TErrorHandler.php @@ -67,7 +67,7 @@ class TErrorHandler extends TComponent implements IModule /**
* @var string module ID
*/
- private $_id;
+ private $_id='error';
/**
* @var TApplication application instance
*/
@@ -86,7 +86,6 @@ class TErrorHandler extends TComponent implements IModule public function init($application,$config)
{
$this->_application=$application;
- $application->attachEventHandler('Error',array($this,'handleError'));
$application->setErrorHandler($this);
}
diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt index 4c6a4c87..8a20b0c0 100644 --- a/framework/Exceptions/messages.txt +++ b/framework/Exceptions/messages.txt @@ -34,9 +34,9 @@ appconfig_alias_invalid = Application configuration <alias> element must hav appconfig_alias_redefined = Application configuration <alias id="%s"> cannot be redefined.
appconfig_using_invalid = Application configuration <using> element must have a "namespace" attribute.
appconfig_moduleid_required = Application configuration <module> element must have an "id" attribute.
-appconfig_moduletype_required = Application configuration <module id="%s"> must have a "type" attribute.
+appconfig_moduletype_required = Application configuration <module id="%s"> must have a "class" attribute.
appconfig_serviceid_required = Application configuration <service> element must have an "id" attribute.
-appconfig_servicetype_required = Application configuration <service id="%s"> must have a "type" attribute.
+appconfig_servicetype_required = Application configuration <service id="%s"> must have a "class" attribute.
appconfig_parameterid_required = Application configuration <parameter> element must have an "id" attribute.
uri_format_invalid = '%s' is not a valid URI.
@@ -86,9 +86,9 @@ pageserviceconf_aliaspath_invalid = <alias id="%s"> uses an invalid file path " pageserviceconf_alias_invalid = <alias> element must have an "id" attribute and a "path" attribute in page directory configuration file '%s'.
pageserviceconf_using_invalid = <using> element must have a "namespace" attribute in page directory configuration file '%s'.
pageserviceconf_module_invalid = <module> element must have an "id" attribute in page directory configuration file '%s'.
-pageserviceconf_moduletype_required = <module id="%s"> must have a "type" attribute in page directory configuration file '%s'.
+pageserviceconf_moduletype_required = <module id="%s"> must have a "class" attribute in page directory configuration file '%s'.
pageserviceconf_parameter_invalid = <parameter> element must have an "id" attribute in page directory configuration file '%s'.
-pageserviceconf_page_invalid = <page> element must have an "id" attribute and a "type" attribute in page directory configuration file '%s'.
+pageserviceconf_page_invalid = <page> element must have an "id" attribute and a "class" attribute in page directory configuration file '%s'.
template_templatefile_invalid = Template file '%s' cannot open.
template_closingtag_unexpected = %s: Unexpected closing tag '%s' is found.
diff --git a/framework/TApplication.php b/framework/TApplication.php index bd8e8e39..3f9457ea 100644 --- a/framework/TApplication.php +++ b/framework/TApplication.php @@ -808,7 +808,7 @@ class TApplicationConfiguration extends TComponent $properties=$node->getAttributes();
if(($id=$properties->itemAt('id'))===null)
throw new TConfigurationException('appconfig_moduleid_required');
- if(($type=$properties->remove('type'))===null && isset($this->_modules[$id]) && $this->_modules[$id][2]===null)
+ if(($type=$properties->remove('class'))===null && isset($this->_modules[$id]) && $this->_modules[$id][2]===null)
$type=$this->_modules[$id][0];
if($type===null)
throw new TConfigurationException('appconfig_moduletype_required',$id);
@@ -825,7 +825,7 @@ class TApplicationConfiguration extends TComponent $properties=$node->getAttributes();
if(($id=$properties->itemAt('id'))===null)
throw new TConfigurationException('appconfig_serviceid_required');
- if(($type=$properties->remove('type'))===null && isset($this->_services[$id]) && $this->_services[$id][2]===null)
+ if(($type=$properties->remove('class'))===null && isset($this->_services[$id]) && $this->_services[$id][2]===null)
$type=$this->_services[$id][0];
if($type===null)
throw new TConfigurationException('appconfig_servicetype_required',$id);
@@ -842,7 +842,7 @@ class TApplicationConfiguration extends TComponent $properties=$node->getAttributes();
if(($id=$properties->remove('id'))===null)
throw new TConfigurationException('appconfig_parameterid_required');
- if(($type=$properties->remove('type'))===null)
+ if(($type=$properties->remove('class'))===null)
$this->_parameters[$id]=$node->getValue();
else
$this->_parameters[$id]=array($type,$properties->toArray());
diff --git a/framework/Web/Services/TPageService.php b/framework/Web/Services/TPageService.php index 6ef07d03..078f8706 100644 --- a/framework/Web/Services/TPageService.php +++ b/framework/Web/Services/TPageService.php @@ -17,6 +17,7 @@ Prado::using('System.Web.UI.TPage'); Prado::using('System.Web.TTemplateManager');
Prado::using('System.Web.TThemeManager');
Prado::using('System.Web.TAssetManager');
+Prado::using('System.Web.THiddenFieldPageStatePersister');
/**
* TPageService class.
@@ -102,6 +103,10 @@ class TPageService extends TComponent implements IService */
private $_pageType;
/**
+ * @var TPage the requested page
+ */
+ private $_page=null;
+ /**
* @var array list of initial page property values
*/
private $_properties;
@@ -125,6 +130,10 @@ class TPageService extends TComponent implements IService * @var TTemplateManager template manager
*/
private $_templateManager=null;
+ /**
+ * @var IPageStatePersister page state persister
+ */
+ private $_pageStatePersister=null;
/**
* Initializes the service.
@@ -312,6 +321,27 @@ class TPageService extends TComponent implements IService }
/**
+ * @return IPageStatePersister page state persister
+ */
+ public function getPageStatePersister()
+ {
+ if(!$this->_pageStatePersister)
+ {
+ $this->_pageStatePersister=new THiddenFieldPageStatePersister;
+ $this->_pageStatePersister->init($this->_application,null);
+ }
+ return $this->_pageStatePersister;
+ }
+
+ /**
+ * @param IPageStatePersister page state persister
+ */
+ public function setPageStatePersister(IPageStatePersister $value)
+ {
+ $this->_pageStatePersister=$value;
+ }
+
+ /**
* @return string the requested page path
*/
public function getRequestedPagePath()
@@ -320,6 +350,14 @@ class TPageService extends TComponent implements IService }
/**
+ * @return TPage the requested page
+ */
+ public function getRequestedPage()
+ {
+ return $this->_page;
+ }
+
+ /**
* @return string default page path to be served if no explicit page is request
*/
public function getDefaultPage()
@@ -391,11 +429,11 @@ class TPageService extends TComponent implements IService }
}
if(class_exists($className,false))
- $page=new $className($this->_properties);
+ $this->_page=new $className($this->_properties);
else
throw new THttpException(404,'pageservice_page_unknown',$this->_pageType);
$writer=$this->_application->getResponse()->createHtmlWriter();
- $page->run($writer);
+ $this->_page->run($writer);
$writer->flush();
}
@@ -624,7 +662,7 @@ class TPageConfiguration extends TComponent foreach($modulesNode->getElementsByTagName('module') as $node)
{
$properties=$node->getAttributes();
- $type=$properties->remove('type');
+ $type=$properties->remove('class');
if(($id=$properties->itemAt('id'))===null)
throw new TConfigurationException('pageserviceconf_module_invalid',$configPath);
if(isset($this->_modules[$id]))
@@ -660,7 +698,7 @@ class TPageConfiguration extends TComponent $properties=$node->getAttributes();
if(($id=$properties->remove('id'))===null)
throw new TConfigurationException('pageserviceconf_parameter_invalid',$configPath);
- if(($type=$properties->remove('type'))===null)
+ if(($type=$properties->remove('class'))===null)
$this->_parameters[$id]=$node->getValue();
else
$this->_parameters[$id]=array($type,$properties->toArray());
@@ -704,7 +742,7 @@ class TPageConfiguration extends TComponent foreach($pagesNode->getElementsByTagName('page') as $node)
{
$properties=$node->getAttributes();
- $type=$properties->remove('type');
+ $type=$properties->remove('class');
$id=$properties->itemAt('id');
if($id===null || $type===null)
throw new TConfigurationException('pageserviceconf_page_invalid',$configPath);
diff --git a/framework/Web/TAssetManager.php b/framework/Web/TAssetManager.php index 3e7df967..e2b9f9a8 100644 --- a/framework/Web/TAssetManager.php +++ b/framework/Web/TAssetManager.php @@ -58,7 +58,7 @@ class TAssetManager extends TComponent implements IModule /**
* @var string module ID
*/
- private $_id;
+ private $_id='asset';
/**
* @var boolean whether to use timestamp checking to ensure files are published with up-to-date versions.
*/
diff --git a/framework/Web/THiddenFieldPageStatePersister.php b/framework/Web/THiddenFieldPageStatePersister.php new file mode 100644 index 00000000..3d305668 --- /dev/null +++ b/framework/Web/THiddenFieldPageStatePersister.php @@ -0,0 +1,80 @@ +<?php
+
+class THiddenFieldPageStatePersister extends TComponent implements IPageStatePersister, IModule
+{
+ private $_application;
+ private $_id='persister';
+
+ /**
+ * Initializes the service.
+ * This method is required by IModule interface.
+ * @param TApplication application
+ * @param TXmlElement module configuration
+ */
+ public function init($application,$config)
+ {
+ $this->_application=$application;
+ }
+
+ /**
+ * @return string id of this module
+ */
+ public function getID()
+ {
+ return $this->_id;
+ }
+
+ /**
+ * @param string id of this module
+ */
+ public function setID($value)
+ {
+ $this->_id=$value;
+ }
+
+ public function save($state)
+ {
+ $data=Prado::serialize($state);
+ $hmac=$this->computeHMAC($data,$this->getKey());
+ if(function_exists('gzuncompress') && function_exists('gzcompress'))
+ $data=gzcompress($hmac.$data);
+ else
+ $data=$hmac.$data;
+ $this->_application->getService()->getRequestedPage()->saveStateField($data);
+ }
+
+ public function load()
+ {
+ $str=$this->_application->getService()->getRequestedPage()->loadStateField();
+ if($str==='')
+ return null;
+ if(function_exists('gzuncompress') && function_exists('gzcompress'))
+ $data=gzuncompress($str);
+ else
+ $data=$str;
+ if($data!==false && strlen($data)>32)
+ {
+ $hmac=substr($data,0,32);
+ $state=substr($data,32);
+ if($hmac===$this->computeHMAC($state,$this->getKey()))
+ return Prado::unserialize($state);
+ }
+ throw new Exception('viewstate data is corrupted.');
+ }
+
+ private function getKey()
+ {
+ return 'abcdefe';
+ }
+
+ private function computeHMAC($data,$key)
+ {
+ if (strlen($key) > 64)
+ $key = pack('H32', md5($key));
+ else if (strlen($key) < 64)
+ $key = str_pad($key, 64, "\0");
+ return md5((str_repeat("\x5c", 64) ^ substr($key, 0, 64)) . pack('H32', md5((str_repeat("\x36", 64) ^ substr($key, 0, 64)) . $data)));
+ }
+}
+
+?>
\ No newline at end of file diff --git a/framework/Web/TThemeManager.php b/framework/Web/TThemeManager.php index 0a54cf8e..504e8ecb 100644 --- a/framework/Web/TThemeManager.php +++ b/framework/Web/TThemeManager.php @@ -45,7 +45,7 @@ class TThemeManager extends TComponent implements IModule /**
* @var string module ID
*/
- private $_id;
+ private $_id='theme';
/**
* @var boolean whether this module has been initialized
*/
@@ -212,6 +212,10 @@ class TTheme extends TComponent * @var array list of skins for the theme
*/
private $_skins=null;
+ /**
+ * @var string theme name
+ */
+ private $_name='';
/**
* Constructor.
@@ -223,6 +227,7 @@ class TTheme extends TComponent public function __construct($application,$themePath,$themeUrl)
{
$this->_themeUrl=$themeUrl;
+ $this->_name=basename($themePath);
if(($cache=$application->getCache())!==null)
{
$array=$cache->get(self::THEME_CACHE_PREFIX.$themePath);
@@ -284,6 +289,14 @@ class TTheme extends TComponent }
/**
+ * @return string theme name
+ */
+ public function getName()
+ {
+ return $this->_name;
+ }
+
+ /**
* Applies the theme to a particular control.
* The control's class name and SkinID value will be used to
* identify which skin to be applied. If the control's SkinID is empty,
diff --git a/framework/Web/UI/TClientScriptManager.php b/framework/Web/UI/TClientScriptManager.php index 7bbbbdfa..d4aea650 100644 --- a/framework/Web/UI/TClientScriptManager.php +++ b/framework/Web/UI/TClientScriptManager.php @@ -33,7 +33,13 @@ class TPostBackOptions extends TComponent class TClientScriptManager extends TComponent
{
- const POSTBACK_FUNC='__doPostBack';
+ const SCRIPT_DIR='Web/Javascripts/js';
+ const POSTBACK_FUNC='Prado.PostBack.perform';
+ const POSTBACK_OPTIONS='Prado.PostBack.Options';
+ const FIELD_POSTBACK_TARGET='PRADO_POSTBACK_TARGET';
+ const FIELD_POSTBACK_PARAMETER='PRADO_POSTBACK_PARAMETER';
+ const FIELD_LASTFOCUS='PRADO_LASTFOCUS';
+ const FIELD_PAGE_STATE='PRADO_PAGE_STATE';
private $_owner;
private $_hiddenFields=array();
private $_scriptBlocks=array();
@@ -48,78 +54,89 @@ class TClientScriptManager extends TComponent $this->_owner=$owner;
}
- public function getPostBackEventReference($options,$javascriptPrefix=true)
+ public function getPostBackEventReference($control,$parameter='',$options=null,$javascriptPrefix=true)
{
- $str=$javascriptPrefix?'javascript:':'';
- if($options->AutoPostBack)
- $str.="setTimeout('";
- if(!$options->PerformValidation && !$options->TrackFocus && $options->ClientSubmit && $options->ActionUrl==='')
+ if($options)
{
- $this->registerPostBackScript();
- $postback=self::POSTBACK_FUNC.'(\''.$options->TargetControl->getUniqueID().'\',\''.THttpUtility::quoteJavaScriptString($options->Argument).'\')';
- if($options->AutoPostBack)
+ $flag=false;
+ $opt='new '.self::POSTBACK_OPTIONS.'(';
+ if($options->PerformValidation)
{
- $str.=THttpUtility::quoteJavaScriptString($postback);
- $str.="',0)";
+ $flag=true;
+ $this->registerValidationScript();
+ $opt.='true,';
}
else
- $str.=$postback;
- return $str;
- }
- $str.='WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("';
- $str.=$options->TargetControl->getUniqueID().'", ';
- if(($arg=$options->Argument)==='')
- $str.='"", ';
- else
- $str.='"'.THttpUtility::quoteJavaScriptString($arg).'", ';
- $flag=false;
- if($options->PerformValidation)
- {
- $flag=true;
- $str.='true, ';
- }
- else
- $str.='false, ';
- if($options->ValidationGroup!=='')
- {
- $flag=true;
- $str.='"'.$options->ValidationGroup.'", ';
- }
- else
- $str.='"", ';
- if($options->ActionUrl!=='')
- {
- $flag=true;
- $this->_owner->setContainsCrossPagePost(true);
- $str.='"'.THttpUtility::quoteJavaScriptString($options->ActionUrl).'", ';
- }
- else
- $str.='"", ';
- if($options->TrackFocus)
- {
- $this->_owner->registerFocusScript();
- $flag=true;
- $str.='true, ';
- }
- else
- $str.='false, ';
- if($options->ClientSubmit)
- {
- $flag=true;
- $this->_owner->registerPostBackScript();
- $str.='true))';
- }
- else
- $str.='false))';
- if($options->AutoPostBack)
- $str.="', 0)";
- if($flag)
- {
- $this->_owner->registerWebFormsScript();
- return $str;
+ $opt.='false,';
+ if($options->ValidationGroup!=='')
+ {
+ $flag=true;
+ $opt.='"'.$options->ValidationGroup.'",';
+ }
+ else
+ $opt.='"",';
+ if($options->ActionUrl!=='')
+ {
+ $flag=true;
+ $this->_owner->setCrossPagePostBack(true);
+ $opt.='"'.THttpUtility::quoteJavaScriptString($options->ActionUrl).'",';
+ }
+ else
+ $opt.='"",';
+ if($options->TrackFocus)
+ {
+ $flag=true;
+ $this->registerFocusScript();
+ $opt.='true,';
+ }
+ else
+ $opt.='false,';
+ if($options->ClientSubmit)
+ {
+ $flag=true;
+ $opt.='true)';
+ }
+ else
+ $opt.='false)';
+ //if(!$flag)
+ // return '';
}
else
- return '';
+ $opt='null';
+ $this->registerPostBackScript();
+ $formID=$this->_owner->getForm()->getUniqueID();
+ $postback=self::POSTBACK_FUNC.'(\''.$formID.'\',\''.$control->getUniqueID().'\',\''.THttpUtility::quoteJavaScriptString($parameter).'\','.$opt.')';
+ if($options && $options->AutoPostBack)
+ $postback='setTimeout(\''.THttpUtility::quoteJavaScriptString($postback).'\',0)';
+ return $javascriptPrefix?'javascript:'.$postback:$postback;
+ }
+
+ protected function registerPostBackScript()
+ {
+ $this->registerHiddenField(self::FIELD_POSTBACK_TARGET,'');
+ $this->registerHiddenField(self::FIELD_POSTBACK_PARAMETER,'');
+ $am=$this->_owner->getService()->getAssetManager();
+ $url=$am->publishFilePath(Prado::getFrameworkPath().'/'.self::SCRIPT_DIR.'/base.js');
+ $this->registerScriptInclude('prado:base',$url);
+ }
+
+ public function registerFocusScript()
+ {
+ // need Focus.js
+ }
+
+ public function registerScrollScript()
+ {
+ $this->registerHiddenField(self::FIELD_SCROLL_X,$this->_owner->getScrollPositionX());
+ $this->registerHiddenField(self::FIELD_SCROLL_Y,$this->_owner->getScrollPositionY());
+ /*
+ this.ClientScript.RegisterStartupScript(typeof(Page), "PageScrollPositionScript", "\r\ntheForm.oldSubmit = theForm.submit;\r\ntheForm.submit = WebForm_SaveScrollPositionSubmit;\r\n\r\ntheForm.oldOnSubmit = theForm.onsubmit;\r\ntheForm.onsubmit = WebForm_SaveScrollPositionOnSubmit;\r\n" + (this.IsPostBack ? "\r\ntheForm.oldOnLoad = window.onload;\r\nwindow.onload = WebForm_RestoreScrollPosition;\r\n" : string.Empty), true);
+ need base.js
+ */
+ }
+
+ public function registerValidationScript()
+ {
}
public function isHiddenFieldRegistered($key)
@@ -226,11 +243,14 @@ class TClientScriptManager extends TComponent public function renderStartupScripts($writer)
{
+ $str='';
+ foreach($this->_scriptIncludes as $include)
+ $str.="\n<script type=\"text/javascript\" src=\"".THttpUtility::htmlEncode($include)."\"></script>";
if(count($this->_startupScripts))
{
- $str="\n<script type=\"text/javascript\">\n<!--\n";
+ $str.="\n<script type=\"text/javascript\">\n<!--\n";
foreach($this->_startupScripts as $script)
- $str.="\n".$script;
+ $str.=$script;
$str.="// -->\n</script>\n";
$writer->write($str);
}
@@ -292,24 +312,6 @@ class TClientScriptManager extends TComponent public void ValidateEvent(string uniqueId, string argument);
public function getCallbackEventReference()
*/
-
- public function registerPostBackScript()
- {
- $this->registerHiddenField('__EVENTTARGET','');
- $this->registerHiddenField('__EVENTPARAM','');
- $id=$this->_owner->getForm()->getUniqueID();
- $script=<<<EOD
-function __doPostBack(eventTarget, eventParameter) {
- var validation = typeof(Prado) != 'undefined' && typeof(Prado.Validation) != 'undefined';
- var theform = document.getElementById ? document.getElementById('$id') : document.forms['$id'];
- theform.__EVENTTARGET.value = eventTarget.split('\$').join(':');
- theform.__EVENTPARAMETER.value = eventParameter;
- if(!validation || Prado.Validation.OnSubmit(theform))
- theform.submit();
-}
-EOD;
- $this->registerStartupScript('form',$script);
- }
}
?>
\ No newline at end of file diff --git a/framework/Web/UI/TControl.php b/framework/Web/UI/TControl.php index a3c031f4..0e601386 100644 --- a/framework/Web/UI/TControl.php +++ b/framework/Web/UI/TControl.php @@ -983,7 +983,7 @@ class TControl extends TComponent if($this->_stage<self::CS_INITIALIZED)
{
$this->_stage=self::CS_CHILD_INITIALIZED;
- if(($page=$this->getPage()) && $page->getContainsTheme() && $this->getEnableTheming() && !($this->_flags & self::IS_SKIN_APPLIED))
+ if(($page=$this->getPage()) && $this->getEnableTheming() && !($this->_flags & self::IS_SKIN_APPLIED))
{
$page->applyControlSkin($this);
$this->_flags |= self::IS_SKIN_APPLIED;
diff --git a/framework/Web/UI/THiddenFieldPageStatePersister.php b/framework/Web/UI/THiddenFieldPageStatePersister.php index 24ef5491..3d305668 100644 --- a/framework/Web/UI/THiddenFieldPageStatePersister.php +++ b/framework/Web/UI/THiddenFieldPageStatePersister.php @@ -1,14 +1,35 @@ <?php
-require_once(PRADO_DIR.'/Web/UI/TPageStatePersister.php');
-
-class THiddenFieldPageStatePersister extends TPageStatePersister
+class THiddenFieldPageStatePersister extends TComponent implements IPageStatePersister, IModule
{
- private $_page;
+ private $_application;
+ private $_id='persister';
+
+ /**
+ * Initializes the service.
+ * This method is required by IModule interface.
+ * @param TApplication application
+ * @param TXmlElement module configuration
+ */
+ public function init($application,$config)
+ {
+ $this->_application=$application;
+ }
+
+ /**
+ * @return string id of this module
+ */
+ public function getID()
+ {
+ return $this->_id;
+ }
- public function __construct($page)
+ /**
+ * @param string id of this module
+ */
+ public function setID($value)
{
- $this->_page=$page;
+ $this->_id=$value;
}
public function save($state)
@@ -19,12 +40,12 @@ class THiddenFieldPageStatePersister extends TPageStatePersister $data=gzcompress($hmac.$data);
else
$data=$hmac.$data;
- $this->_page->saveStateField($data);
+ $this->_application->getService()->getRequestedPage()->saveStateField($data);
}
public function load()
{
- $str=$this->_page->loadStateField();
+ $str=$this->_application->getService()->getRequestedPage()->loadStateField();
if($str==='')
return null;
if(function_exists('gzuncompress') && function_exists('gzcompress'))
diff --git a/framework/Web/UI/TPage.php b/framework/Web/UI/TPage.php index 902a0212..9eb50cde 100644 --- a/framework/Web/UI/TPage.php +++ b/framework/Web/UI/TPage.php @@ -5,19 +5,44 @@ Prado::using('System.Web.UI.WebControls.*'); class TPage extends TTemplateControl
{
+ /**
+ * @var TApplication application instance
+ */
private $_application;
- private $_contentTemplateCollection=null;
+ /**
+ * @var TPageService page service instance
+ */
+ private $_pageService;
+ /**
+ * @var string template file name
+ */
+ private $_templateFile=null;
+ /**
+ * @var array list of registered validators
+ */
+ private $_validators=array();
+ /**
+ * @var boolean if validation has been performed
+ */
+ private $_validated=false;
+ /**
+ * @var TTheme page theme
+ */
+ private $_theme=null;
+ /**
+ * @var TTheme page stylesheet theme
+ */
+ private $_styleSheet=null;
+ /**
+ * @var TClientScriptManager client script manager
+ */
+ private $_clientScript=null;
+
private $_maxPageStateFieldLength=10;
private $_enableViewStateMac=true;
private $_performPreRendering=true;
private $_performRendering=true;
- private $_supportsStyleSheet=true;
- private $_theme=null;
- private $_themeName='';
- private $_styleSheet=null;
- private $_styleSheetName='';
- private $_clientScript=null;
private $_form=null;
private $_formRendered=false;
private $_inFormRender=false;
@@ -34,18 +59,20 @@ class TPage extends TTemplateControl private $_controlsRequiringPostBack=array();
private $_registeredControlThatRequireRaiseEvent=null;
private $_registeredControlsThatRequirePostBack=null;
- private $_validators=array();
- private $_validated=false;
private $_autoPostBackControl=null;
private $_webFormsScriptRendered=false;
private $_requireWebFormsScript=false;
private static $_systemPostFields=array('__EVENTTARGET','__EVENTPARAM','__STATE','__PREVPAGE','__CALLBACKID','__CALLBACKPARAM','__LASTFOCUS');
- private $_contents=array();
- private $_templateFile=null;
+ /**
+ * Constructor.
+ * If initial property values are given, they will be set to the page.
+ * @param array initial property values for the page.
+ */
public function __construct($initProperties=null)
{
$this->_application=Prado::getApplication();
+ $this->_pageService=$this->_application->getService();
$this->setPage($this);
if(is_array($initProperties))
{
@@ -56,7 +83,9 @@ class TPage extends TTemplateControl }
/**
- * Loads and parses the control template
+ * Loads and parses the page template.
+ * This method overrides the parent implementation by allowing loading
+ * a page template from a specified template file.
* @return ITemplate the parsed template structure
*/
protected function loadTemplate()
@@ -65,125 +94,376 @@ class TPage extends TTemplateControl return parent::loadTemplate();
else
{
- $template=Prado::getApplication()->getService()->getTemplateManager()->getTemplateByFileName(Prado::getPathOfNamespace($this->_templateFile,'.tpl'));
+ $template=$this->_pageService->getTemplateManager()->getTemplateByFileName($this->_templateFile);
$this->setTemplate($template);
return $template;
}
}
+ /**
+ * @return string the user-specified template file, defaults to null.
+ */
public function getTemplateFile()
{
return $this->_templateFile;
}
+ /**
+ * Sets the user-specified template file.
+ * The template file must be specified in a namespace format.
+ * @param string the user-specified template file.
+ * @throws TInvalidDataValueException if the file is not in namespace format.
+ */
public function setTemplateFile($value)
{
- $this->_templateFile=$value;
+ if(($templateFile=Prado::getPathOfNamespace($value,TTemplateManager::TEMPLATE_FILE_EXT))===null)
+ throw new TInvalidDataValueException('page_templatefile_invalid',$value);
+ else
+ $this->_templateFile=$templateFile;
}
- final public function setForm($form)
+ /**
+ * Registers a TForm instance to the page.
+ * Note, a page can contain at most one TForm instance.
+ * @param TForm the form on the page
+ * @throws TInvalidOperationException if this method is invoked twice or more.
+ */
+ public function setForm(TForm $form)
{
- $this->_form=$form;
+ if($this->_form===null)
+ $this->_form=$form;
+ else
+ throw new TInvalidOperationException('page_form_duplicated');
}
- final public function getForm()
+ /**
+ * @return TForm the form on the page
+ */
+ public function getForm()
{
return $this->_form;
}
- public function validate($validationGroup='')
+ /**
+ * Returns a list of registered validators.
+ * If validation group is specified, only the validators in that group will be returned.
+ * @param string validation group
+ * @return TList registered validators
+ */
+ public function getValidators($validationGroup='')
{
- $this->_validated=true;
+ if(!$this->_validators)
+ $this->_validators=new TList;
if($validationGroup==='')
- {
- foreach($this->_validators as $validator)
- $validator->validate();
- }
+ return $this->_validators;
else
{
+ $list=new TList;
foreach($this->_validators as $validator)
if($validator->getValidationGroup()===$validationGroup)
- $validator->validate();
+ $list->add($validator);
+ return $list;
}
}
- public function RegisterEnabledControl($control)
+ /**
+ * Performs input validation.
+ * This method will invoke the registered validators to perform the actual validation.
+ * If validation group is specified, only the validators in that group will be invoked.
+ * @param string validation group
+ */
+ public function validate($validationGroup='')
{
- $this->getEna.EnabledControls.Add(control);
+ $this->_validated=true;
+ if($this->_validators && $this->_validators->getCount())
+ {
+ if($validationGroup==='')
+ {
+ foreach($this->_validators as $validator)
+ $validator->validate();
+ }
+ else
+ {
+ foreach($this->_validators as $validator)
+ if($validator->getValidationGroup()===$validationGroup)
+ $validator->validate();
+ }
+ }
}
-
-
/**
- * @internal
+ * Returns whether user input is valid or not.
+ * This method must be invoked after {@link validate} is called.
+ * @return boolean whether the user input is valid or not.
+ * @throws TInvalidOperationException if {@link validate} is not invoked yet.
*/
- public function registerPostBackScript()
+ public function getIsValid()
{
- if($this->getClientSupportsJavaScript() && !$this->_postBackScriptRendered)
+ if($this->_validated)
{
- if(!$this->_requirePostBackScript)
+ if($this->_validators && $this->_validators->getCount())
{
- $this->getClientScript()->registerHiddenField('__EVENTTARGET','');
- $this->getClientScript()->registerHiddenField('__EVENTPARAM','');
- $this->_requirePostBackScript=true;
+ foreach($this->_validators as $validator)
+ if(!$validator->getIsValid())
+ return false;
}
+ return true;
}
+ else
+ throw new TInvalidOperationException('page_isvalid_unknown');
}
- public function registerWebFormsScript()
+ /**
+ * @return TTheme the theme used for the page. Defaults to null.
+ */
+ public function getTheme()
{
- if($this->getClientSupportsJavaScript() && !$this->_webFormsScriptRendered)
- {
- $this->registerPostBackScript();
- $this->_requireWebFormsScript=true;
- }
+ if(is_string($this->_theme))
+ $this->_theme=$this->_pageService->getThemeManager()->getTheme($this->_theme);
+ return $this->_theme;
}
+ /**
+ * Sets the theme to be used for the page.
+ * @param string|TTheme the theme name or the theme object to be used for the page.
+ * @throws TInvalidDataTypeException if the parameter is neither a string nor a TTheme object
+ */
+ public function setTheme($value)
+ {
+ $this->_theme=$value;
+ }
- public function ensureRenderInForm($control)
+
+ /**
+ * @return TTheme the stylesheet theme used for the page. Defaults to null.
+ */
+ public function getStyleSheetTheme()
{
- if(!$this->_inFormRender)
- throw new THttpException('control_not_in_form',$control->getUniqueID());
+ if(is_string($this->_styleSheet))
+ $this->_styleSheet=$this->_pageService->getThemeManager()->getTheme($this->_styleSheet);
+ return $this->_styleSheet;
}
/**
- * @internal
+ * Sets the stylesheet theme to be used for the page.
+ * @param string|TTheme the stylesheet theme name or the stylesheet theme object to be used for the page.
+ * @throws TInvalidDataTypeException if the parameter is neither a string nor a TTheme object
*/
- final protected function addContentTemplate($name,$template)
+ public function setStyleSheetTheme($value)
{
- if(!$this->_contentTemplateCollection)
- $this->_contentTemplateCollection=new TMap;
- if($this->_contentTemplateCollection->has($name))
- throw new Exception("Content '$name' duplicated.");
- $this->_contentTemplateCollection->add($name,$template);
+ $this->_styleSheet=$value;
}
/**
- * @internal
+ * Applies a skin in the current theme to a control.
+ * This method should only be used by framework developers.
+ * @param TControl a control to be applied skin with
+ */
+ public function applyControlSkin($control)
+ {
+ if(($theme=$this->getTheme())!==null)
+ $theme->applySkin($control);
+ }
+
+ /**
+ * Applies a stylesheet skin in the current theme to a control.
+ * This method should only be used by framework developers.
+ * @param TControl a control to be applied stylesheet skin with
+ */
+ public function applyControlStyleSheet($control)
+ {
+ if(($theme=$this->getStyleSheetTheme())!==null)
+ $theme->applySkin($control);
+ }
+
+ /**
+ * @return TClientScriptManager client script manager
+ */
+ public function getClientScript()
+ {
+ if(!$this->_clientScript)
+ $this->_clientScript=new TClientScriptManager($this);
+ return $this->_clientScript;
+ }
+
+ /**
+ * Raises PreInit event.
+ * This method is invoked right before {@link onInit Init} stage.
+ * You may override this method to provide additional initialization that
+ * should be done before {@link onInit Init} (e.g. setting {@link setTheme Theme} or
+ * {@link setStyleSheetTheme StyleSheetTheme}).
+ * Remember to call the parent implementation to ensure PreInit event is raised.
+ * @param mixed event parameter
+ */
+ protected function onPreInit($param)
+ {
+ $this->raiseEvent('PreInit',$this,$param);
+ }
+
+ /**
+ * Raises InitComplete event.
+ * This method is invoked right after {@link onInit Init} stage and before {@link onLoad Load} stage.
+ * You may override this method to provide additional initialization that
+ * should be done after {@link onInit Init}.
+ * Remember to call the parent implementation to ensure InitComplete event is raised.
+ * @param mixed event parameter
+ */
+ protected function onInitComplete($param)
+ {
+ $this->raiseEvent('InitComplete',$this,$param);
+ }
+
+ /**
+ * Raises PreLoad event.
+ * This method is invoked right before {@link onLoad Load} stage.
+ * You may override this method to provide additional page loading logic that
+ * should be done before {@link onLoad Load}.
+ * Remember to call the parent implementation to ensure PreLoad event is raised.
+ * @param mixed event parameter
+ */
+ protected function onPreLoad($param)
+ {
+ $this->raiseEvent('PreLoad',$this,$param);
+ }
+
+ /**
+ * Raises LoadComplete event.
+ * This method is invoked right after {@link onLoad Load} stage.
+ * You may override this method to provide additional page loading logic that
+ * should be done after {@link onLoad Load}.
+ * Remember to call the parent implementation to ensure LoadComplete event is raised.
+ * @param mixed event parameter
+ */
+ protected function onLoadComplete($param)
+ {
+ $this->raiseEvent('LoadComplete',$this,$param);
+ }
+
+ /**
+ * Raises PreRenderComplete event.
+ * This method is invoked right after {@link onPreRender PreRender} stage.
+ * You may override this method to provide additional preparation for page rendering
+ * that should be done after {@link onPreRender PreRender}.
+ * Remember to call the parent implementation to ensure PreRenderComplete event is raised.
+ * @param mixed event parameter
+ */
+ protected function onPreRenderComplete($param)
+ {
+ $this->raiseEvent('PreRenderComplete',$this,$param);
+ }
+
+ /**
+ * Raises SaveStateComplete event.
+ * This method is invoked right after {@link onSaveState SaveState} stage.
+ * You may override this method to provide additional logic after page state is saved.
+ * Remember to call the parent implementation to ensure SaveStateComplete event is raised.
+ * @param mixed event parameter
+ */
+ protected function onSaveStateComplete($param)
+ {
+ $this->raiseEvent('SaveStateComplete',$this,$param);
+ }
+
+ /**
+ * Determines whether the current page request is a postback.
+ * Call {@link getIsPostBack} to get the result.
+ */
+ private function determinePostBackMode()
+ {
+ $postData=$this->_application->getRequest()->getItems();
+ if($postData->contains(TClientScriptManager::FIELD_PAGE_STATE) || $postData->contains(TClientScriptManager::FIELD_POSTBACK_TARGET))
+ $this->_postData=$postData;
+ }
+
+ /**
+ * @return boolean whether the current page request is a postback
*/
- final public function applyControlSkin($control)
+ public function getIsPostBack()
{
- if($this->_theme)
- $this->_theme->applySkin($control);
+ return $this->_postData!==null;
}
/**
+ * @return IPageStatePersister page state persister
+ */
+ protected function getPageStatePersister()
+ {
+ return $this->_pageService->getPageStatePersister();
+ }
+
+ /**
+ * Loads page state from persistent storage.
+ */
+ protected function loadPageState()
+ {
+ $state=$this->getPageStatePersister()->load();
+ $this->loadStateRecursive($state,$this->getEnableViewState());
+ }
+
+ /**
+ * Saves page state from persistent storage.
+ */
+ protected function savePageState()
+ {
+ $state=&$this->saveStateRecursive($this->getEnableViewState());
+ $this->getPageStatePersister()->save($state);
+ }
+
+ /**
+ * Loads page state data from a hidden field.
+ * @return string page state data stored in hidden field
+ */
+ public function loadStateField()
+ {
+ return base64_decode($this->_postData->itemAt(TClientScriptManager::FIELD_PAGE_STATE));
+ }
+
+ /**
+ * Saves page state data in a hidden field.
+ * @param string string representation of the page state data.
+ */
+ public function saveStateField($state)
+ {
+ $this->getClientScript()->registerHiddenField(TClientScriptManager::FIELD_PAGE_STATE,base64_encode($state));
+ }
+
+ public function RegisterEnabledControl($control)
+ {
+ $this->getEna.EnabledControls.Add(control);
+ }
+
+
+
+ /**
* @internal
*/
- final public function applyControlStyleSheet($control)
+ public function registerPostBackScript()
{
- if($this->_styleSheet)
+ if($this->getClientSupportsJavaScript() && !$this->_postBackScriptRendered)
{
- $this->_styleSheet->applySkin($control);
- return true;
+ if(!$this->_requirePostBackScript)
+ {
+ $this->getClientScript()->registerHiddenField('__EVENTTARGET','');
+ $this->getClientScript()->registerHiddenField('__EVENTPARAM','');
+ $this->_requirePostBackScript=true;
+ }
}
- else
- return false;
}
- private function renderStateFields($writer)
+ public function registerWebFormsScript()
{
- $writer->write("\n<input type=\"hidden\" name=\"__STATE\" id=\"__STATE\" value=\"".$this->_pageState."\" />\n");
+ if($this->getClientSupportsJavaScript() && !$this->_webFormsScriptRendered)
+ {
+ $this->registerPostBackScript();
+ $this->_requireWebFormsScript=true;
+ }
+ }
+
+
+ public function ensureRenderInForm($control)
+ {
+ if(!$this->_inFormRender)
+ throw new THttpException('control_not_in_form',$control->getUniqueID());
}
private function renderPostBackScript($writer)
@@ -232,7 +512,6 @@ EOD; $this->_inFormRender=true;
$this->getClientScript()->renderHiddenFields($writer);
- //$this->renderStateFields($writer);
if($this->getClientSupportsJavaScript())
{
/*
@@ -280,13 +559,6 @@ EOD; $this->_inFormRender=false;
}
- final public function getClientScript()
- {
- if(!$this->_clientScript)
- $this->_clientScript=new TClientScriptManager($this);
- return $this->_clientScript;
- }
-
final public function getClientOnSubmitEvent()
{
// todo
@@ -296,19 +568,6 @@ EOD; return '';
}
- final public function getValidators($validationGroup='')
- {
- if(!$this->_validators)
- $this->_validators=new TList;
- if($validationGroup==='')
- return $this->_validators;
- $list=new TList;
- foreach($this->_validators as $validator)
- if($validator->getValidationGroup()===$validationGroup)
- $list->add($validator);
- return $list;
- }
-
protected function initializeCulture()
{
}
@@ -316,23 +575,6 @@ EOD; /**
* @internal
*/
- public function initializeStyleSheet()
- {
- if($this->_styleSheet!=='')
- $this->_styleSheet=new TTheme($this->_styleSheetName);
- }
-
- private function initializeThemes()
- {
- if($this->_themeName!=='')
- $this->_theme=$this->getService()->getThemeManager()->getTheme($this->_themeName);
- if($this->_styleSheetName!=='')
- $this->_styleSheet=$this->getService()->getThemeManager()->getTheme($this->_styleSheetName);
- }
-
- /**
- * @internal
- */
public function loadScrollPosition()
{
if($this->_previousPagePath==='' && $this->_requestValueCollection)
@@ -344,44 +586,6 @@ EOD; }
}
- protected function onInit($param)
- {
- parent::onInit($param);/*
- if($this->_theme)
- $this->_theme->setStyleSheet();
- if($this->_styleSheet)
- $this->_styleSheet->setStyleSheet();*/
- }
-
- protected function onInitComplete($param)
- {
- $this->raiseEvent('InitComplete',$this,$param);
- }
-
- protected function onLoadComplete($param)
- {
- $this->raiseEvent('LoadComplete',$this,$param);
- }
-
- protected function onPreInit($param)
- {
- $this->raiseEvent('PreInit',$this,$param);
- }
-
- protected function onPreLoad($param)
- {
- $this->raiseEvent('PreLoad',$this,$param);
- }
-
- protected function onPreRenderComplete($param)
- {
- $this->raiseEvent('PreRenderComplete',$this,$param);
- }
-
- protected function onSaveStateComplete($param)
- {
- $this->raiseEvent('SaveStateComplete',$this,$param);
- }
final public function registerAsyncTask()
{
@@ -404,64 +608,6 @@ EOD; return $this->_application;
}
- public function loadStateField()
- {
- return base64_decode($this->_postData->itemAt('__STATE'));
- }
-
- public function saveStateField($state)
- {
- $this->getClientScript()->registerHiddenField('__STATE',base64_encode($state));
- }
-
- protected function determinePostBackMode()
- {
- /*
- $application=$this->getApplication();
- if($application->getPreventPostBack())
- return null;
- */
- $postData=new TMap($this->_application->getRequest()->getItems());
- if($postData->itemAt('__STATE')!==null || $postData->itemAt('__EVENTTARGET')!==null)
- return $postData;
- else
- return null;
- }
-
- final public function getIsPostBack()
- {
- if($this->_postData)
- {
- if($this->_isCrossPagePostBack)
- return true;
- if($this->_previousPagePath!=='')
- return false;
- return !$this->_pageStateChanged;
- }
- else
- return false;
- }
-
- protected function getPageStatePersister()
- {
- require_once(PRADO_DIR.'/Web/UI/THiddenFieldPageStatePersister.php');
- return new THiddenFieldPageStatePersister($this);
- }
-
- protected function loadPageState()
- {
- $persister=$this->getPageStatePersister();
- $state=$persister->load();
- $this->loadStateRecursive($state,$this->getEnableViewState());
- }
-
- protected function savePageState()
- {
- $state=&$this->saveStateRecursive($this->getEnableViewState());
- $persister=$this->getPageStatePersister();
- $persister->save($state);
- }
-
protected function processPostData($postData,$beforeLoad)
{
$eventTarget=$postData->itemAt('__EVENTTARGET');
@@ -551,11 +697,10 @@ EOD; public function run($writer)
{
- $this->_postData=$this->determinePostBackMode();
+ $this->determinePostBackMode();
$this->_restPostData=new TMap;
$this->onPreInit(null);
- $this->initializeThemes();
$this->_preInitWorkComplete=true;
$this->initRecursive(null);
@@ -587,30 +732,6 @@ EOD; $this->unloadRecursive();
}
- public function getTheme()
- {
- return $this->_themeName;
- }
-
- public function setTheme($value)
- {
- $this->_themeName=$value;
- }
-
- public function getStyleSheetTheme()
- {
- return $this->_styleSheetName;
- }
-
- public function setStyleSheetTheme($value)
- {
- $this->_styleSheetName=$value;
- }
-
- public function getContainsTheme()
- {
- return $this->_theme!==null;
- }
}
?>
\ No newline at end of file diff --git a/framework/Web/UI/WebControls/TButton.php b/framework/Web/UI/WebControls/TButton.php index 4eb8e093..6c423d84 100644 --- a/framework/Web/UI/WebControls/TButton.php +++ b/framework/Web/UI/WebControls/TButton.php @@ -78,7 +78,7 @@ class TButton extends TWebControl implements IPostBackEventHandler $onclick=$this->getOnClientClick();
if($onclick!=='')
$onclick=rtrim($onclick,';').';';
- $onclick.=$page->getClientScript()->getPostBackEventReference($this->getPostBackOptions());
+ $onclick.=$page->getClientScript()->getPostBackEventReference($this,'',$this->getPostBackOptions(),false);
}
else if($this->getEnabled()) // in this case, parent will not render 'disabled'
$writer->addAttribute('disabled','disabled');
diff --git a/framework/Web/UI/WebControls/TCheckBox.php b/framework/Web/UI/WebControls/TCheckBox.php index 756fb2ea..7b9d4702 100644 --- a/framework/Web/UI/WebControls/TCheckBox.php +++ b/framework/Web/UI/WebControls/TCheckBox.php @@ -381,10 +381,10 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl $option->AutoPostBack=true;
if(!empty($onclick))
$onclick=rtrim($onclick,';').';';
- $onclick.=$page->getClientScript()->getPostBackEventReference($option);
+ $onclick.=$page->getClientScript()->getPostBackEventReference($this,'',$option,false);
}
if(!empty($onclick))
- $writer->addAttribute('onclick',$onclick);
+ $writer->addAttribute('onclick','javascript:'.$onclick);
if(($accesskey=$this->getAccessKey())!=='')
$writer->addAttribute('accesskey',$accesskey);
if(($tabindex=$this->getTabIndex())>0)
diff --git a/framework/Web/UI/WebControls/TImageButton.php b/framework/Web/UI/WebControls/TImageButton.php index d715480d..b0fb5a8b 100644 --- a/framework/Web/UI/WebControls/TImageButton.php +++ b/framework/Web/UI/WebControls/TImageButton.php @@ -74,7 +74,7 @@ class TImageButton extends TImage implements IPostBackDataHandler, IPostBackEven $onclick=$this->getOnClientClick();
if($onclick!=='')
$onclick=rtrim($onclick,';').';';
- $onclick.=$page->getClientScript()->getPostBackEventReference($this->getPostBackOptions());
+ $onclick.=$page->getClientScript()->getPostBackEventReference($this,'',$this->getPostBackOptions(),false);
}
else if($this->getEnabled()) // in this case, parent will not render 'disabled'
$writer->addAttribute('disabled','disabled');
diff --git a/framework/core.php b/framework/core.php index 5c3d645c..84077a04 100644 --- a/framework/core.php +++ b/framework/core.php @@ -287,6 +287,30 @@ interface IUser }
/**
+ * IPageStatePersister class.
+ *
+ * This interface must be implemented by all page state persister classes.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $ $Date: $
+ * @package System
+ * @since 3.0
+ */
+interface IPageStatePersister
+{
+ /**
+ * Loads state from a persistent storage.
+ * @return mixed the state
+ */
+ public function load();
+ /**
+ * Saves state into a persistent storage.
+ * @param mixed the state to be saved
+ */
+ public function save($state);
+}
+
+/**
* PradoBase class.
*
* PradoBase implements a few fundamental static methods.
|