From 112d86bb08a1dd4bde14005f757c95b0fc7a5a21 Mon Sep 17 00:00:00 2001 From: xue <> Date: Sun, 4 Jun 2006 20:51:27 +0000 Subject: Merge from 3.0 branch till 1140. --- .gitattributes | 2 + HISTORY | 3 + UPGRADE | 2 + buildscripts/classtree/build.php | 179 +++++++++++++++++++++ .../quickstart/protected/comments/CommentList.tpl | 20 +-- framework/TApplicationComponent.php | 2 +- framework/TComponent.php | 138 ++++++++++------ framework/Web/UI/TControl.php | 9 +- framework/Web/UI/TPageStatePersister.php | 2 +- framework/Web/UI/WebControls/TDataBoundControl.php | 8 +- framework/Web/UI/WebControls/TDataGrid.php | 11 +- framework/Web/UI/WebControls/TDataList.php | 6 +- framework/Web/UI/WebControls/TFileUpload.php | 3 +- framework/Web/UI/WebControls/TListControl.php | 3 +- framework/Web/UI/WebControls/TMarkdown.php | 90 ++++------- framework/Web/UI/WebControls/TMultiView.php | 2 +- framework/Web/UI/WebControls/TRepeater.php | 6 +- framework/Web/UI/WebControls/TTextHighlighter.php | 61 +++---- framework/Web/UI/WebControls/TTextProcessor.php | 87 ++++++++++ framework/Web/UI/WebControls/TWizard.php | 2 +- 20 files changed, 446 insertions(+), 190 deletions(-) create mode 100644 buildscripts/classtree/build.php create mode 100644 framework/Web/UI/WebControls/TTextProcessor.php 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 diff --git a/HISTORY b/HISTORY index 8e82239b..3d01115c 100644 --- a/HISTORY +++ b/HISTORY @@ -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 diff --git a/UPGRADE b/UPGRADE index 2cbf3355..66770c10 100644 --- a/UPGRADE +++ b/UPGRADE @@ -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 @@ +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 @@ -

Comments +

Comments ( Add your comments )

@@ -16,7 +16,7 @@
- + <%# $this->DataItem['comment'] %> @@ -29,13 +29,13 @@

Post a comment

-

Note: +

Note: Please only use the comments in relation to this page for -

    +
    • questions/critcisms/suggestions on the documentation,
    • small notes that can solve or clarify a particular problem or task.
    - If you experience errors please file a ticket + If you experience errors please file a ticket or ask at the forum. Please use the Prado wiki for longer pieces and detailed solutions.

    @@ -49,8 +49,8 @@ ControlToValidate="email" Display="Dynamic" ErrorMessage="An email address is required." /> - @@ -70,13 +70,13 @@

    Preview comment

    - + <%= $this->content->Text %>
- +
@@ -90,7 +90,7 @@

Preview comment

- + <%= $this->content->Text %> 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}, * @@ -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 OnPreLoad event handler as {@link onPagePreLoad}. + * Sets page's OnPreLoad 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 OnBubbleEvent. * 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 BubbleEvent. * This method overrides parent's implementation by wrapping event parameter * for OnCommand 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 BubbleEvent. * This method overrides parent's implementation by wrapping event parameter * for OnCommand 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 BubbleEvent. * 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 BubbleEvent. * This method overrides parent's implementation by wrapping event parameter * for Command 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 @@ -10,13 +10,19 @@ * @package System.Web.UI.WebControls */ +/** + * 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,56 +33,33 @@ * 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 * @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( - '/
\[\s*(\w+)\s*\]\n+((.|\n)*?)\s*<\\/code><\\/pre>/im', 
+				'/
\[\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
@@ -84,29 +67,14 @@ class TMarkdown extends TControl
 	 */
 	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 BubbleEvent.
 	 * 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 BubbleEvent.
 	 * This method overrides parent's implementation by wrapping event parameter
 	 * for Command 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 @@
+
+ * @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 
+ * @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)
 		{
-- 
cgit v1.2.3