diff options
| -rw-r--r-- | .gitattributes | 2 | ||||
| -rw-r--r-- | HISTORY | 3 | ||||
| -rw-r--r-- | UPGRADE | 2 | ||||
| -rw-r--r-- | buildscripts/classtree/build.php | 179 | ||||
| -rw-r--r-- | demos/quickstart/protected/comments/CommentList.tpl | 20 | ||||
| -rw-r--r-- | framework/TApplicationComponent.php | 2 | ||||
| -rw-r--r-- | framework/TComponent.php | 138 | ||||
| -rw-r--r-- | framework/Web/UI/TControl.php | 9 | ||||
| -rw-r--r-- | framework/Web/UI/TPageStatePersister.php | 2 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TDataBoundControl.php | 8 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TDataGrid.php | 11 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TDataList.php | 6 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TFileUpload.php | 3 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TListControl.php | 3 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TMarkdown.php | 90 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TMultiView.php | 2 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TRepeater.php | 6 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TTextHighlighter.php | 61 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TTextProcessor.php | 87 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TWizard.php | 2 | 
20 files changed, 446 insertions, 190 deletions
| diff --git a/.gitattributes b/.gitattributes index a18d9820..79cb8dfd 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,6 +4,7 @@  /UPGRADE -text  /build.xml -text  buildscripts/.htaccess -text +buildscripts/classtree/build.php -text  buildscripts/index/api_index.php -text  buildscripts/index/build.php -text  buildscripts/index/quickstart_index.php -text @@ -1107,6 +1108,7 @@ framework/Web/UI/WebControls/TTableRow.php -text  framework/Web/UI/WebControls/TTemplateColumn.php -text  framework/Web/UI/WebControls/TTextBox.php -text  framework/Web/UI/WebControls/TTextHighlighter.php -text +framework/Web/UI/WebControls/TTextProcessor.php -text  framework/Web/UI/WebControls/TValidationSummary.php -text  framework/Web/UI/WebControls/TWebControl.php -text  framework/Web/UI/WebControls/TWebControlAdapter.php -text @@ -34,8 +34,11 @@ ENH: refactored TUserManager and TAuthManager so that they are easier to be exte  ENH: template syntax now supports setting event handler via subproperties (Qiang)
  CHG: Ticket#151 - URL format is modified to handle empty GET values (Qiang)
  CHG: Ticket#153 - TAssetManager now ignores .svn directories (Qiang)
 +CHG: Changed TControl::onBubbleEvent() to TControl::bubbleEvent() (Qiang)
  NEW: TTableHeaderRow, TTableFooterRow and table section support (Qiang)
  NEW: TCompositeControl (Qiang)
 +NEW: TTextProcessor (Qiang)
 +NEW: TMarkdown (Wei)
  NEW: Blog demo (Qiang)
  Version 3.0.0 May 1, 2006
 @@ -23,6 +23,8 @@ Upgrading from v3.0.0    /index.php/ServiceID,ServiceParam/Name1,Value1/Name2,Value2/...
    In v3.0.0, the above URL is written as:
    /index.php/ServiceID/ServiceParam/Name1/Value1/Name2/Value2/...
 +- TControl::onBubbleEvent() has been changed to TControl::bubbleEvent().
 +  This change only affects user controls that override this method.
  Upgrading from v3.0.0 RC2
  -------------------------
 diff --git a/buildscripts/classtree/build.php b/buildscripts/classtree/build.php new file mode 100644 index 00000000..ffb4eef3 --- /dev/null +++ b/buildscripts/classtree/build.php @@ -0,0 +1,179 @@ +<?php
 +
 +$rootPath=dirname(__FILE__).'/../../framework';
 +require_once($rootPath.'/prado.php');
 +$exclusions=array(
 +	'prado.php',
 +	'pradolite.php',
 +	'PradoBase.php',
 +	'clientscripts.php',
 +	'.svn',
 +	'/I18N/core',
 +	'/3rdParty',
 +	);
 +$a=new ClassTreeBuilder($rootPath,$exclusions);
 +$a->buildTree();
 +$a->saveToFile('classtree.data');
 +
 +class ClassTreeBuilder
 +{
 +	const REGEX_RULES='/^\s*(abstract\s+)?class\s+(\w+)(\s+extends\s+(\w+)\s*|\s*)/msS';
 +	private $_basePath;
 +	private $_exclusions;
 +	private $_classes=array();
 +
 +	public function __construct($basePath,$exclusions)
 +	{
 +		$this->_basePath=realpath($basePath);
 +		$this->_exclusions=array();
 +		foreach($exclusions as $exclusion)
 +		{
 +			if($exclusion[0]==='/')
 +				$this->_exclusions[realpath($basePath.'/'.$exclusion)]=true;
 +			else
 +				$this->_exclusions[$exclusion]=true;
 +		}
 +	}
 +
 +	public function buildTree()
 +	{
 +		$sourceFiles=$this->getSourceFiles($this->_basePath);
 +		foreach($sourceFiles as $sourceFile)
 +			$this->parseFile($sourceFile);
 +		ksort($this->_classes);
 +		foreach(array_keys($this->_classes) as $className)
 +		{
 +			$parentClass=$this->_classes[$className]['ParentClass'];
 +			if(isset($this->_classes[$parentClass]))
 +				$this->_classes[$parentClass]['ChildClasses'][]=$className;
 +		}
 +		echo "\nClass tree built successfully. Total ".count($this->_classes)." classes found.\n";
 +	}
 +
 +	public function saveToFile($fileName)
 +	{
 +		file_put_contents($fileName,serialize($this->_classes));
 +	}
 +
 +	public function displayTree()
 +	{
 +		$this->displayTreeInternal(array_keys($this->_baseClasses),0);
 +	}
 +
 +	public function displayTreeInternal($classNames,$level)
 +	{
 +		foreach($classNames as $className)
 +		{
 +			echo str_repeat(' ',$level*4);
 +			echo $className.':'.$this->_classes[$className]->Package."\n";
 +			$this->displayTreeInternal(array_keys($this->_classes[$className]->ChildClasses),$level+1);
 +		}
 +	}
 +
 +	protected function parseFile($sourceFile)
 +	{
 +		include_once($sourceFile);
 +		$classFile=strtr(substr($sourceFile,strlen($this->_basePath)),'\\','/');
 +		echo "Parsing $classFile...\n";
 +		$content=file_get_contents($sourceFile);
 +		if(preg_match('/@package\s+([\w\.]+)\s*/msS',$content,$matches)>0)
 +			$package=$matches[1];
 +		else
 +			$package='';
 +		$n=preg_match_all(self::REGEX_RULES,$content,$matches,PREG_SET_ORDER);
 +		for($i=0;$i<$n;++$i)
 +		{
 +			$className=$matches[$i][2];
 +			if(isset($this->_classes[$className]))
 +				throw new Exception("Class $className is defined in both $sourceFile and ".$this->_classes[$className]->ClassFile);
 +			$c=new TComponentReflection($className);
 +			$properties=$c->getProperties();
 +			$this->parseMethodComments($properties);
 +			$events=$c->getEvents();
 +			$this->parseMethodComments($events);
 +			$methods=$c->getMethods();
 +			$this->parseMethodComments($methods);
 +			$this->_classes[$className]=array(
 +				'ClassFile'=>$classFile,
 +				'Package'=>$package,
 +				'ParentClass'=>isset($matches[$i][4])?$matches[$i][4]:'',
 +				'ChildClasses'=>array(),
 +				'Properties'=>$properties,
 +				'Events'=>$events,
 +				'Methods'=>$methods);
 +		}
 +	}
 +
 +	protected function parseMethodComments(&$methods)
 +	{
 +		foreach(array_keys($methods) as $key)
 +		{
 +			$method=&$methods[$key];
 +			$comments=$method['comments'];
 +			$s='';
 +			foreach(explode("\n",$comments) as $line)
 +			{
 +				$line=trim($line);
 +				$line=trim($line,'/*');
 +				$s.=' '.$line;
 +			}
 +			$s=trim($s);
 +			$s=preg_replace('/\{@link.*?([\w\(\)]+)\}/i','$1',$s);
 +			$pos1=strpos($s,'@');
 +			$pos2=strpos($s,'.');
 +			if($pos1===false)
 +			{
 +				if($pos2!==false)
 +					$method['comments']=substr($s,0,$pos2);
 +				else
 +					$method['comments']=$s;
 +			}
 +			else if($pos1>0)
 +			{
 +				if($pos2 && $pos2<$pos1)	// use the first line as comment
 +					$method['comments']=substr($s,0,$pos2);
 +				else
 +					$method['comments']=substr($s,0,$pos1);
 +			}
 +			else
 +			{
 +				$matches=array();
 +				if(preg_match('/@return\s+[\w\|]+\s+([^\.]*)/',$s,$matches)>0)
 +					$method['comments']=$matches[1];
 +				else
 +					$method['comments']='';
 +			}
 +		}
 +	}
 +
 +	protected function isValidPath($path)
 +	{
 +		if(is_dir($path))
 +			return !isset($this->_exclusions[basename($path)]) && !isset($this->_exclusions[$path]);
 +		else
 +			return basename($path)!==basename($path,'.php') && !isset($this->_exclusions[basename($path)]);
 +	}
 +
 +	public function getSourceFiles($path)
 +	{
 +		$files=array();
 +		$folder=opendir($path);
 +		while($file=readdir($folder))
 +		{
 +			if($file==='.' || $file==='..')
 +				continue;
 +			$fullPath=realpath($path.'/'.$file);
 +			if($this->isValidPath($fullPath))
 +			{
 +				if(is_file($fullPath))
 +					$files[]=$fullPath;
 +				else
 +					$files=array_merge($files,$this->getSourceFiles($fullPath));
 +			}
 +		}
 +		closedir($folder);
 +		return $files;
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/demos/quickstart/protected/comments/CommentList.tpl b/demos/quickstart/protected/comments/CommentList.tpl index 0aeb2c81..ef74316a 100644 --- a/demos/quickstart/protected/comments/CommentList.tpl +++ b/demos/quickstart/protected/comments/CommentList.tpl @@ -2,7 +2,7 @@  <com:TRepeater ID="comments">  	<prop:HeaderTemplate> -		<h2 class="comment_header">Comments  +		<h2 class="comment_header">Comments  			<span style="font-size:0.8em">( <a href="#add_comments">Add your comments</a> )</span></h2>  	</prop:HeaderTemplate>  	<prop:ItemTemplate> @@ -16,7 +16,7 @@  			</span>  			<div class="comment">  				<com:TSafeHtml> -				<com:TMarkdown TextHighlighter.CssClass="source"> +				<com:TMarkdown CssClass="source">  					<%# $this->DataItem['comment'] %>  				</com:TMarkdown>  				</com:TSafeHtml> @@ -29,13 +29,13 @@  	<com:TView ID="view1">  		<div id="add_comments" class="add_comments">  			<h3>Post a comment</h3> -			<p><strong>Note:</strong>  +			<p><strong>Note:</strong>  				Please only use the comments in relation to this page for -				<ul>  +				<ul>  					<li>questions/critcisms/suggestions on the documentation,</li>  					<li>small notes that can solve or clarify a particular problem or task.</li>  				</ul> -				If you experience errors please <a href="http://trac.pradosoft.com/newticket">file a ticket</a>  +				If you experience errors please <a href="http://trac.pradosoft.com/newticket">file a ticket</a>  				or <a href="http://www.pradosoft.com/forum/">ask at the forum</a>.  				Please use the <a href="http://pradosoft.com/wiki/index.php/Main_Page">Prado wiki</a> for longer pieces and detailed solutions</a>.  			</p> @@ -49,8 +49,8 @@  				ControlToValidate="email"  				Display="Dynamic"  				ErrorMessage="An email address is required." /> -			<com:TEmailAddressValidator	 -				ControlToValidate="email"  +			<com:TEmailAddressValidator +				ControlToValidate="email"  				CheckMXRecord="false"  				Display="Dynamic"  				ErrorMessage="Please provide your email address."/> @@ -70,13 +70,13 @@  				<h3 style="margin:0">Preview comment</h3>  					<div class="comment">  						<com:TSafeHtml> -							<com:TMarkdown TextHighlighter.CssClass="source"> +							<com:TMarkdown CssClass="source">  							<%= $this->content->Text %>  							</com:TMarkdown>  						</com:TSafeHtml>  					</div>  				</div> -			</com:TPlaceHolder>			 +			</com:TPlaceHolder>  			<div class="add_comment">  				<com:TButton ID="previewComment" Text="Preview Comment" />  				<com:TButton ID="addComment" Text="Add Comment" OnClick="addComment_Clicked"/> @@ -90,7 +90,7 @@  			<h3 style="margin:0">Preview comment</h3>  			<div class="comment">  			<com:TSafeHtml> -				<com:TMarkdown TextHighlighter.CssClass="source"> +				<com:TMarkdown CssClass="source">  				<%= $this->content->Text %>  				</com:TMarkdown>  			</com:TSafeHtml> diff --git a/framework/TApplicationComponent.php b/framework/TApplicationComponent.php index 580f1d33..bd4f0db0 100644 --- a/framework/TApplicationComponent.php +++ b/framework/TApplicationComponent.php @@ -75,7 +75,7 @@ class TApplicationComponent extends TComponent  	}
  	/**
 -	 * @return IUser user
 +	 * @return IUser information about the current user
  	 */
  	public function getUser()
  	{
 diff --git a/framework/TComponent.php b/framework/TComponent.php index 5501f137..7564edff 100644 --- a/framework/TComponent.php +++ b/framework/TComponent.php @@ -582,12 +582,8 @@ class TEventParameter extends TComponent  /**
   * TComponentReflection class.
   *
 - * TComponentReflection provides functionalities to inspect the properties and events
 - * defined in a component. It shows the definition of component properties, including
 - * their name, type, writability and defining class. It also shows the definition
 - * of component events, including their name and defining class.
 - *
 - * Note, only public properties and events are displayed.
 + * TComponentReflection provides functionalities to inspect the public/protected
 + * properties, events and methods defined in a class.
   *
   * The following code displays the properties and events defined in {@link TDataGrid},
   * <code>
 @@ -606,72 +602,99 @@ class TComponentReflection extends TComponent  	private $_className;
  	private $_properties=array();
  	private $_events=array();
 +	private $_methods=array();
  	/**
  	 * Constructor.
 -	 * @param TComponent|string the component instance or the class name
 +	 * @param object|string the component instance or the class name
  	 * @throws TInvalidDataTypeException if the object is not a component
  	 */
  	public function __construct($component)
  	{
 -		if(is_string($component))
 +		if(is_string($component) && class_exists($component,false))
  			$this->_className=$component;
 -		else if($component instanceof TComponent)
 +		else if(is_object($component))
  			$this->_className=get_class($component);
  		else
  			throw new TInvalidDataTypeException('componentreflection_class_invalid');
  		$this->reflect();
  	}
 +	private function isPropertyMethod($method)
 +	{
 +		$methodName=$method->getName();
 +		return $method->getNumberOfRequiredParameters()===0
 +				&& strncasecmp($methodName,'get',3)===0
 +				&& isset($methodName[3]);
 +	}
 +
 +	private function isEventMethod($method)
 +	{
 +		$methodName=$method->getName();
 +		return strncasecmp($methodName,'on',2)===0
 +				&& isset($methodName[2]);
 +	}
 +
  	private function reflect()
  	{
  		$class=new TReflectionClass($this->_className);
 -		$methods=$class->getMethods();
  		$properties=array();
  		$events=array();
 -		foreach($methods as $method)
 +		$methods=array();
 +		$isComponent=is_subclass_of($this->_className,'TComponent') || strcasecmp($this->_className,'TComponent')===0;
 +		foreach($class->getMethods() as $method)
  		{
 -			if($method->isPublic() && !$method->isStatic())
 +			if($method->isPublic() || $method->isProtected())
  			{
  				$methodName=$method->getName();
 -				if($method->getNumberOfRequiredParameters()===0 && strncasecmp($methodName,'get',3)===0 && isset($methodName[3]))
 -				{
 -					$propertyName=substr($methodName,3);
 -					$readOnly=!$class->hasMethod('set'.$propertyName);
 -					$methodClass=$method->getDeclaringClass()->getName();
 -					$properties[$methodClass][$propertyName]=$method;
 -				}
 -				else if(strncasecmp($methodName,'on',2)===0 && isset($methodName[2]))
 +				if(!$method->isStatic() && $isComponent)
  				{
 -					$methodName[0]='O';
 -					$methodClass=$method->getDeclaringClass()->getName();
 -					$events[$methodClass][$methodName]=$method;
 +					if($this->isPropertyMethod($method))
 +						$properties[substr($methodName,3)]=$method;
 +					else if($this->isEventMethod($method))
 +					{
 +						$methodName[0]='O';
 +						$events[$methodName]=$method;
 +					}
  				}
 +				if(strncmp($methodName,'__',2)!==0)
 +					$methods[$methodName]=$method;
  			}
  		}
 -		foreach($properties as $className=>$props)
 +		$reserved=array();
 +		ksort($properties);
 +		foreach($properties as $name=>$method)
  		{
 -			ksort($props);
 -			foreach($props as $name=>$method)
 -			{
 -				$this->_properties[]=array(
 -					'name'=>$name,
 -					'type'=>$this->determinePropertyType($method),
 -					'readonly'=>!$class->hasMethod('set'.$name),
 -					'class'=>$className,
 -				);
 -			}
 +			$this->_properties[$name]=array(
 +				'type'=>$this->determinePropertyType($method),
 +				'readonly'=>!$class->hasMethod('set'.$name),
 +				'protected'=>$method->isProtected(),
 +				'class'=>$method->getDeclaringClass()->getName(),
 +				'comments'=>$method->getDocComment()
 +			);
 +			$reserved['get'.strtolower($name)]=1;
 +			$reserved['set'.strtolower($name)]=1;
  		}
 -		foreach($events as $className=>$evts)
 +		ksort($events);
 +		foreach($events as $name=>$method)
  		{
 -			ksort($evts);
 -			foreach($evts as $name=>$method)
 -			{
 -				$this->_events[]=array(
 -					'name'=>$name,
 -					'class'=>$className,
 +			$this->_events[$name]=array(
 +				'class'=>$method->getDeclaringClass()->getName(),
 +				'protected'=>$method->isProtected(),
 +				'comments'=>$method->getDocComment()
 +			);
 +			$reserved[strtolower($name)]=1;
 +		}
 +		ksort($methods);
 +		foreach($methods as $name=>$method)
 +		{
 +			if(!isset($reserved[strtolower($name)]))
 +				$this->_methods[$name]=array(
 +					'class'=>$method->getDeclaringClass()->getName(),
 +					'protected'=>$method->isProtected(),
 +					'static'=>$method->isStatic(),
 +					'comments'=>$method->getDocComment()
  				);
 -			}
  		}
  	}
 @@ -699,10 +722,13 @@ class TComponentReflection extends TComponent  	}
  	/**
 -	 * @return array list of component properties. Each array element is of the following
 -	 * structure: [name]=>property name, [type]=>property type,
 -	 * [readonly]=>whether the property is read-only, [class]=>the class where the
 -	 * property is inherited from
 +	 * @return array list of component properties. Array keys are property names.
 +	 * Each array element is of the following structure:
 +	 * [type]=>property type,
 +	 * [readonly]=>whether the property is read-only,
 +	 * [protected]=>whether the method is protected or not
 +	 * [class]=>the class where the property is inherited from,
 +	 * [comments]=>comments	associated with the property.
  	 */
  	public function getProperties()
  	{
 @@ -710,13 +736,29 @@ class TComponentReflection extends TComponent  	}
  	/**
 -	 * @return array list of component events. Each array element is of the following
 -	 * structure: [name]=>event name,[class]=>the class where the event is inherited from
 +	 * @return array list of component events. Array keys are event names.
 +	 * Each array element is of the following structure:
 +	 * [protected]=>whether the event is protected or not
 +	 * [class]=>the class where the event is inherited from.
 +	 * [comments]=>comments associated with the event.
  	 */
  	public function getEvents()
  	{
  		return $this->_events;
  	}
 +
 +	/**
 +	 * @return array list of public/protected methods. Array keys are method names.
 +	 * Each array element is of the following structure:
 +	 * [protected]=>whether the method is protected or not
 +	 * [static]=>whether the method is static or not
 +	 * [class]=>the class where the property is inherited from,
 +	 * [comments]=>comments associated with the event.
 +	 */
 +	public function getMethods()
 +	{
 +		return $this->_methods;
 +	}
  }
  ?>
\ No newline at end of file diff --git a/framework/Web/UI/TControl.php b/framework/Web/UI/TControl.php index 10541a37..eced51ea 100644 --- a/framework/Web/UI/TControl.php +++ b/framework/Web/UI/TControl.php @@ -591,6 +591,7 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable  	}
  	/**
 +	 * Sets a custom control attribute.
  	 * @param string attribute name
  	 * @param string value of the attribute
  	 */
 @@ -1336,18 +1337,18 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable  	}
  	/**
 -	 * Invokes the parent's onBubbleEvent method.
 +	 * Invokes the parent's bubbleEvent method.
  	 * A control who wants to bubble an event must call this method in its onEvent method.
  	 * @param TControl sender of the event
  	 * @param TEventParameter event parameter
 -	 * @see onBubbleEvent
 +	 * @see bubbleEvent
  	 */
  	protected function raiseBubbleEvent($sender,$param)
  	{
  		$control=$this;
  		while($control=$control->_parent)
  		{
 -			if($control->onBubbleEvent($sender,$param))
 +			if($control->bubbleEvent($sender,$param))
  				break;
  		}
  	}
 @@ -1361,7 +1362,7 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable  	 * @return boolean true if the event bubbling is handled and no more bubbling.
  	 * @see raiseBubbleEvent
  	 */
 -	public function onBubbleEvent($sender,$param)
 +	public function bubbleEvent($sender,$param)
  	{
  		return false;
  	}
 diff --git a/framework/Web/UI/TPageStatePersister.php b/framework/Web/UI/TPageStatePersister.php index ff5b088b..af470a26 100644 --- a/framework/Web/UI/TPageStatePersister.php +++ b/framework/Web/UI/TPageStatePersister.php @@ -31,7 +31,7 @@ class TPageStatePersister extends TComponent implements IPageStatePersister  	private $_page;
  	/**
 -	 * @param TPage the page that this persister works for
 +	 * @return TPage the page that this persister works for
  	 */
  	public function getPage()
  	{
 diff --git a/framework/Web/UI/WebControls/TDataBoundControl.php b/framework/Web/UI/WebControls/TDataBoundControl.php index 9e6ecbf3..09023b66 100644 --- a/framework/Web/UI/WebControls/TDataBoundControl.php +++ b/framework/Web/UI/WebControls/TDataBoundControl.php @@ -128,7 +128,7 @@ abstract class TDataBoundControl extends TWebControl  	}
  	/**
 -	 * @return boolean if databind has been invoked in the previous page request
 +	 * @return boolean whether databind has been invoked in the previous page request
  	 */
  	protected function getIsDataBound()
  	{
 @@ -272,7 +272,7 @@ abstract class TDataBoundControl extends TWebControl  	}
  	/**
 -	 * Sets page's <b>OnPreLoad</b> event handler as {@link onPagePreLoad}.
 +	 * Sets page's <b>OnPreLoad</b> event handler as {@link pagePreLoad}.
  	 * If viewstate is disabled and the current request is a postback,
  	 * {@link setRequiresDataBinding RequiresDataBinding} will be set true.
  	 * This method overrides the parent implementation.
 @@ -282,7 +282,7 @@ abstract class TDataBoundControl extends TWebControl  	{
  		parent::onInit($param);
  		$page=$this->getPage();
 -		$page->attachEventHandler('OnPreLoad',array($this,'onPagePreLoad'));
 +		$page->attachEventHandler('OnPreLoad',array($this,'pagePreLoad'));
  	}
  	/**
 @@ -291,7 +291,7 @@ abstract class TDataBoundControl extends TWebControl  	 * @param mixed event sender
  	 * @param TEventParameter event parameter
  	 */
 -	public function onPagePreLoad($sender,$param)
 +	public function pagePreLoad($sender,$param)
  	{
  		$this->_initialized=true;
  		$isPostBack=$this->getPage()->getIsPostBack();
 diff --git a/framework/Web/UI/WebControls/TDataGrid.php b/framework/Web/UI/WebControls/TDataGrid.php index 82c243ca..d2625c0d 100644 --- a/framework/Web/UI/WebControls/TDataGrid.php +++ b/framework/Web/UI/WebControls/TDataGrid.php @@ -217,7 +217,7 @@ class TDataGrid extends TBaseDataList implements INamingContainer  	}
  	/**
 -	 * @return TDataGridColumnCollection automatically specified datagrid columns
 +	 * @return TDataGridColumnCollection automatically generated datagrid columns
  	 */
  	public function getAutoColumns()
  	{
 @@ -683,7 +683,6 @@ class TDataGrid extends TBaseDataList implements INamingContainer  	}
  	/**
 -	 * Handles <b>OnBubbleEvent</b>.
  	 * This method overrides parent's implementation to handle
  	 * {@link onItemCommand OnItemCommand} event which is bubbled from
  	 * {@link TDataGridItem} child controls.
 @@ -696,7 +695,7 @@ class TDataGrid extends TBaseDataList implements INamingContainer  	 * @param TEventParameter event parameter
  	 * @return boolean whether the event bubbling should stop here.
  	 */
 -	public function onBubbleEvent($sender,$param)
 +	public function bubbleEvent($sender,$param)
  	{
  		if($param instanceof TDataGridCommandEventParameter)
  		{
 @@ -1890,14 +1889,13 @@ class TDataGridItem extends TTableRow implements INamingContainer  	}
  	/**
 -	 * Handles <b>BubbleEvent</b>.
  	 * This method overrides parent's implementation by wrapping event parameter
  	 * for <b>OnCommand</b> event with item information.
  	 * @param TControl the sender of the event
  	 * @param TEventParameter event parameter
  	 * @return boolean whether the event bubbling should stop here.
  	 */
 -	public function onBubbleEvent($sender,$param)
 +	public function bubbleEvent($sender,$param)
  	{
  		if($param instanceof TCommandEventParameter)
  		{
 @@ -1934,14 +1932,13 @@ class TDataGridPager extends TPanel implements INamingContainer  	}
  	/**
 -	 * Handles <b>BubbleEvent</b>.
  	 * This method overrides parent's implementation by wrapping event parameter
  	 * for <b>OnCommand</b> event with item information.
  	 * @param TControl the sender of the event
  	 * @param TEventParameter event parameter
  	 * @return boolean whether the event bubbling should stop here.
  	 */
 -	public function onBubbleEvent($sender,$param)
 +	public function bubbleEvent($sender,$param)
  	{
  		if($param instanceof TCommandEventParameter)
  		{
 diff --git a/framework/Web/UI/WebControls/TDataList.php b/framework/Web/UI/WebControls/TDataList.php index 695d072a..0bec8921 100644 --- a/framework/Web/UI/WebControls/TDataList.php +++ b/framework/Web/UI/WebControls/TDataList.php @@ -635,7 +635,6 @@ class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUs  	}
  	/**
 -	 * Handles <b>BubbleEvent</b>.
  	 * This method overrides parent's implementation to handle
  	 * {@link onItemCommand OnItemCommand} event which is bubbled from
  	 * {@link TDataListItem} child controls.
 @@ -648,7 +647,7 @@ class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUs  	 * @param TEventParameter event parameter
  	 * @return boolean whether the event bubbling should stop here.
  	 */
 -	public function onBubbleEvent($sender,$param)
 +	public function bubbleEvent($sender,$param)
  	{
  		if($param instanceof TDataListCommandEventParameter)
  		{
 @@ -1356,14 +1355,13 @@ class TDataListItem extends TWebControl implements INamingContainer  	}
  	/**
 -	 * Handles <b>BubbleEvent</b>.
  	 * This method overrides parent's implementation by wrapping event parameter
  	 * for <b>Command</b> event with item information.
  	 * @param TControl the sender of the event
  	 * @param TEventParameter event parameter
  	 * @return boolean whether the event bubbling should stop here.
  	 */
 -	public function onBubbleEvent($sender,$param)
 +	public function bubbleEvent($sender,$param)
  	{
  		if($param instanceof TCommandEventParameter)
  		{
 diff --git a/framework/Web/UI/WebControls/TFileUpload.php b/framework/Web/UI/WebControls/TFileUpload.php index 41ffaa7f..37689746 100644 --- a/framework/Web/UI/WebControls/TFileUpload.php +++ b/framework/Web/UI/WebControls/TFileUpload.php @@ -152,7 +152,8 @@ class TFileUpload extends TWebControl implements IPostBackDataHandler, IValidata  	}
  	/**
 -	 * @return integer an error code describing the status of this file uploading
 +	 * Returns an error code describing the status of this file uploading.
 +	 * @return integer the error code
  	 * @see http://www.php.net/manual/en/features.file-upload.errors.php
  	 */
  	public function getErrorCode()
 diff --git a/framework/Web/UI/WebControls/TListControl.php b/framework/Web/UI/WebControls/TListControl.php index 42f09aad..f20ff4cc 100644 --- a/framework/Web/UI/WebControls/TListControl.php +++ b/framework/Web/UI/WebControls/TListControl.php @@ -203,7 +203,7 @@ abstract class TListControl extends TDataBoundControl  		{
  			$index=$items->findIndexByValue($this->_cachedSelectedValue);
  			if($index===-1 || ($this->_cachedSelectedIndex!==-1 && $this->_cachedSelectedIndex!==$index))
 -				throw new TInvalidDataValueException('listcontrol_selection_invalid');
 +				throw new TInvalidDataValueException('listcontrol_selection_invalid',get_class($this));
  			$this->setSelectedIndex($index);
  			$this->_cachedSelectedValue=null;
  			$this->_cachedSelectedIndex=-1;
 @@ -594,6 +594,7 @@ abstract class TListControl extends TDataBoundControl  	public function onSelectedIndexChanged($param)
  	{
  		$this->raiseEvent('OnSelectedIndexChanged',$this,$param);
 +		$this->onTextChanged($param);
  	}
  	/**
 diff --git a/framework/Web/UI/WebControls/TMarkdown.php b/framework/Web/UI/WebControls/TMarkdown.php index 49660b4e..740653a5 100644 --- a/framework/Web/UI/WebControls/TMarkdown.php +++ b/framework/Web/UI/WebControls/TMarkdown.php @@ -11,12 +11,18 @@   */
  /**
 + * Using TTextHighlighter and MarkdownParser classes
 + */
 +Prado::using('System.Web.UI.WebControls.TTextHighlighter');
 +Prado::using('System.3rdParty.Markdown.MarkdownParser');
 +
 +/**
   * TMarkdown class
   *
   * TMarkdown is a control that produces HTML from code with markdown syntax.
   *
 - * Markdown is a text-to-HTML conversion tool for web writers. Markdown allows 
 - * you to write using an easy-to-read, easy-to-write plain text format, then 
 + * Markdown is a text-to-HTML conversion tool for web writers. Markdown allows
 + * you to write using an easy-to-read, easy-to-write plain text format, then
   * convert it to structurally valid XHTML (or HTML).
   * Further documentation regarding Markdown can be found at
   * http://daringfireball.net/projects/markdown/
 @@ -27,86 +33,48 @@   * See http://www.pradosoft.com/demos/quickstart/?page=Markdown for
   * details on the Markdown syntax usage.
   *
 + * TMarkdown also performs syntax highlighting for code blocks whose language
 + * is recognized by {@link TTextHighlighter}.
 + * The language of a code block must be specified in the first line of the block
 + * and enclosed within a pair of square brackets (e.g. [php]).
 + *
   * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
   * @version $Revision: $  $Date: $
   * @package System.Web.UI.WebControls
 - * @since 3.0
 + * @since 3.0.1
   */
 -class TMarkdown extends TControl
 +class TMarkdown extends TTextHighlighter
  {
  	/**
 -	 * @var TTextHighlighter
 +	 * Processes a text string.
 +	 * This method is required by the parent class.
 +	 * @param string text string to be processed
 +	 * @return string the processed text result
  	 */
 -	private $_highlighter;
 -
 -	/**
 -	 * Renders body content.
 -	 * This method overrides parent implementation by removing
 -	 * malicious javascript code from the body content
 -	 * @param THtmlWriter writer
 -	 */
 -	public function render($writer)
 +	public function processText($text)
  	{
 -		$textWriter=new TTextWriter;
 -		parent::render(new THtmlWriter($textWriter));
 -		$writer->write($this->renderMarkdown($textWriter->flush()));
 -	}
 -
 -	/**
 -	 * Use MarkdownParser to render the HTML content.
 -	 * @param string markdown content
 -	 * @return string HTML content
 -	 */
 -	protected function renderMarkdown($text)
 -	{
 -		$renderer = Prado::createComponent('System.3rdParty.Markdown.MarkdownParser');
 +		$renderer = new MarkdownParser;
  		$result = $renderer->parse($text);
  		return preg_replace_callback(
 -				'/<pre><code>\[\s*(\w+)\s*\]\n+((.|\n)*?)\s*<\\/code><\\/pre>/im', 
 +				'/<pre><code>\[\s*(\w+)\s*\]\n+((.|\n)*?)\s*<\\/code><\\/pre>/im',
  				array($this, 'highlightCode'), $result);
  	}
  	/**
 -	 * @return TTextHighlighter source code highlighter
 -	 */
 -	public function getTextHighlighter()
 -	{
 -		if(is_null($this->_highlighter))
 -			$this->_highlighter = new TTextHighlighter;
 -		return $this->_highlighter;
 -	}
 -
 -	
 -	/**
  	 * Highlights source code using TTextHighlighter
  	 * @param array matches of code blocks
  	 * @return string highlighted code.
  	 */
  	protected function highlightCode($matches)
  	{
 -		$text = new TTextWriter;
 -		$writer = new THtmlWriter($text);
 -		$hi = $this->getTextHighlighter();
 -		if($hi->getControls()->getCount() > 0)
 -			$hi->getControls()->removeAt(0);
 -		$hi->addParsedObject(html_entity_decode($matches[2]));
 -		$hi->setLanguage($matches[1]);
 -		$hi->render($writer);
 -		return $text->flush();
 -	}
 +		$geshi=new GeSHi(html_entity_decode($matches[2],ENT_QUOTES,'UTF-8'), $matches[1]);
 +		if($this->getShowLineNumbers())
 +			$geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
 +		$geshi->enable_classes();
 +		if($this->getEnableCopyCode())
 +			$geshi->set_header_content($this->getHeaderTemplate());
 -	/**
 -	 * Registers css style for the highlighted result.
 -	 * This method overrides parent implementation.
 -	 * @param THtmlWriter writer
 -	 */
 -	public function onPreRender($writer)
 -	{
 -		parent::onPreRender($writer);
 -		$hi = $this->getTextHighlighter();
 -		$this->getControls()->insertAt(0,$hi);
 -		$hi->onPreRender($writer);
 -		$this->getControls()->removeAt(0);
 +		return $geshi->parse_code();
  	}
  }
 diff --git a/framework/Web/UI/WebControls/TMultiView.php b/framework/Web/UI/WebControls/TMultiView.php index 59b9f53d..b6001f90 100644 --- a/framework/Web/UI/WebControls/TMultiView.php +++ b/framework/Web/UI/WebControls/TMultiView.php @@ -213,7 +213,7 @@ class TMultiView extends TControl  	 * @param mixed event parameter
  	 * @return boolean whether this event is handled
  	 */
 -	public function onBubbleEvent($sender,$param)
 +	public function bubbleEvent($sender,$param)
  	{
  		if(!$this->_ignoreBubbleEvents && ($param instanceof TCommandEventParameter))
  		{
 diff --git a/framework/Web/UI/WebControls/TRepeater.php b/framework/Web/UI/WebControls/TRepeater.php index 9aa7af8d..2070cb1a 100644 --- a/framework/Web/UI/WebControls/TRepeater.php +++ b/framework/Web/UI/WebControls/TRepeater.php @@ -463,7 +463,6 @@ class TRepeater extends TDataBoundControl implements INamingContainer  	}
  	/**
 -	 * Handles <b>BubbleEvent</b>.
  	 * This method overrides parent's implementation to handle
  	 * {@link onItemCommand OnItemCommand} event which is bubbled from
  	 * {@link TRepeaterItem} child controls.
 @@ -472,7 +471,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer  	 * @param TEventParameter event parameter
  	 * @return boolean whether the event bubbling should stop here.
  	 */
 -	public function onBubbleEvent($sender,$param)
 +	public function bubbleEvent($sender,$param)
  	{
  		if($param instanceof TRepeaterCommandEventParameter)
  		{
 @@ -717,14 +716,13 @@ class TRepeaterItem extends TControl implements INamingContainer  	}
  	/**
 -	 * Handles <b>BubbleEvent</b>.
  	 * This method overrides parent's implementation by wrapping event parameter
  	 * for <b>Command</b> event with item information.
  	 * @param TControl the sender of the event
  	 * @param TEventParameter event parameter
  	 * @return boolean whether the event bubbling should stop here.
  	 */
 -	public function onBubbleEvent($sender,$param)
 +	public function bubbleEvent($sender,$param)
  	{
  		if($param instanceof TCommandEventParameter)
  		{
 diff --git a/framework/Web/UI/WebControls/TTextHighlighter.php b/framework/Web/UI/WebControls/TTextHighlighter.php index f5c3eca9..a9ccf5bb 100644 --- a/framework/Web/UI/WebControls/TTextHighlighter.php +++ b/framework/Web/UI/WebControls/TTextHighlighter.php @@ -11,9 +11,10 @@   */
  /**
 - * Using GeSHi and TTextWriter classes
 + * Using GeSHi and TTextProcessor classes
   */
  Prado::using('System.3rdParty.geshi.geshi');
 +Prado::using('System.Web.UI.WebControls.TTextProcessor');
  /**
   * TTextHighlighter class.
 @@ -31,7 +32,7 @@ Prado::using('System.3rdParty.geshi.geshi');   * @package System.Web.UI.WebControls
   * @since 3.0
   */
 -class TTextHighlighter extends TWebControl
 +class TTextHighlighter extends TTextProcessor
  {
  	/**
  	 * @return string tag name of the panel
 @@ -77,39 +78,30 @@ class TTextHighlighter extends TWebControl  	}
  	/**
 -	 * Registers css style for the highlighted result.
 -	 * This method overrides parent implementation.
 -	 * @param THtmlWriter writer
 +	 * @return boolean true will show "Copy Code" link. Defaults to false.
  	 */
 -	public function onPreRender($writer)
 +	public function getEnableCopyCode()
  	{
 -		parent::onPreRender($writer);
 -		$this->registerHighlightScripts();
 +		return $this->getViewState('CopyCode', false);
  	}
  	/**
 -	 * HTML-decodes static text.
 -	 * This method overrides parent implementation.
 -	 * @param mixed object to be added as body content
 +	 * @param boolean true to show the "Copy Code" link.
  	 */
 -	public function addParsedObject($object)
 +	public function setEnableCopyCode($value)
  	{
 -		if(is_string($object))
 -			$object=html_entity_decode($object);
 -		parent::addParsedObject($object);
 +		$this->setViewState('CopyCode', TPropertyValue::ensureBoolean($value), false);
  	}
  	/**
 -	 * Renders body content.
 -	 * This method overrides parent implementation by replacing
 -	 * the body content with syntax highlighted result.
 +	 * Registers css style for the highlighted result.
 +	 * This method overrides parent implementation.
  	 * @param THtmlWriter writer
  	 */
 -	public function renderContents($writer)
 +	public function onPreRender($writer)
  	{
 -		$textWriter=new TTextWriter;
 -		parent::renderContents(new THtmlWriter($textWriter));
 -		$writer->write($this->highlightText($textWriter->flush()));
 +		parent::onPreRender($writer);
 +		$this->registerHighlightScripts();
  	}
  	/**
 @@ -131,27 +123,12 @@ class TTextHighlighter extends TWebControl  	}
  	/**
 -	 * @return boolean true will show "Copy Code" link. Defaults to false.
 -	 */
 -	public function getEnableCopyCode()
 -	{
 -		return $this->getViewState('CopyCode', false);
 -	}
 -
 -	/**
 -	 * @param boolean true to show the "Copy Code" link.
 -	 */
 -	public function setEnableCopyCode($value)
 -	{
 -		$this->setViewState('CopyCode', TPropertyValue::ensureBoolean($value), false);
 -	}
 -
 -	/**
 -	 * Returns the highlighted text.
 -	 * @param string text to highlight.
 -	 * @return string highlighted text.
 +	 * Processes a text string.
 +	 * This method is required by the parent class.
 +	 * @param string text string to be processed
 +	 * @return string the processed text result
  	 */
 -	protected function highlightText($text)
 +	public function processText($text)
  	{
  		$geshi = new GeSHi(trim($text), $this->getLanguage());
  		if($this->getShowLineNumbers())
 diff --git a/framework/Web/UI/WebControls/TTextProcessor.php b/framework/Web/UI/WebControls/TTextProcessor.php new file mode 100644 index 00000000..4c4c68f2 --- /dev/null +++ b/framework/Web/UI/WebControls/TTextProcessor.php @@ -0,0 +1,87 @@ +<?php
 +/**
 + * TTextProcessor class file
 + *
 + * @author Qiang Xue <qiang.xue@gmail.com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005 Wei Zhuo
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $Date: $
 + * @package System.Web.UI.WebControls
 + */
 +
 +/**
 + * TTextProcessor class.
 + *
 + * TTextProcessor is the base class for classes that process or transform
 + * text content into different forms. The text content to be processed
 + * is specified by {@link setText Text} property. If it is not set, the body
 + * content enclosed within the processor control will be processed and rendered.
 + * The body content includes static text strings and the rendering result
 + * of child controls.
 + *
 + * Note, all child classes must implement {@link processText} method.
 + *
 + * @author Qiang Xue <qiang.xue@gmail.com>
 + * @version $Revision: $  $Date: $
 + * @package System.Web.UI
 + * @since 3.0.1
 + */
 +abstract class TTextProcessor extends TWebControl
 +{
 +	/**
 +	 * Processes a text string.
 +	 * This method must be implemented by child classes.
 +	 * @param string text string to be processed
 +	 * @return string the processed text result
 +	 */
 +	abstract public function processText($text);
 +
 +	/**
 +	 * HTML-decodes static text.
 +	 * This method overrides parent implementation.
 +	 * @param mixed object to be added as body content
 +	 */
 +	public function addParsedObject($object)
 +	{
 +		if(is_string($object))
 +			$object=html_entity_decode($object,ENT_QUOTES,'UTF-8');
 +		parent::addParsedObject($object);
 +	}
 +
 +	/**
 +	 * @return string text to be processed
 +	 */
 +	public function getText()
 +	{
 +		return $this->getViewState('Text','');
 +	}
 +
 +	/**
 +	 * @param string text to be processed
 +	 */
 +	public function setText($value)
 +	{
 +		$this->setViewState('Text',$value);
 +	}
 +
 +	/**
 +	 * Renders body content.
 +	 * This method overrides the parent implementation by replacing
 +	 * the body content with the processed text content.
 +	 * @param THtmlWriter writer
 +	 */
 +	public function renderContents($writer)
 +	{
 +		if(($text=$this->getText())==='' && $this->getHasControls())
 +		{
 +			$textWriter=new TTextWriter;
 +			parent::renderContents(new THtmlWriter($textWriter));
 +			$text=$textWriter->flush();
 +		}
 +		if($text!=='')
 +			$writer->write($this->processText($text));
 +	}
 +
 +}
 +?>
\ No newline at end of file diff --git a/framework/Web/UI/WebControls/TWizard.php b/framework/Web/UI/WebControls/TWizard.php index 811c4e76..fa0fd92a 100644 --- a/framework/Web/UI/WebControls/TWizard.php +++ b/framework/Web/UI/WebControls/TWizard.php @@ -1332,7 +1332,7 @@ class TWizard extends TWebControl implements INamingContainer  	 * @param TEventParameter event parameter
  	 * @throws TInvalidDataValueException if a navigation command is associated with an invalid parameter
  	 */
 -	public function onBubbleEvent($sender,$param)
 +	public function bubbleEvent($sender,$param)
  	{
  		if($param instanceof TCommandEventParameter)
  		{
 | 
