summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes2
-rw-r--r--HISTORY3
-rw-r--r--UPGRADE2
-rw-r--r--buildscripts/classtree/build.php179
-rw-r--r--demos/quickstart/protected/comments/CommentList.tpl20
-rw-r--r--framework/TApplicationComponent.php2
-rw-r--r--framework/TComponent.php138
-rw-r--r--framework/Web/UI/TControl.php9
-rw-r--r--framework/Web/UI/TPageStatePersister.php2
-rw-r--r--framework/Web/UI/WebControls/TDataBoundControl.php8
-rw-r--r--framework/Web/UI/WebControls/TDataGrid.php11
-rw-r--r--framework/Web/UI/WebControls/TDataList.php6
-rw-r--r--framework/Web/UI/WebControls/TFileUpload.php3
-rw-r--r--framework/Web/UI/WebControls/TListControl.php3
-rw-r--r--framework/Web/UI/WebControls/TMarkdown.php90
-rw-r--r--framework/Web/UI/WebControls/TMultiView.php2
-rw-r--r--framework/Web/UI/WebControls/TRepeater.php6
-rw-r--r--framework/Web/UI/WebControls/TTextHighlighter.php61
-rw-r--r--framework/Web/UI/WebControls/TTextProcessor.php87
-rw-r--r--framework/Web/UI/WebControls/TWizard.php2
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
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 @@
+<?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 &copy; 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)
{