summaryrefslogtreecommitdiff
path: root/demos/blog/protected/Pages
diff options
context:
space:
mode:
authorxue <>2006-05-29 03:08:07 +0000
committerxue <>2006-05-29 03:08:07 +0000
commit2ea02214b2fb6bedb58dbbd318ef171a9e146524 (patch)
tree16b12d9f68986fe204900d1cee4914a0a4035a7b /demos/blog/protected/Pages
parent8c1edb7f4eced999c9704ec9ff7ba11d88248bbd (diff)
Merge from 3.0 branch till 1099.
Diffstat (limited to 'demos/blog/protected/Pages')
-rw-r--r--demos/blog/protected/Pages/Admin/AdminMenu.php7
-rw-r--r--demos/blog/protected/Pages/Admin/AdminMenu.tpl16
-rw-r--r--demos/blog/protected/Pages/Admin/ConfigMan.page56
-rw-r--r--demos/blog/protected/Pages/Admin/ConfigMan.php15
-rw-r--r--demos/blog/protected/Pages/Admin/PostMan.page76
-rw-r--r--demos/blog/protected/Pages/Admin/PostMan.php56
-rw-r--r--demos/blog/protected/Pages/Admin/Settings.page4
-rw-r--r--demos/blog/protected/Pages/Admin/UserMan.page95
-rw-r--r--demos/blog/protected/Pages/Admin/UserMan.php58
-rw-r--r--demos/blog/protected/Pages/Admin/config.xml8
-rw-r--r--demos/blog/protected/Pages/ErrorReport.page15
-rw-r--r--demos/blog/protected/Pages/ErrorReport.php12
-rw-r--r--demos/blog/protected/Pages/Posts/EditCategory.page36
-rw-r--r--demos/blog/protected/Pages/Posts/EditCategory.php44
-rw-r--r--demos/blog/protected/Pages/Posts/EditPost.page41
-rw-r--r--demos/blog/protected/Pages/Posts/EditPost.php51
-rw-r--r--demos/blog/protected/Pages/Posts/ListPost.page27
-rw-r--r--demos/blog/protected/Pages/Posts/ListPost.php44
-rw-r--r--demos/blog/protected/Pages/Posts/MyPost.page46
-rw-r--r--demos/blog/protected/Pages/Posts/MyPost.php34
-rw-r--r--demos/blog/protected/Pages/Posts/NewCategory.page36
-rw-r--r--demos/blog/protected/Pages/Posts/NewCategory.php24
-rw-r--r--demos/blog/protected/Pages/Posts/NewPost.page41
-rw-r--r--demos/blog/protected/Pages/Posts/NewPost.php34
-rw-r--r--demos/blog/protected/Pages/Posts/ViewPost.page113
-rw-r--r--demos/blog/protected/Pages/Posts/ViewPost.php73
-rw-r--r--demos/blog/protected/Pages/Posts/config.xml7
-rw-r--r--demos/blog/protected/Pages/Users/EditUser.page74
-rw-r--r--demos/blog/protected/Pages/Users/EditUser.php43
-rw-r--r--demos/blog/protected/Pages/Users/NewUser.page104
-rw-r--r--demos/blog/protected/Pages/Users/NewUser.php31
-rw-r--r--demos/blog/protected/Pages/Users/ViewUser.page21
-rw-r--r--demos/blog/protected/Pages/Users/ViewUser.php19
-rw-r--r--demos/blog/protected/Pages/Users/config.xml7
34 files changed, 1368 insertions, 0 deletions
diff --git a/demos/blog/protected/Pages/Admin/AdminMenu.php b/demos/blog/protected/Pages/Admin/AdminMenu.php
new file mode 100644
index 00000000..40f40b88
--- /dev/null
+++ b/demos/blog/protected/Pages/Admin/AdminMenu.php
@@ -0,0 +1,7 @@
+<?php
+
+class AdminMenu extends TTemplateControl
+{
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Admin/AdminMenu.tpl b/demos/blog/protected/Pages/Admin/AdminMenu.tpl
new file mode 100644
index 00000000..596f3ed2
--- /dev/null
+++ b/demos/blog/protected/Pages/Admin/AdminMenu.tpl
@@ -0,0 +1,16 @@
+<div class="submenu">
+<com:XListMenu ActiveCssClass="submenu-active" InactiveCssClass="submenu-inactive">
+ <com:XListMenuItem
+ Text="Posts"
+ PagePath="Admin.PostMan"
+ NavigateUrl=<%= $this->Service->constructUrl('Admin.PostMan') %> />
+ <com:XListMenuItem
+ Text="Users"
+ PagePath="Admin.UserMan"
+ NavigateUrl=<%= $this->Service->constructUrl('Admin.UserMan') %> />
+ <com:XListMenuItem
+ Text="Configurations"
+ PagePath="Admin.ConfigMan"
+ NavigateUrl=<%= $this->Service->constructUrl('Admin.ConfigMan') %> />
+</com:XListMenu>
+</div> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Admin/ConfigMan.page b/demos/blog/protected/Pages/Admin/ConfigMan.page
new file mode 100644
index 00000000..ad728284
--- /dev/null
+++ b/demos/blog/protected/Pages/Admin/ConfigMan.page
@@ -0,0 +1,56 @@
+<com:TContent ID="Main">
+
+<h2>Administration Center</h2>
+
+<com:Application.Pages.Admin.AdminMenu />
+
+<com:TPanel GroupingText="Site settings">
+
+<span class="input-label">Title</span>
+<br/>
+<com:TTextBox ID="SiteTitle" />
+<br/>
+
+<span class="input-label">Subtitle</span>
+<br/>
+<com:TTextBox ID="SiteSubtitle" />
+<br/>
+
+<span class="input-label">Owner name</span>
+<br/>
+<com:TTextBox ID="SiteOwner" />
+<br/>
+
+<span class="input-label">Owner email</span>
+<br/>
+<com:TTextBox ID="AdminEmail" />
+<br/>
+
+<span class="input-label">Site theme</span>
+<br/>
+<com:TDropDownList ID="ThemeList" />
+<br/>
+
+</com:TPanel>
+
+
+<com:TPanel GroupingText="Account settings">
+
+<com:TCheckBox ID="MultipleUser" Text="Allow multiple users" />
+<br/>
+
+<com:TCheckBox ID="AccountApproval" Text="New accounts need approval" />
+<br/>
+
+</com:TPanel>
+
+<com:TPanel GroupingText="Post settings">
+
+<com:TCheckBox ID="PostApproval" Text="New posts need approval" />
+<br/>
+
+</com:TPanel>
+
+<com:TLinkButton Text="Save" OnClick="saveButtonClicked" />
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Admin/ConfigMan.php b/demos/blog/protected/Pages/Admin/ConfigMan.php
new file mode 100644
index 00000000..dcbe1537
--- /dev/null
+++ b/demos/blog/protected/Pages/Admin/ConfigMan.php
@@ -0,0 +1,15 @@
+<?php
+
+class ConfigMan extends BlogPage
+{
+ public function onLoad($param)
+ {
+ parent::onLoad($param);
+ }
+
+ public function saveButtonClicked($sender,$param)
+ {
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Admin/PostMan.page b/demos/blog/protected/Pages/Admin/PostMan.page
new file mode 100644
index 00000000..8ba8ef29
--- /dev/null
+++ b/demos/blog/protected/Pages/Admin/PostMan.page
@@ -0,0 +1,76 @@
+<com:TContent ID="Main">
+
+<h2>Administration Center</h2>
+
+<com:Application.Pages.Admin.AdminMenu />
+
+<com:TDataGrid ID="PostGrid"
+ AutoGenerateColumns="false"
+ DataKeyField="ID"
+ CssClass="grid"
+ HeaderStyle.CssClass="grid-header"
+ ItemStyle.CssClass="grid-row1"
+ SelectedItemStyle.CssClass="grid-row-selected"
+ AlternatingItemStyle.CssClass="grid-row2"
+ AllowPaging="true"
+ AllowCustomPaging="true"
+ PageSize="20"
+ PagerStyle.CssClass="grid-pager"
+ PagerStyle.Mode="Numeric"
+ OnPageIndexChanged="changePage"
+ OnPagerCreated="pagerCreated"
+ OnEditCommand="editItem"
+ OnUpdateCommand="saveItem"
+ OnCancelCommand="cancelItem"
+ >
+ <com:THyperLinkColumn
+ HeaderText="Title"
+ DataNavigateUrlField="ID"
+ DataNavigateUrlFormatString="#$this->Service->constructUrl('Posts.ViewPost',array('id'=>{0}))"
+ DataTextField="Title"
+ />
+ <com:THyperLinkColumn
+ HeaderText="Author"
+ DataNavigateUrlField="AuthorID"
+ DataNavigateUrlFormatString="#$this->Service->constructUrl('Users.ViewUser',array('id'=>{0}))"
+ DataTextField="AuthorName"
+ />
+ <com:TTemplateColumn
+ HeaderText="Status"
+ ItemStyle.HorizontalAlign="Center"
+ ItemStyle.Width="90px" >
+ <prop:ItemTemplate>
+ <%#
+ $this->Parent->DataItem->Status===0 ?
+ 'Published' :
+ ($this->Parent->DataItem->Status===1 ? 'Draft' : 'Pending')
+ %>
+ </prop:ItemTemplate>
+ <prop:EditItemTemplate>
+ <com:TDropDownList ID="PostStatus" SelectedValue=<%# $this->Parent->DataItem->Status %> >
+ <com:TListItem Value="0" Text="Published" />
+ <com:TListItem Value="1" Text="Draft" />
+ <com:TListItem Value="2" Text="Pending" />
+ </com:TDropDownList>
+ </prop:EditItemTemplate>
+ </com:TTemplateColumn>
+ <com:TBoundColumn
+ HeaderText="Time"
+ ReadOnly="true"
+ DataField="CreateTime"
+ DataFormatString="#date('M j, Y',{0})"
+ ItemStyle.Wrap="false"
+ ItemStyle.Width="90px"
+ ItemStyle.HorizontalAlign="Center"
+ />
+ <com:TEditCommandColumn
+ HeaderText="Command"
+ HeaderStyle.Width="80px"
+ UpdateText="Save"
+ ItemStyle.HorizontalAlign="Center"
+ ItemStyle.Wrap="false"
+ ItemStyle.Width="80px"
+ />
+</com:TDataGrid>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Admin/PostMan.php b/demos/blog/protected/Pages/Admin/PostMan.php
new file mode 100644
index 00000000..a99332eb
--- /dev/null
+++ b/demos/blog/protected/Pages/Admin/PostMan.php
@@ -0,0 +1,56 @@
+<?php
+
+class PostMan extends BlogPage
+{
+ protected function bindData()
+ {
+ $offset=$this->PostGrid->CurrentPageIndex*$this->PostGrid->PageSize;
+ $limit=$this->PostGrid->PageSize;
+ $this->PostGrid->DataSource=$this->DataAccess->queryPosts('','','','ORDER BY a.status DESC, create_time DESC',"LIMIT $offset,$limit");
+ $this->PostGrid->VirtualItemCount=$this->DataAccess->queryPostCount('','','');
+ $this->PostGrid->dataBind();
+ }
+
+ public function onLoad($param)
+ {
+ parent::onLoad($param);
+ if(!$this->IsPostBack)
+ $this->bindData();
+ }
+
+ public function changePage($sender,$param)
+ {
+ $this->PostGrid->CurrentPageIndex=$param->NewPageIndex;
+ $this->bindData();
+ }
+
+ public function pagerCreated($sender,$param)
+ {
+ $param->Pager->Controls->insertAt(0,'Page: ');
+ }
+
+ public function editItem($sender,$param)
+ {
+ $this->PostGrid->EditItemIndex=$param->Item->ItemIndex;
+ $this->bindData();
+ }
+
+ public function saveItem($sender,$param)
+ {
+ $item=$param->Item;
+ $postID=$this->PostGrid->DataKeys[$item->ItemIndex];
+ $postRecord=$this->DataAccess->queryPostByID($postID);
+ $postRecord->Status=TPropertyValue::ensureInteger($item->Cells[2]->PostStatus->SelectedValue);
+ $this->DataAccess->updatePost($postRecord);
+ $this->PostGrid->EditItemIndex=-1;
+ $this->bindData();
+ }
+
+ public function cancelItem($sender,$param)
+ {
+ $this->PostGrid->EditItemIndex=-1;
+ $this->bindData();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Admin/Settings.page b/demos/blog/protected/Pages/Admin/Settings.page
new file mode 100644
index 00000000..48dfde96
--- /dev/null
+++ b/demos/blog/protected/Pages/Admin/Settings.page
@@ -0,0 +1,4 @@
+<com:TContent ID="main" >
+Welcome, <com:TLabel Text=<%= $this->User->Name %> />!
+This page contains site settings accessible only to site admin.
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Admin/UserMan.page b/demos/blog/protected/Pages/Admin/UserMan.page
new file mode 100644
index 00000000..a8b634c6
--- /dev/null
+++ b/demos/blog/protected/Pages/Admin/UserMan.page
@@ -0,0 +1,95 @@
+<com:TContent ID="Main">
+
+<h2>Administration Center</h2>
+
+<com:Application.Pages.Admin.AdminMenu />
+
+<com:TDataGrid ID="UserGrid"
+ AutoGenerateColumns="false"
+ DataKeyField="ID"
+ CssClass="grid"
+ HeaderStyle.CssClass="grid-header"
+ ItemStyle.CssClass="grid-row1"
+ SelectedItemStyle.CssClass="grid-row-selected"
+ AlternatingItemStyle.CssClass="grid-row2"
+ AllowPaging="true"
+ AllowCustomPaging="true"
+ PageSize="20"
+ PagerStyle.CssClass="grid-pager"
+ PagerStyle.Mode="Numeric"
+ OnPageIndexChanged="changePage"
+ OnPagerCreated="pagerCreated"
+ OnEditCommand="editItem"
+ OnUpdateCommand="saveItem"
+ OnCancelCommand="cancelItem"
+ >
+ <com:THyperLinkColumn
+ HeaderText="Name"
+ DataNavigateUrlField="ID"
+ DataNavigateUrlFormatString="#$this->Service->constructUrl('Users.ViewUser',array('id'=>{0}))"
+ DataTextField="Name"
+ />
+ <com:TTemplateColumn
+ HeaderText="Role"
+ ItemStyle.HorizontalAlign="Center"
+ ItemStyle.Wrap="false"
+ ItemStyle.Width="7px" >
+ <prop:ItemTemplate>
+ <%# $this->Parent->DataItem->Role===0 ? 'User' : 'Admin' %>
+ </prop:ItemTemplate>
+ <prop:EditItemTemplate>
+ <com:TDropDownList ID="UserRole" SelectedValue=<%# $this->Parent->DataItem->Role %> >
+ <com:TListItem Value="0" Text="User" />
+ <com:TListItem Value="1" Text="Admin" />
+ </com:TDropDownList>
+ </prop:EditItemTemplate>
+ </com:TTemplateColumn>
+ <com:TTemplateColumn
+ HeaderText="Status"
+ ItemStyle.HorizontalAlign="Center"
+ ItemStyle.Wrap="false"
+ ItemStyle.Width="70px" >
+ <prop:ItemTemplate>
+ <%#
+ $this->Parent->DataItem->Status===0 ?
+ 'Normal' :
+ ($this->Parent->DataItem->Status===1 ? 'Disabled' : 'Pending')
+ %>
+ </prop:ItemTemplate>
+ <prop:EditItemTemplate>
+ <com:TDropDownList ID="UserStatus" SelectedValue=<%# $this->Parent->DataItem->Status %> >
+ <com:TListItem Value="0" Text="Normal" />
+ <com:TListItem Value="1" Text="Disabled" />
+ <com:TListItem Value="2" Text="Pending" />
+ </com:TDropDownList>
+ </prop:EditItemTemplate>
+ </com:TTemplateColumn>
+ <com:TBoundColumn
+ HeaderText="Email"
+ DataField="Email"
+ ItemStyle.Wrap="false"
+ ItemStyle.Width="90px"
+ ReadOnly="true" >
+ <prop:DataFormatString>#
+ '<a href="mailto:'.{0}.'">'.{0}.'</a>'
+ </prop:DataFormatString>
+ </com:TBoundColumn>
+ <com:TBoundColumn
+ HeaderText="Reg. Date"
+ DataField="CreateTime"
+ DataFormatString="#date('M j, Y',{0})"
+ ReadOnly="true"
+ ItemStyle.Wrap="false"
+ ItemStyle.Width="90px"
+ />
+ <com:TEditCommandColumn
+ HeaderText="Command"
+ HeaderStyle.Width="80px"
+ UpdateText="Save"
+ ItemStyle.HorizontalAlign="Center"
+ ItemStyle.Wrap="false"
+ ItemStyle.Width="80px"
+ />
+</com:TDataGrid>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Admin/UserMan.php b/demos/blog/protected/Pages/Admin/UserMan.php
new file mode 100644
index 00000000..1cb62482
--- /dev/null
+++ b/demos/blog/protected/Pages/Admin/UserMan.php
@@ -0,0 +1,58 @@
+<?php
+
+class UserMan extends BlogPage
+{
+ protected function bindData()
+ {
+ $author=$this->User->ID;
+ $offset=$this->UserGrid->CurrentPageIndex*$this->UserGrid->PageSize;
+ $limit=$this->UserGrid->PageSize;
+ $this->UserGrid->DataSource=$this->DataAccess->queryUsers('','ORDER BY status DESC, name ASC',"LIMIT $offset,$limit");
+ $this->UserGrid->VirtualItemCount=$this->DataAccess->queryUserCount('');
+ $this->UserGrid->dataBind();
+ }
+
+ public function onLoad($param)
+ {
+ parent::onLoad($param);
+ if(!$this->IsPostBack)
+ $this->bindData();
+ }
+
+ public function changePage($sender,$param)
+ {
+ $this->UserGrid->CurrentPageIndex=$param->NewPageIndex;
+ $this->bindData();
+ }
+
+ public function pagerCreated($sender,$param)
+ {
+ $param->Pager->Controls->insertAt(0,'Page: ');
+ }
+
+ public function editItem($sender,$param)
+ {
+ $this->UserGrid->EditItemIndex=$param->Item->ItemIndex;
+ $this->bindData();
+ }
+
+ public function saveItem($sender,$param)
+ {
+ $item=$param->Item;
+ $userID=$this->UserGrid->DataKeys[$item->ItemIndex];
+ $userRecord=$this->DataAccess->queryUserByID($userID);
+ $userRecord->Role=TPropertyValue::ensureInteger($item->Cells[1]->UserRole->SelectedValue);
+ $userRecord->Status=TPropertyValue::ensureInteger($item->Cells[2]->UserStatus->SelectedValue);
+ $this->DataAccess->updateUser($userRecord);
+ $this->UserGrid->EditItemIndex=-1;
+ $this->bindData();
+ }
+
+ public function cancelItem($sender,$param)
+ {
+ $this->UserGrid->EditItemIndex=-1;
+ $this->bindData();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Admin/config.xml b/demos/blog/protected/Pages/Admin/config.xml
new file mode 100644
index 00000000..c99e5892
--- /dev/null
+++ b/demos/blog/protected/Pages/Admin/config.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<configuration>
+ <authorization>
+ <allow roles="admin" />
+ <deny users="*" />
+ </authorization>
+</configuration> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/ErrorReport.page b/demos/blog/protected/Pages/ErrorReport.page
new file mode 100644
index 00000000..a9b461d9
--- /dev/null
+++ b/demos/blog/protected/Pages/ErrorReport.page
@@ -0,0 +1,15 @@
+<com:TContent ID="Main">
+
+<h2>Error</h2>
+
+<p>
+<%= $this->ErrorMessage %>
+</p>
+
+<p>
+Please <a href="mailto:<%$ AdminEmail %>">report to us</a>
+if you believe this error is caused by our system. Thanks!
+</p>
+
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/ErrorReport.php b/demos/blog/protected/Pages/ErrorReport.php
new file mode 100644
index 00000000..3b24170f
--- /dev/null
+++ b/demos/blog/protected/Pages/ErrorReport.php
@@ -0,0 +1,12 @@
+<?php
+
+class ErrorReport extends BlogPage
+{
+ public function getErrorMessage()
+ {
+ $id=TPropertyValue::ensureInteger($this->Request['id']);
+ return BlogErrors::getMessage($id);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/EditCategory.page b/demos/blog/protected/Pages/Posts/EditCategory.page
new file mode 100644
index 00000000..fdde2648
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/EditCategory.page
@@ -0,0 +1,36 @@
+<com:TContent ID="Main">
+
+<h2>Update Post Category</h2>
+
+<span class="input-label">Category name</span>
+<com:TRequiredFieldValidator
+ Display="Dynamic"
+ ControlToValidate="CategoryName"
+ ErrorMessage="...is required"
+ ValidationGroup="category" />
+<com:TCustomValidator
+ ControlToValidate="CategoryName"
+ ValidationGroup="category"
+ Display="Dynamic"
+ OnServerValidate="checkCategoryName"
+ Text="...must be unique"
+ ControlCssClass="inputerror" />
+<br/>
+<com:TTextBox ID="CategoryName" Columns="50" MaxLength="128" />
+<br/>
+
+<span class="input-label">Description</span>
+<br/>
+<com:TTextBox
+ ID="CategoryDescription"
+ TextMode="MultiLine"
+ Columns="50"
+ Rows="5" />
+<br/>
+
+<com:TLinkButton
+ Text="Save"
+ OnClick="saveButtonClicked"
+ ValidationGroup="category" />
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/EditCategory.php b/demos/blog/protected/Pages/Posts/EditCategory.php
new file mode 100644
index 00000000..fd2d0707
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/EditCategory.php
@@ -0,0 +1,44 @@
+<?php
+
+class EditCategory extends BlogPage
+{
+ public function getCurrentCategory()
+ {
+ $id=TPropertyValue::ensureInteger($this->Request['id']);
+ if(($cat=$this->DataAccess->queryCategoryByID($id))!==null)
+ return $cat;
+ else
+ throw new BlogException('xxx');
+ }
+
+ public function onLoad($param)
+ {
+ parent::onLoad($param);
+ if(!$this->IsPostBack)
+ {
+ $catRecord=$this->getCurrentCategory();
+ $this->CategoryName->Text=$catRecord->Name;
+ $this->CategoryDescription->Text=$catRecord->Description;
+ }
+ }
+
+ public function saveButtonClicked($sender,$param)
+ {
+ if($this->IsValid)
+ {
+ $categoryRecord=$this->getCurrentCategory();
+ $categoryRecord->Name=$this->CategoryName->Text;
+ $categoryRecord->Description=$this->CategoryDescription->Text;
+ $this->DataAccess->updateCategory($categoryRecord);
+ $this->gotoPage('Posts.ListPost',array('cat'=>$categoryRecord->ID));
+ }
+ }
+
+ public function checkCategoryName($sender,$param)
+ {
+ $name=$this->CategoryName->Text;
+ $param->IsValid=$this->DataAccess->queryCategoryByName($name)===null;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/EditPost.page b/demos/blog/protected/Pages/Posts/EditPost.page
new file mode 100644
index 00000000..591f5945
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/EditPost.page
@@ -0,0 +1,41 @@
+<com:TContent ID="Main">
+
+<h2>Update Post</h2>
+
+Title
+<com:TRequiredFieldValidator
+Display="Dynamic"
+ ControlToValidate="Title"
+ ErrorMessage="...is required"
+ ValidationGroup="post" />
+<br/>
+<com:TTextBox ID="Title" Columns="70" MaxLength="256" />
+<br/>
+
+Content
+<com:TRequiredFieldValidator
+Display="Dynamic"
+ ControlToValidate="Content"
+ ErrorMessage="...is required"
+ ValidationGroup="post" />
+<br/>
+<com:THtmlArea ID="Content" Width="450px" />
+<br/>
+
+Categories<br/>
+<com:TListBox
+ ID="Categories"
+ SelectionMode="Multiple"
+ DataTextField="Name"
+ DataValueField="ID" />
+<br/>
+
+<com:TCheckBox ID="DraftMode" Text="in draft mode (the post will not be published)" />
+<br/>
+
+<com:TLinkButton
+ Text="Save"
+ OnClick="saveButtonClicked"
+ ValidationGroup="post" />
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/EditPost.php b/demos/blog/protected/Pages/Posts/EditPost.php
new file mode 100644
index 00000000..57e92b1c
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/EditPost.php
@@ -0,0 +1,51 @@
+<?php
+
+class EditPost extends BlogPage
+{
+ public function getCurrentPost()
+ {
+ $id=TPropertyValue::ensureInteger($this->Request['id']);
+ if(($post=$this->DataAccess->queryPostByID($id))!==null)
+ return $post;
+ else
+ throw new BlogException('xxx');
+ }
+
+ public function onLoad($param)
+ {
+ parent::onLoad($param);
+ if(!$this->IsPostBack)
+ {
+ $postRecord=$this->getCurrentPost();
+ $this->Title->Text=$postRecord->Title;
+ $this->Content->Text=$postRecord->Content;
+ $this->DraftMode->Checked=$postRecord->Status===0;
+ $this->Categories->DataSource=$this->DataAccess->queryCategories();
+ $this->Categories->dataBind();
+ $cats=$this->DataAccess->queryCategoriesByPostID($postRecord->ID);
+ $catIDs=array();
+ foreach($cats as $cat)
+ $catIDs[]=$cat->ID;
+ $this->Categories->SelectedValues=$catIDs;
+ }
+ }
+
+ public function saveButtonClicked($sender,$param)
+ {
+ if($this->IsValid)
+ {
+ $postRecord=$this->getCurrentPost();
+ $postRecord->Title=$this->Title->Text;
+ $postRecord->Content=$this->Content->Text;
+ $postRecord->Status=$this->DraftMode->Checked?0:1;
+ $postRecord->ModifyTime=time();
+ $cats=array();
+ foreach($this->Categories->SelectedValues as $value)
+ $cats[]=TPropertyValue::ensureInteger($value);
+ $this->DataAccess->updatePost($postRecord,$cats);
+ $this->gotoPage('Posts.ViewPost',array('id'=>$postRecord->ID));
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/ListPost.page b/demos/blog/protected/Pages/Posts/ListPost.page
new file mode 100644
index 00000000..15fc3d0c
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/ListPost.page
@@ -0,0 +1,27 @@
+<com:TContent ID="Main">
+
+<com:TRepeater ID="PostList" EnableViewState="false">
+ <prop:ItemTemplate>
+<div class="post">
+<div class="post-title">
+<%# $this->DataItem->Title %>
+</div>
+<div class="post-time">
+<%# date('l, F j, Y \a\t h:i:s a',$this->DataItem->CreateTime) %>
+</div>
+<div class="post-content">
+<%# $this->DataItem->Content %>
+</div>
+<div class="post-footer">
+posted by
+<%# '<a href="' . $this->Service->constructUrl('Users.ViewUser',array('id'=>$this->DataItem->AuthorID)) . '">' . $this->DataItem->AuthorName . '</a>' %>
+|
+<%# '<a href="' . $this->Service->constructUrl('Posts.ViewPost',array('id'=>$this->DataItem->ID)) . '">PermaLink</a>' %>
+|
+<%# '<a href="' . $this->Service->constructUrl('Posts.ViewPost',array('id'=>$this->DataItem->ID)) . '#comments">Comments (' . $this->DataItem->CommentCount . ')</a>' %>
+</div>
+</div>
+ </prop:ItemTemplate>
+</com:TRepeater>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/ListPost.php b/demos/blog/protected/Pages/Posts/ListPost.php
new file mode 100644
index 00000000..6d56b543
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/ListPost.php
@@ -0,0 +1,44 @@
+<?php
+
+class ListPost extends BlogPage
+{
+ const DEFAULT_LIMIT=10;
+
+ public function getPosts()
+ {
+ $timeFilter='';
+ $catFilter='';
+ if(($time=TPropertyValue::ensureInteger($this->Request['time']))>0)
+ {
+ $year=(integer)($time/100);
+ $month=$time%100;
+ $startTime=mktime(0,0,0,$month,1,$year);
+ if(++$month>12)
+ {
+ $month=1;
+ $year++;
+ }
+ $endTime=mktime(0,0,0,$month,1,$year);
+ $timeFilter="create_time>=$startTime AND create_time<$endTime";
+ }
+ if(($catID=$this->Request['cat'])!==null)
+ {
+ $catID=TPropertyValue::ensureInteger($catID);
+ $catFilter="category_id=$catID";
+ }
+ if(($offset=TPropertyValue::ensureInteger($this->Request['offset']))<=0)
+ $offset=0;
+ if(($limit=TPropertyValue::ensureInteger($this->Request['limit']))<=0)
+ $limit=self::DEFAULT_LIMIT;
+ return $this->DataAccess->queryPosts('',$timeFilter,$catFilter,'ORDER BY create_time DESC',"LIMIT $offset,$limit");
+ }
+
+ public function onLoad($param)
+ {
+ parent::onLoad($param);
+ $this->PostList->DataSource=$this->getPosts();
+ $this->PostList->dataBind();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/MyPost.page b/demos/blog/protected/Pages/Posts/MyPost.page
new file mode 100644
index 00000000..95a32ac9
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/MyPost.page
@@ -0,0 +1,46 @@
+<com:TContent ID="Main">
+
+<h2>My Posts</h2>
+
+<com:TDataGrid ID="PostGrid"
+ AutoGenerateColumns="false"
+ CssClass="grid"
+ HeaderStyle.CssClass="grid-header"
+ ItemStyle.CssClass="grid-row1"
+ AlternatingItemStyle.CssClass="grid-row2"
+ AllowPaging="true"
+ AllowCustomPaging="true"
+ PageSize="20"
+ PagerStyle.CssClass="grid-pager"
+ PagerStyle.Mode="Numeric"
+ OnPageIndexChanged="changePage"
+ OnPagerCreated="pagerCreated"
+ >
+ <com:THyperLinkColumn
+ HeaderText="Title"
+ DataNavigateUrlField="ID"
+ DataNavigateUrlFormatString="#$this->Service->constructUrl('Posts.ViewPost',array('id'=>{0}))"
+ DataTextField="Title"
+ />
+ <com:TBoundColumn
+ HeaderText="Status"
+ DataField="Status"
+ DataFormatString="#{0}?'Published':'Draft'"
+ ItemStyle.Width="70px"
+ />
+ <com:TBoundColumn
+ HeaderText="Comments"
+ DataField="CommentCount"
+ ItemStyle.HorizontalAlign="Center"
+ ItemStyle.Width="80px"
+ />
+ <com:TBoundColumn
+ HeaderText="Time"
+ DataField="CreateTime"
+ DataFormatString="#date('M j, Y',{0})"
+ ItemStyle.Wrap="false"
+ ItemStyle.Width="90px"
+ />
+</com:TDataGrid>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/MyPost.php b/demos/blog/protected/Pages/Posts/MyPost.php
new file mode 100644
index 00000000..be03ca63
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/MyPost.php
@@ -0,0 +1,34 @@
+<?php
+
+class MyPost extends BlogPage
+{
+ protected function bindData()
+ {
+ $author=$this->User->ID;
+ $offset=$this->PostGrid->CurrentPageIndex*$this->PostGrid->PageSize;
+ $limit=$this->PostGrid->PageSize;
+ $this->PostGrid->DataSource=$this->DataAccess->queryPosts("author_id=$author",'','','ORDER BY a.status ASC, create_time DESC',"LIMIT $offset,$limit");
+ $this->PostGrid->VirtualItemCount=$this->DataAccess->queryPostCount("author_id=$author",'','');
+ $this->PostGrid->dataBind();
+ }
+
+ public function onLoad($param)
+ {
+ parent::onLoad($param);
+ if(!$this->IsPostBack)
+ $this->bindData();
+ }
+
+ public function changePage($sender,$param)
+ {
+ $this->PostGrid->CurrentPageIndex=$param->NewPageIndex;
+ $this->bindData();
+ }
+
+ public function pagerCreated($sender,$param)
+ {
+ $param->Pager->Controls->insertAt(0,'Page: ');
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/NewCategory.page b/demos/blog/protected/Pages/Posts/NewCategory.page
new file mode 100644
index 00000000..92fe1468
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/NewCategory.page
@@ -0,0 +1,36 @@
+<com:TContent ID="Main">
+
+<h2>New Post Category</h2>
+
+<span class="input-label">Category name</span>
+<com:TRequiredFieldValidator
+ Display="Dynamic"
+ ControlToValidate="CategoryName"
+ ErrorMessage="...is required"
+ ValidationGroup="category" />
+<com:TCustomValidator
+ ControlToValidate="CategoryName"
+ ValidationGroup="category"
+ Display="Dynamic"
+ OnServerValidate="checkCategoryName"
+ Text="...must be unique"
+ ControlCssClass="inputerror" />
+<br/>
+<com:TTextBox ID="CategoryName" Columns="50" MaxLength="128" />
+<br/>
+
+<span class="input-label">Description</span>
+<br/>
+<com:TTextBox
+ ID="CategoryDescription"
+ TextMode="MultiLine"
+ Columns="50"
+ Rows="5" />
+<br/>
+
+<com:TLinkButton
+ Text="Save"
+ OnClick="saveButtonClicked"
+ ValidationGroup="category" />
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/NewCategory.php b/demos/blog/protected/Pages/Posts/NewCategory.php
new file mode 100644
index 00000000..d36f6af1
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/NewCategory.php
@@ -0,0 +1,24 @@
+<?php
+
+class NewCategory extends BlogPage
+{
+ public function saveButtonClicked($sender,$param)
+ {
+ if($this->IsValid)
+ {
+ $categoryRecord=new CategoryRecord;
+ $categoryRecord->Name=$this->CategoryName->Text;
+ $categoryRecord->Description=$this->CategoryDescription->Text;
+ $this->DataAccess->insertCategory($categoryRecord);
+ $this->gotoPage('Posts.ListPost',array('cat'=>$categoryRecord->ID));
+ }
+ }
+
+ public function checkCategoryName($sender,$param)
+ {
+ $name=$this->CategoryName->Text;
+ $param->IsValid=$this->DataAccess->queryCategoryByName($name)===null;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/NewPost.page b/demos/blog/protected/Pages/Posts/NewPost.page
new file mode 100644
index 00000000..a49188f6
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/NewPost.page
@@ -0,0 +1,41 @@
+<com:TContent ID="Main">
+
+<h2>Write a New Post</h2>
+
+Title
+<com:TRequiredFieldValidator
+Display="Dynamic"
+ ControlToValidate="Title"
+ ErrorMessage="...is required"
+ ValidationGroup="post" />
+<br/>
+<com:TTextBox ID="Title" Columns="70" MaxLength="256" />
+<br/>
+
+Content
+<com:TRequiredFieldValidator
+Display="Dynamic"
+ ControlToValidate="Content"
+ ErrorMessage="...is required"
+ ValidationGroup="post" />
+<br/>
+<com:THtmlArea ID="Content" Width="450px" />
+<br/>
+
+Categories<br/>
+<com:TListBox
+ ID="Categories"
+ SelectionMode="Multiple"
+ DataTextField="Name"
+ DataValueField="ID" />
+<br/>
+
+<com:TCheckBox ID="DraftMode" Text="in draft mode (the post will not be published)" />
+<br/>
+
+<com:TLinkButton
+ Text="Save"
+ OnClick="saveButtonClicked"
+ ValidationGroup="post" />
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/NewPost.php b/demos/blog/protected/Pages/Posts/NewPost.php
new file mode 100644
index 00000000..055c7f92
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/NewPost.php
@@ -0,0 +1,34 @@
+<?php
+
+class NewPost extends BlogPage
+{
+ public function onLoad($param)
+ {
+ parent::onLoad($param);
+ if(!$this->IsPostBack)
+ {
+ $this->Categories->DataSource=$this->DataAccess->queryCategories();
+ $this->Categories->dataBind();
+ }
+ }
+
+ public function saveButtonClicked($sender,$param)
+ {
+ if($this->IsValid)
+ {
+ $postRecord=new PostRecord;
+ $postRecord->Title=$this->Title->Text;
+ $postRecord->Content=$this->Content->Text;
+ $postRecord->Status=$this->DraftMode->Checked?0:1;
+ $postRecord->CreateTime=time();
+ $postRecord->AuthorID=$this->User->ID;
+ $cats=array();
+ foreach($this->Categories->SelectedValues as $value)
+ $cats[]=TPropertyValue::ensureInteger($value);
+ $this->DataAccess->insertPost($postRecord,$cats);
+ $this->gotoPage('Posts.ViewPost',array('id'=>$postRecord->ID));
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/ViewPost.page b/demos/blog/protected/Pages/Posts/ViewPost.page
new file mode 100644
index 00000000..4b233615
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/ViewPost.page
@@ -0,0 +1,113 @@
+<com:TContent ID="Main">
+
+<div class="post">
+<div class="post-title">
+<%= $this->CurrentPost->Title %>
+</div>
+<div class="post-time">
+<%= date('l, F j, Y \a\t h:i:s a',$this->CurrentPost->CreateTime) %>
+by
+<%= '<a href="' . $this->Service->constructUrl('Users.ViewUser',array('id'=>$this->CurrentPost->AuthorID)) . '">' . $this->CurrentPost->AuthorName . '</a>' %>
+<%= $this->CanEditPost ? '| <a href="' . $this->Service->constructUrl('Posts.EditPost',array('id'=>$this->CurrentPost->ID)) . '">Edit</a> | ' : '';
+%>
+<com:TLinkButton
+ Text="Delete"
+ OnClick="deleteButtonClicked"
+ Visible=<%= $this->CanEditPost %>
+ Attributes.onclick="if(!confirm('Are you sure to delete this post? This will also delete all related comments.')) return false;"
+ />
+</div>
+<div class="post-content">
+<%= $this->CurrentPost->Content %>
+</div>
+<div class="post-footer">
+<com:TRepeater ID="CategoryList" EnableViewState="false">
+ <prop:ItemTemplate>
+ [
+ <a href="<%# $this->Service->constructUrl('Posts.ListPost',array('cat'=>$this->DataItem->ID)) %>"><%# $this->DataItem->Name %></a>
+ ]
+ </prop:ItemTemplate>
+</com:TRepeater>
+</div>
+</div>
+
+<div class="comments">
+<a name="comments"></a>
+<h3>Comments</h3>
+
+<com:TRepeater ID="CommentList" OnItemCommand="repeaterItemCommand">
+ <prop:ItemTemplate>
+<div class="comment">
+<div class="comment-header">
+<com:TLinkButton
+ Text="Delete"
+ Attributes.onclick="if(!confirm('Are you sure to delete this comment?')) return false;"
+ CommandParameter=<%# $this->DataItem->ID %>
+ Visible=<%= $this->Page->CanEditPost %> Style="float:right"/>
+<%# date('F j, Y \a\t h:i:s a',$this->DataItem->CreateTime) %>
+by
+<%# $this->DataItem->AuthorWebsite==='' ?
+ $this->DataItem->AuthorName :
+ '<a href="' . $this->DataItem->AuthorWebsite . '">' . $this->DataItem->AuthorName . '</a>' %>
+</div>
+<div class="comment-content">
+<%# $this->DataItem->Content %>
+</div>
+</div>
+ </prop:ItemTemplate>
+</com:TRepeater>
+
+<h4>Leave your comment</h4>
+
+<span class="input-label">Name</span>
+<com:TRequiredFieldValidator
+ ControlToValidate="CommentAuthor"
+ ValidationGroup="comment""
+ Display="Dynamic"
+ Text="...is required"
+ ControlCssClass="inputerror" />
+<br/>
+<com:TTextBox ID="CommentAuthor" />
+<br/>
+
+<span class="input-label">Email address</span>
+<com:TRequiredFieldValidator
+ ControlToValidate="CommentEmail"
+ ValidationGroup="comment""
+ Display="Dynamic"
+ Text="...is required"
+ ControlCssClass="inputerror" />
+<com:TEmailAddressValidator
+ ControlToValidate="CommentEmail"
+ ValidationGroup="comment"
+ Display="Dynamic"
+ Text="*"
+ ErrorMessage="You entered an invalid email address."
+ ControlCssClass="inputerror" />
+<br/>
+<com:TTextBox ID="CommentEmail" />
+<br/>
+
+<span class="input-label">Personal website</span>
+<br/>
+<com:TTextBox ID="CommentWebsite" Columns="70"/>
+<br/>
+
+<span class="input-label">Comment</span>
+<com:TRequiredFieldValidator
+ ControlToValidate="CommentContent"
+ ValidationGroup="comment"
+ Display="Dynamic"
+ Text="...is required"
+ ControlCssClass="inputerror" />
+<br/>
+<com:TTextBox ID="CommentContent" TextMode="MultiLine" Columns="55" Rows="10"/>
+<br/>
+
+<com:TLinkButton
+ Text="Submit"
+ ValidationGroup="comment"
+ OnClick="submitCommentButtonClicked" />
+
+</div>
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/ViewPost.php b/demos/blog/protected/Pages/Posts/ViewPost.php
new file mode 100644
index 00000000..309bedc1
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/ViewPost.php
@@ -0,0 +1,73 @@
+<?php
+
+class ViewPost extends BlogPage
+{
+ private $_postID=null;
+ private $_post=null;
+
+ public function getPostID()
+ {
+ if($this->_postID===null)
+ $this->_postID=TPropertyValue::ensureInteger($this->Request['id']);
+ return $this->_postID;
+ }
+
+ public function getCurrentPost()
+ {
+ if($this->_post===null)
+ {
+ if(($this->_post=$this->DataAccess->queryPostByID($this->getPostID()))===null)
+ $this->reportError(BlogErrors::ERROR_POST_NOT_FOUND);
+ }
+ return $this->_post;
+ }
+
+ public function getCanEditPost()
+ {
+ $user=$this->getUser();
+ $authorID=$this->getCurrentPost()->AuthorID;
+ return $authorID===$user->getID() || $user->isInRole('admin');
+ }
+
+ public function onLoad($param)
+ {
+ parent::onLoad($param);
+ $this->CategoryList->DataSource=$this->DataAccess->queryCategoriesByPostID($this->getPostID());
+ $this->CategoryList->dataBind();
+ $this->CommentList->DataSource=$this->DataAccess->queryCommentsByPostID($this->getPostID());
+ $this->CommentList->dataBind();
+ }
+
+ public function submitCommentButtonClicked($sender,$param)
+ {
+ if($this->IsValid)
+ {
+ $commentRecord=new CommentRecord;
+ $commentRecord->PostID=$this->CurrentPost->ID;
+ $commentRecord->AuthorName=$this->CommentAuthor->Text;
+ $commentRecord->AuthorEmail=$this->CommentEmail->Text;
+ $commentRecord->AuthorWebsite=$this->CommentWebsite->Text;
+ $commentRecord->AuthorIP=$this->Request->UserHostAddress;
+ $commentRecord->Content=$this->CommentContent->Text;
+ $commentRecord->CreateTime=time();
+ $commentRecord->Status=0;
+ $this->DataAccess->insertComment($commentRecord);
+ $this->Response->reload();
+ }
+ }
+
+ public function deleteButtonClicked($sender,$param)
+ {
+ $this->DataAccess->deletePost($this->PostID);
+ $this->gotoDefaultPage();
+ }
+
+ public function repeaterItemCommand($sender,$param)
+ {
+ $id=TPropertyValue::ensureInteger($param->CommandParameter);
+ $this->DataAccess->deleteComment($id);
+ $this->Response->reload();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Posts/config.xml b/demos/blog/protected/Pages/Posts/config.xml
new file mode 100644
index 00000000..1c04e946
--- /dev/null
+++ b/demos/blog/protected/Pages/Posts/config.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<configuration>
+ <authorization>
+ <deny pages="EditPost,NewPost,MyPost" users="?" />
+ </authorization>
+</configuration> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Users/EditUser.page b/demos/blog/protected/Pages/Users/EditUser.page
new file mode 100644
index 00000000..8c21fd50
--- /dev/null
+++ b/demos/blog/protected/Pages/Users/EditUser.page
@@ -0,0 +1,74 @@
+<com:TContent ID="Main">
+
+<h2>Update Profile</h2>
+
+<com:TValidationSummary Display="Dynamic" ValidationGroup="user" />
+
+<span class="input-label">Username</span>
+<br/>
+<com:TLabel ID="Username" />
+
+<br/>
+
+<span class="input-label">Full name</span>
+<br/>
+<com:TTextBox ID="FullName" />
+
+<br/>
+
+<span class="input-label">Password</span>
+<br/>
+<com:TTextBox ID="Password" TextMode="Password" />
+<com:TRegularExpressionValidator
+ ControlToValidate="Password"
+ ValidationGroup="user"
+ Display="Dynamic"
+ RegularExpression="[\w\.]{6,16}"
+ Text="*"
+ ErrorMessage="Your password must contain only letters, digits and underscores, and it must contain at least 6 and at most 16 characters."
+ ControlCssClass="inputerror" />
+
+<br/>
+
+<span class="input-label">Re-type Password</span>
+<br/>
+<com:TTextBox ID="Password2" TextMode="Password" />
+<com:TCompareValidator
+ ControlToValidate="Password"
+ ControlToCompare="Password2"
+ ValidationGroup="user"
+ Display="Dynamic"
+ Text="*"
+ ErrorMessage="Your password entries did not match."
+ ControlCssClass="inputerror" />
+
+<br/>
+
+<span class="input-label">Email Address</span>
+<br/>
+<com:TTextBox ID="Email" />
+<com:TRequiredFieldValidator
+ ControlToValidate="Email"
+ ValidationGroup="user"
+ Text="*"
+ ErrorMessage="Please provide your email address."
+ ControlCssClass="inputerror" />
+<com:TEmailAddressValidator
+ ControlToValidate="Email"
+ ValidationGroup="user"
+ Display="Dynamic"
+ Text="*"
+ ErrorMessage="You entered an invalid email address."
+ ControlCssClass="inputerror" />
+
+<br/>
+
+<span class="input-label">Personal Website</span>
+<br/>
+<com:TTextBox ID="Website" AutoTrim="true" />
+
+<br/>
+
+<com:TLinkButton Text="Save" ValidationGroup="user" OnClick="saveButtonClicked" />
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Users/EditUser.php b/demos/blog/protected/Pages/Users/EditUser.php
new file mode 100644
index 00000000..e3efcfd1
--- /dev/null
+++ b/demos/blog/protected/Pages/Users/EditUser.php
@@ -0,0 +1,43 @@
+<?php
+
+class EditUser extends BlogPage
+{
+ public function getCurrentUser()
+ {
+ if(($user=$this->DataAccess->queryUserByID($this->User->ID))!==null)
+ return $user;
+ else
+ throw new BlogException('xxx');
+ }
+
+ public function onLoad($param)
+ {
+ parent::onLoad($param);
+ if(!$this->IsPostBack)
+ {
+ $userRecord=$this->getCurrentUser();
+ $this->Username->Text=$userRecord->Name;
+ $this->FullName->Text=$userRecord->FullName;
+ $this->Email->Text=$userRecord->Email;
+ $this->Website->Text=$userRecord->Website;
+ }
+ }
+
+ public function saveButtonClicked($sender,$param)
+ {
+ if($this->IsValid)
+ {
+ $userRecord=$this->getCurrentUser();
+ if($this->Password->Text!=='')
+ $userRecord->Password=md5($this->Password->Text);
+ $userRecord->FullName=$this->FullName->Text;
+ $userRecord->Email=$this->Email->Text;
+ $userRecord->Website=$this->Website->Text;
+ $this->DataAccess->updateUser($userRecord);
+ $authManager=$this->Application->getModule('auth');
+ $this->gotoPage('Users.ViewUser',array('id'=>$userRecord->ID));
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Users/NewUser.page b/demos/blog/protected/Pages/Users/NewUser.page
new file mode 100644
index 00000000..eba2dcec
--- /dev/null
+++ b/demos/blog/protected/Pages/Users/NewUser.page
@@ -0,0 +1,104 @@
+<com:TContent ID="Main">
+
+<h2>Create New Account</h2>
+
+<com:TValidationSummary Display="Dynamic" ValidationGroup="NewUser" />
+
+<span class="input-label">Username</span>
+<br/>
+<com:TTextBox ID="Username" />
+<com:TRequiredFieldValidator
+ ControlToValidate="Username"
+ ValidationGroup="NewUser"
+ Display="Dynamic"
+ Text="*"
+ ErrorMessage="Please choose a username."
+ ControlCssClass="inputerror" />
+<com:TRegularExpressionValidator
+ ControlToValidate="Username"
+ ValidationGroup="NewUser"
+ Display="Dynamic"
+ RegularExpression="[\w]{3,16}"
+ Text="*"
+ ErrorMessage="Your username must contain only letters, digits and underscores, and it must contain at least 3 and at most 16 characters."
+ ControlCssClass="inputerror" />
+<com:TCustomValidator
+ ControlToValidate="Username"
+ ValidationGroup="NewUser"
+ Display="Dynamic"
+ OnServerValidate="checkUsername"
+ Text="*"
+ ErrorMessage="Sorry, your username is taken by someone else. Please choose another username."
+ ControlCssClass="inputerror" />
+
+<br/>
+
+<span class="input-label">Full name</span>
+<br/>
+<com:TTextBox ID="FullName" />
+
+<br/>
+
+<span class="input-label">Password</span>
+<br/>
+<com:TTextBox ID="Password" TextMode="Password" />
+<com:TRequiredFieldValidator
+ ControlToValidate="Password"
+ ValidationGroup="NewUser"
+ Display="Dynamic"
+ Text="*"
+ ErrorMessage="Please choose a password."
+ ControlCssClass="inputerror" />
+<com:TRegularExpressionValidator
+ ControlToValidate="Password"
+ ValidationGroup="NewUser"
+ Display="Dynamic"
+ RegularExpression="[\w\.]{6,16}"
+ Text="*"
+ ErrorMessage="Your password must contain only letters, digits and underscores, and it must contain at least 6 and at most 16 characters."
+ ControlCssClass="inputerror" />
+
+<br/>
+
+<span class="input-label">Re-type Password</span>
+<br/>
+<com:TTextBox ID="Password2" TextMode="Password" />
+<com:TCompareValidator
+ ControlToValidate="Password"
+ ControlToCompare="Password2"
+ ValidationGroup="NewUser"
+ Display="Dynamic"
+ Text="*"
+ ErrorMessage="Your password entries did not match."
+ ControlCssClass="inputerror" />
+
+<br/>
+
+<span class="input-label">Email Address</span>
+<br/>
+<com:TTextBox ID="Email" />
+<com:TRequiredFieldValidator
+ ControlToValidate="Email"
+ ValidationGroup="NewUser"
+ Text="*"
+ ErrorMessage="Please provide your email address."
+ ControlCssClass="inputerror" />
+<com:TEmailAddressValidator
+ ControlToValidate="Email"
+ ValidationGroup="NewUser"
+ Display="Dynamic"
+ Text="*"
+ ErrorMessage="You entered an invalid email address."
+ ControlCssClass="inputerror" />
+
+<br/>
+
+<span class="input-label">Personal Website</span>
+<br/>
+<com:TTextBox ID="Website" AutoTrim="true" />
+
+<br/>
+
+<com:TLinkButton Text="Register" ValidationGroup="NewUser" OnClick="createUser" />
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Users/NewUser.php b/demos/blog/protected/Pages/Users/NewUser.php
new file mode 100644
index 00000000..166abf66
--- /dev/null
+++ b/demos/blog/protected/Pages/Users/NewUser.php
@@ -0,0 +1,31 @@
+<?php
+
+class NewUser extends BlogPage
+{
+ public function checkUsername($sender,$param)
+ {
+ $username=$this->Username->Text;
+ $param->IsValid=$this->DataAccess->queryUserByName($username)===null;
+ }
+
+ public function createUser($sender,$param)
+ {
+ if($this->IsValid)
+ {
+ $userRecord=new UserRecord;
+ $userRecord->Name=$this->Username->Text;
+ $userRecord->FullName=$this->FullName->Text;
+ $userRecord->Role=0;
+ $userRecord->Password=md5($this->Password->Text);
+ $userRecord->Email=$this->Email->Text;
+ $userRecord->CreateTime=time();
+ $userRecord->Website=$this->Website->Text;
+ $this->DataAccess->insertUser($userRecord);
+ $authManager=$this->Application->getModule('auth');
+ $authManager->login($this->Username->Text,$this->Password->Text);
+ $this->gotoDefaultPage();
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Users/ViewUser.page b/demos/blog/protected/Pages/Users/ViewUser.page
new file mode 100644
index 00000000..2dba6b77
--- /dev/null
+++ b/demos/blog/protected/Pages/Users/ViewUser.page
@@ -0,0 +1,21 @@
+<com:TContent ID="Main">
+
+<h2>User Profile</h2>
+
+Username: <%= $this->CurrentUser->Name %>
+<br/>
+
+Full name: <%= $this->CurrentUser->FullName %>
+<br/>
+
+Email: <%= $this->CurrentUser->Email %>
+<br/>
+
+Privilege: <%= $this->CurrentUser->Role===0? 'User':'Administrator' %>
+<br/>
+
+Personal website: <%= $this->CurrentUser->Website %>
+<br/>
+
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Users/ViewUser.php b/demos/blog/protected/Pages/Users/ViewUser.php
new file mode 100644
index 00000000..3485f56b
--- /dev/null
+++ b/demos/blog/protected/Pages/Users/ViewUser.php
@@ -0,0 +1,19 @@
+<?php
+
+class ViewUser extends BlogPage
+{
+ private $_currentUser=null;
+
+ public function getCurrentUser()
+ {
+ if($this->_currentUser===null)
+ {
+ $id=TPropertyValue::ensureInteger($this->Request['id']);
+ if(($this->_currentUser=$this->DataAccess->queryUserByID($id))===null)
+ throw new BlogException('xxx');
+ }
+ return $this->_currentUser;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog/protected/Pages/Users/config.xml b/demos/blog/protected/Pages/Users/config.xml
new file mode 100644
index 00000000..df8e4ad1
--- /dev/null
+++ b/demos/blog/protected/Pages/Users/config.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<configuration>
+ <authorization>
+ <deny pages="EditUser" users="?" />
+ </authorization>
+</configuration> \ No newline at end of file