summaryrefslogtreecommitdiff
path: root/demos/blog-tutorial/protected
diff options
context:
space:
mode:
authorxue <>2007-04-03 21:43:22 +0000
committerxue <>2007-04-03 21:43:22 +0000
commit51db38c9423a1d3bf476bb30054cf3288ee16c88 (patch)
tree370665b0eb19070334b73e73e4080239b1a5c055 /demos/blog-tutorial/protected
parent03dbe16b7762cc1a9e57df4e9e34bc04f46bb57f (diff)
Added blog-tutorial.
Diffstat (limited to 'demos/blog-tutorial/protected')
-rw-r--r--demos/blog-tutorial/protected/.htaccess1
-rw-r--r--demos/blog-tutorial/protected/application.xml13
-rw-r--r--demos/blog-tutorial/protected/common/InfoBox.php13
-rw-r--r--demos/blog-tutorial/protected/common/NoteBox.php13
-rw-r--r--demos/blog-tutorial/protected/common/TipBox.php13
-rw-r--r--demos/blog-tutorial/protected/common/TopicList.php8
-rw-r--r--demos/blog-tutorial/protected/common/TopicList.tpl70
-rw-r--r--demos/blog-tutorial/protected/layout/MainLayout.php7
-rw-r--r--demos/blog-tutorial/protected/layout/MainLayout.tpl44
-rw-r--r--demos/blog-tutorial/protected/pages/Day1/CreateContact.page181
-rw-r--r--demos/blog-tutorial/protected/pages/Day1/Setup.page161
-rw-r--r--demos/blog-tutorial/protected/pages/Day1/ShareLayout.page178
-rw-r--r--demos/blog-tutorial/protected/pages/Day1/directories.gifbin0 -> 3611 bytes
-rw-r--r--demos/blog-tutorial/protected/pages/Day1/directories2.gifbin0 -> 4147 bytes
-rw-r--r--demos/blog-tutorial/protected/pages/Day1/directories3.gifbin0 -> 3531 bytes
-rw-r--r--demos/blog-tutorial/protected/pages/Day1/output.gifbin0 -> 15045 bytes
-rw-r--r--demos/blog-tutorial/protected/pages/Day2/ConnectDB.page8
-rw-r--r--demos/blog-tutorial/protected/pages/Day2/CreateDB.page46
-rw-r--r--demos/blog-tutorial/protected/pages/Day2/ER.gifbin0 -> 4896 bytes
-rw-r--r--demos/blog-tutorial/protected/pages/Day2/ER.vsdbin0 -> 73728 bytes
-rw-r--r--demos/blog-tutorial/protected/pages/Overview.page21
-rw-r--r--demos/blog-tutorial/protected/pages/Requirements.page38
22 files changed, 815 insertions, 0 deletions
diff --git a/demos/blog-tutorial/protected/.htaccess b/demos/blog-tutorial/protected/.htaccess
new file mode 100644
index 00000000..e0198322
--- /dev/null
+++ b/demos/blog-tutorial/protected/.htaccess
@@ -0,0 +1 @@
+deny from all
diff --git a/demos/blog-tutorial/protected/application.xml b/demos/blog-tutorial/protected/application.xml
new file mode 100644
index 00000000..5eac200b
--- /dev/null
+++ b/demos/blog-tutorial/protected/application.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<application id="Dummy" Mode="Debug">
+ <paths>
+ <using namespace="Application.common.*" />
+ </paths>
+
+ <services>
+ <service id="page" class="TPageService" DefaultPage="Overview">
+ <pages MasterClass="Application.layout.MainLayout" Theme="PradoSoft" />
+ </service>
+ </services>
+</application> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/common/InfoBox.php b/demos/blog-tutorial/protected/common/InfoBox.php
new file mode 100644
index 00000000..271ce1e7
--- /dev/null
+++ b/demos/blog-tutorial/protected/common/InfoBox.php
@@ -0,0 +1,13 @@
+<?php
+
+class InfoBox extends TControl
+{
+ public function render($writer)
+ {
+ $writer->write("<div class=\"info\"><b class=\"tip\">Info:</b>\n");
+ $body=$this->renderChildren($writer);
+ $writer->write("</div>");
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/common/NoteBox.php b/demos/blog-tutorial/protected/common/NoteBox.php
new file mode 100644
index 00000000..f5123380
--- /dev/null
+++ b/demos/blog-tutorial/protected/common/NoteBox.php
@@ -0,0 +1,13 @@
+<?php
+
+class NoteBox extends TControl
+{
+ public function render($writer)
+ {
+ $writer->write("<div class=\"note\"><b class=\"tip\">Note:</b>\n");
+ $body=$this->renderChildren($writer);
+ $writer->write("</div>");
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/common/TipBox.php b/demos/blog-tutorial/protected/common/TipBox.php
new file mode 100644
index 00000000..2464a61a
--- /dev/null
+++ b/demos/blog-tutorial/protected/common/TipBox.php
@@ -0,0 +1,13 @@
+<?php
+
+class TipBox extends TControl
+{
+ public function render($writer)
+ {
+ $writer->write("<div class=\"tip\"><b class=\"tip\">Tip:</b>\n");
+ $body=$this->renderChildren($writer);
+ $writer->write("</div>");
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/common/TopicList.php b/demos/blog-tutorial/protected/common/TopicList.php
new file mode 100644
index 00000000..ce827cc0
--- /dev/null
+++ b/demos/blog-tutorial/protected/common/TopicList.php
@@ -0,0 +1,8 @@
+<?php
+
+class TopicList extends TTemplateControl
+{
+
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/common/TopicList.tpl b/demos/blog-tutorial/protected/common/TopicList.tpl
new file mode 100644
index 00000000..555b0efe
--- /dev/null
+++ b/demos/blog-tutorial/protected/common/TopicList.tpl
@@ -0,0 +1,70 @@
+<div id="toc">
+
+<div class="topic">
+<div>Introduction</div>
+<ul>
+ <li><a href="?page=Overview">Overview</a></li>
+ <li><a href="?page=Requirements">Requirement Analysis</a></li>
+</ul>
+</div>
+
+<div class="topic">
+<div>Day 1: Experiencing PRADO</div>
+<ul>
+ <li><a href="?page=Day1.Setup">Initial Setup</a></li>
+ <li><a href="?page=Day1.CreateContact">Creating Contact Page</a></li>
+ <li><a href="?page=Day1.ShareLayout">Sharing Common Layout</a></li>
+</ul>
+</div>
+
+<div class="topic">
+<div>Day 2: Using Database</div>
+<ul>
+ <li><a href="?page=Day2.CreateDB">Creating Database</a></li>
+ <li><a href="?page=Day2.ConnectDB">Establishing DB Connection</a></li>
+ <li><a href="?page=Day2.CreateDAO">Creating DAOs</a></li>
+ <li><a href="?page=">Creating NewPost Page</a></li>
+ <li><a href="?page=">Creating ListPost Page</a></li>
+</ul>
+</div>
+
+<div class="topic">
+<div>Day 3: Authentication and Authorization</div>
+<ul>
+ <li><a href="?page=">Creating Login Page</a></li>
+ <li><a href="?page=">Using PRADO Auth Framework</a></li>
+ <li><a href="?page=">Database-Driven Authentication</a></li>
+</ul>
+</div>
+
+<div class="topic">
+<div>Day 4: Developing and Using Components</div>
+<ul>
+</ul>
+</div>
+
+<div class="topic">
+<div>Day 5: Customization and Refactoring</div>
+<ul>
+ <li><a href="?page=">Using Themes and Skins</a></li>
+ <li><a href="?page=">Customizing Error Handling</a></li>
+ <li><a href="?page=">Logging</a></li>
+</ul>
+</div>
+
+<div class="topic">
+<div>Day 6: Performance Tuneup and Deployment</div>
+<ul>
+ <li><a href="?page=">Caching</a></li>
+</ul>
+</div>
+
+<div class="topic">
+<div>Summary</div>
+<ul>
+ <li><a href="?page=">Development Process</a></li>
+ <li><a href="?page=">Future Work</a></li>
+</ul>
+</div>
+
+</div> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/layout/MainLayout.php b/demos/blog-tutorial/protected/layout/MainLayout.php
new file mode 100644
index 00000000..253d6c03
--- /dev/null
+++ b/demos/blog-tutorial/protected/layout/MainLayout.php
@@ -0,0 +1,7 @@
+<?php
+
+class MainLayout extends TTemplateControl
+{
+}
+
+?> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/layout/MainLayout.tpl b/demos/blog-tutorial/protected/layout/MainLayout.tpl
new file mode 100644
index 00000000..1ee83bae
--- /dev/null
+++ b/demos/blog-tutorial/protected/layout/MainLayout.tpl
@@ -0,0 +1,44 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
+
+<com:THead Title="PRADO Blog Tutorial">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<meta http-equiv="content-language" content="en"/>
+</com:THead>
+
+<body>
+<com:TForm>
+<div id="header">
+<div class="title">PRADO for Dummies</div>
+<div class="image"></div>
+</div>
+
+<com:TPanel ID="MainMenu" CssClass="mainmenu">
+<a href="?">Home</a> |
+<a href="http://www.pradosoft.com">PradoSoft.com</a>
+</com:TPanel>
+
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+<tr>
+<td valign="top" width="1">
+<com:TopicList ID="TopicPanel" />
+</td>
+<td valign="top">
+
+<div id="content">
+<com:TContentPlaceHolder ID="Main" />
+</div>
+</td>
+</tr>
+</table>
+
+<div id="footer">
+Copyright &copy; 2005-2007 <a href="http://www.pradosoft.com">PradoSoft</a>.
+<br/><br/>
+<%= Prado::poweredByPrado() %>
+<a href="http://validator.w3.org/check?uri=referer"><img border="0" src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0 Transitional" height="31" width="88" /></a>
+</div>
+
+</com:TForm>
+</body>
+</html> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day1/CreateContact.page b/demos/blog-tutorial/protected/pages/Day1/CreateContact.page
new file mode 100644
index 00000000..07adbe93
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day1/CreateContact.page
@@ -0,0 +1,181 @@
+<com:TContent ID="Main">
+
+<h1>Creating Contact Page</h1>
+
+<p>
+We have created a default page <tt>Home.page</tt> using the <a href="http://www.pradosoft.com/demos/quickstart/?page=GettingStarted.CommandLine">PRADO command line tool</a>. The page is relatively static because it does not containt dynamic content. In this section, we will create an interactive page named <tt>Contact</tt>.
+</p>
+
+<p>
+The purpose of the <tt>Contact</tt> page is to collect feedback from Web users of our blog system. To achieve this goal, we plan to present users a feedback form to fill with. In this form, we will require users to provide their name, email address and feedback content. After the form is filled and submitted, an email containing the feedback will be sent to the site administrator.
+</p>
+
+<p>
+To create the <tt>Contact</tt> page, we need two files under the <tt>pages</tt> directory: the page template file <tt>Contact.page</tt> and the page class file <tt>Contact.php</tt>.
+</p>
+
+<img src="<%~ directories2.gif %>" />
+
+<com:InfoBox>
+A <a href="http://www.pradosoft.com/demos/quickstart/?page=Fundamentals.Pages">page</a> must have either a <a href="http://www.pradosoft.com/demos/quickstart/?page=Configurations.Templates1">template</a> file (extension <tt>.page</tt>) or a class file, or both:
+</p>
+
+<ul>
+<li>A template-only page is usually a page with static content, like the homepage we already created;</li>
+<li>A class-only page produces content purely based on the execution of the class methods;</li>
+<li>A page with both template and class combines the advantage of both: it uses template to easily organize the page layout and it uses class to contain necessary logic producing dynamic content.</li>
+</ul>
+</com:InfoBox>
+
+
+<h2>Creating Page Template</h2>
+
+<p>
+We first create the template file for the <tt>Contact</tt> page.
+</p>
+
+<p>
+We use template to organize the presentational layout of the feedback form. In the template, we use <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.TextBox">textboxes</a> to collect user's name, email and feedback. And we use <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.Validation">validators</a> to ensure that the user provides all these information before submitting the feedback form. The whole template looks like the following:
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="prado">
+<html>
+<head><title>My Blog - Contact</title></head>
+<body>
+<h1>Contact</h1>
+<p>Please fill out the following form to let me know your feedback on my blog. Thanks!</p>
+
+&lt;com:TForm>
+
+ ...textbox and validator for user's name...
+
+ ...textbox and validators for user's email...
+
+ ...textbox and validator for user's feedback content...
+
+ &lt;com:TButton Text="Submit" OnClick="submitButtonClicked" />
+
+&lt;/com:TForm>
+
+</body>
+</html>
+</com:TTextHighlighter>
+
+<p>
+The template looks very similar to a normal HTML page. The main difference is that the template contains a few <tt>&lt;com:&gt;</tt> tags. Each <tt>&lt;com:&gt;</tt> tag refers to a <a href="http://www.pradosoft.com/demos/quickstart/?page=Fundamentals.Controls">control</a> whose properties are being initialized with name-value pairs in the tag. For example, the <tt>&lt;com:TButton&gt;</tt> refers to the <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.Button">TButton</a> control which displays a button that users can click on to submit the feedback form. For complete template syntax, please refer to the <a href="http://www.pradosoft.com/demos/quickstart/?page=Configurations.Templates1">Quickstart Tutorial</a>.
+</p>
+
+<com:InfoBox>
+PRADO provides a control for every type of HTML input. For example, <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.TextBox">TTextBox</a> displays a text input field, <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.List">TDropDownList</a> displays a combobox. Each control is a component that may be accessed in code as an object with configurable properties.
+</com:InfoBox>
+
+<p>
+The following template shows the detail about "...textbox and validators for user's email..." in the above.
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="prado">
+<span>Your Email:</span>
+&lt;com:TRequiredFieldValidator
+ ControlToValidate="Email"
+ ErrorMessage="Please provide your email address."
+ Display="Dynamic"
+ />
+&lt;com:TEmailAddressValidator
+ ControlToValidate="Email"
+ ErrorMessage="You entered an invalid email address."
+ Display="Dynamic"
+ />
+<br/>
+&lt;com:TTextBox ID="Email" />
+<br/>
+</com:TTextHighlighter>
+
+<p>
+Three controls are used here:
+</p>
+
+<ul>
+<li><a href="http://www.pradosoft.com/docs/classdoc/TTextBox">TTextBox</a> displays a textbox to allow user to enter his email address.</li>
+<li><a href="http://www.pradosoft.com/docs/classdoc/TRequiredFieldValidator">TRequiredFieldValidator</a> ensures that the textbox is not empty when the feedback is submitted.</li>
+<li><a href="http://www.pradosoft.com/docs/classdoc/TEmailAddressValidator">TEmailAddressValidator</a> ensures that the textbox contains a <i>valid</i> email address when the feedback is submitted.</li>
+</ul>
+
+<com:TipBox>
+Writing templates with plain text editors could be tedious and not intuitive for designers. To ease this situation, PRADO has included in the releases an Adobe Dreamweaver extension that supports auto-completing PRADO tags (e.g. including control names, property names, event names, etc.) in Dreamweaver.
+</com:TipBox>
+
+
+<h2>Creating Page Class</h2>
+
+<p>
+We now create the page class <tt>Contact.php</tt>. The reason we need a page class is because we need to respond to the feedback that the user submits.
+
+<p>
+Notice in the template we have the following line. The template essentially states that when a user clicks on the button, it should call the <tt>submitButtonClicked()</tt> method. Here <tt>OnClick</tt> is the name of the user click event, and the method must be defined in the page class.
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="prado">
+ &lt;com:TButton Text="Submit" OnClick="submitButtonClicked" />
+</com:TTextHighlighter>
+
+<p>
+We thus write down the page class as follows:
+</p>
+
+<com:TTextHighlighter CssClass="source">
+<?php
+class Contact extends TPage
+{
+ /**
+ * Event handler for the OnClick event of the submit button.
+ * @param TButton the button triggering the event
+ * @param TEventParameter event parameter (null here)
+ */
+ public function submitButtonClicked($sender, $param)
+ {
+ if ($this->IsValid) // check if input validation is successful
+ {
+ // obtain the user name, email, feedback from the textboxes
+ $name = $this->Name->Text;
+ $email = $this->Email->Text;
+ $feedback = $this->Feedback->Text;
+
+ // send an email to administrator with the above information
+ $this->mailFeedback($name, $email, $feedback);
+ }
+ }
+
+ protected function mailFeedback($name, $email, $feedback)
+ {
+ // implementation of sending the feedback email
+ }
+}
+?>
+</com:TTextHighlighter>
+
+<p>
+The above code is largely self-explanatory. In fact, we just show the event-driven programming scheme. In the event handler <tt>submitButtonClicked()</tt>, we retrieve the user's input. For example, <tt>$this->Name->Text</tt> returns the <tt>Text</tt> property value of the <tt>Name</tt> control which is the textbox collecting user's name information.
+</p>
+
+<com:InfoBox>
+Page class name must be the same as the file name. This is also a requirement for writing any PRADO component class.
+</com:InfoBox>
+
+
+<h2>Testing</h2>
+
+<p>
+Our newly created <tt>Contact</tt> can be tested via the URL <tt>http://hostname/blog/index.php?page=Contact</tt>. If we click on the submit button without entering any information, we will see error messages appearing next to the corresponding textboxes. If we enter all required information, the method <tt>mailFeedback()</tt> will be invoked.
+</p>
+
+<img src="<%~ output.gif %>" />
+
+<p>
+A further enhancement to this page is to show some confirmation message on the page after the user submits feedback. And possibly, the browser may be redirected to another page if the submission is successful. We will leave these tasks to our readers.
+</p>
+
+<com:InfoBox>
+Each validator represents a validation rule. A single input control can be associated with one or multiple validators. Validators perform validation on both client side and server side. On the client side, namely the browser, validation is done using javascript; on the server side, validation is done using PHP code. Client-side validation can be turned off, while server-side validation cannot. This ensures user inputs are always checked by the specified validation rules.
+</com:InfoBox>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day1/Setup.page b/demos/blog-tutorial/protected/pages/Day1/Setup.page
new file mode 100644
index 00000000..ee4744f5
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day1/Setup.page
@@ -0,0 +1,161 @@
+<com:TContent ID="Main">
+
+<h1>Initial Setup</h1>
+
+<p>
+We start by setting up the directories and the files that are required by most PRADO applications. We use the <a href="http://www.pradosoft.com/demos/quickstart/?page=GettingStarted.CommandLine">PRADO command line tool</a> to achieve this goal.
+</p>
+
+<p>
+Assume <tt>blog</tt> is the name of the directory to hold the whole blog system, and the URL to access this folder is <tt>http://hostname/blog/</tt> (replace <tt>hostname</tt> with the actual host name).
+</p>
+
+<p>
+Under the <tt>blog</tt> directory, we run the <a href="http://www.pradosoft.com/demos/quickstart/?page=GettingStarted.CommandLine">PRADO command line tool</a> with the following command (replace <tt>path/to</tt> with the actual path to the PRADO framework installation):
+</p>
+<com:TTextHighlighter CssClass="source">
+php path/to/prado-cli.php -c .
+</com:TTextHighlighter>
+
+<p>
+Running the above command creates the following directories and files:
+</p>
+
+<img src="<%~ directories.gif %>" />
+
+<p>
+We now have a skeleton PRADO application accessible via the URL <tt>http://hostname/blog/index.php</tt> which brings up a Web page showing "Welcome to PRADO".
+</p>
+
+<p>
+It is beneficial to learn more details about the directories and files we just created.
+</p>
+
+
+<h2>Initial Files</h2>
+
+<h3>The Entry Script</h3>
+
+<p>
+Every PRADO application has an entry script, often named as <tt>index.php</tt>. In most cases, it is the only PHP script that is directly accessible by Web users. This reduces the risk of allowing Web users to execute unwanted scripts on the server.
+</p>
+
+<p>
+The main purpose of the entry script is to initialize the PRADO application and have it handle user requests. The entry script usually contains the following PHP statements,
+</p>
+
+<com:TTextHighlighter CssClass="source">
+<?php
+// include prado.php which contains basic PRADO classes
+require_once('path/to/prado.php');
+// create a PRADO application instance
+$application = new TApplication;
+// run the application and handle user requests
+$application->run();
+?>
+</com:TTextHighlighter>
+
+<com:InfoBox>
+The name of the entry script does not need to be <tt>index.php</tt>. It can be any name as long as the Web server can tell that the script is a PHP 5 script. For example, on some shared hosting environments, one may need to name the script as <tt>index.php5</tt> so that it can be properly handled by the Web server.
+</com:InfoBox>
+
+<h3>Application Configuration</h3>
+<p>
+The <i>optional</i> XML file <tt>application.xml</tt> contains the <a href="http://www.pradosoft.com/demos/quickstart/?page=Configurations.AppConfig">application configuration</a>. Its main purpose is to customize in a configurable fashion the application instance created in the entry script. For example, we may enable the <a href="http://www.pradosoft.com/demos/quickstart/?page=Advanced.Logging">logging</a> feature for our blog system with the help of application configuration.
+</p>
+
+<p>
+The file <tt>application.xml</tt> we have now is nearly empty. In fact, we may safely remove it because the application at the moment uses only default settings of PRADO. As we move forward, we will refer back constantly and show how to configure our application in <tt>application.xml</tt>.
+</p>
+
+
+<h3>Homepage</h3>
+
+<p>
+The homepage (also called default page) <tt>Home.page</tt> is the only <a href="http://www.pradosoft.com/demos/quickstart/?page=Fundamentals.Pages">page</a> created by the PRADO command line tool. It is the content in this file that shows up in the browser when visiting the URL <tt>http://hostname/blog/index.php</tt>.
+</p>
+
+<p>
+Content in the file <tt>Home.page</tt> uses the <a href="http://www.pradosoft.com/demos/quickstart/?page=Configurations.Templates1">PRADO template format</a>, which is mostly like HTML enhanced with a few PRADO-specific tags. For example, in <tt>Home.page</tt> we see the following pure HTML content:
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="prado">
+<html>
+<head>
+ <title>Welcome to PRADO</title>
+</head>
+<body>
+<h1>Welcome to PRADO!</h1>
+</body>
+</html>
+</com:TTextHighlighter>
+
+
+<h2>Initial Directories</h2>
+
+<h3>The <tt>protected</tt> Directory</h3>
+
+<p>
+The <tt>protected</tt> directory, also known as the <i>application base path</i>, is the root directory holding pages, templates, configurations, data, etc. The name <tt>protected</tt> indicates this directory should be hidden from Web users, because files under this directory often contain sensitive data.
+</p>
+
+<p>
+Different Web servers have different ways of "protecting" a directory. For Apache httpd server, the easiest way is to place under the directory a file named <tt>.htaccess</tt> with the content <tt>deny from all</tt>.
+</p>
+
+
+<h3>The <tt>protected/runtime</tt> and <tt>assets</tt> Directories</h3>
+
+<p>
+The <tt>protected/runtime</tt> and <tt>assets</tt> directories are the two directories that must be set writable by the Web server process. The <tt>runtime</tt> directory stores sensitive data (e.g. parsed application configuration) generated when running a PRADO application, while the <tt>assets</tt> directory stores published resources (e.g. image files, javascript files).
+</p>
+
+<com:InfoBox>
+It is safe to remove files and directories under <tt>protected/runtime</tt> and <tt>assets</tt>. In fact, developers are recommended to do this cleanup work when they upgrade their PRADO installation.
+</com:InfoBox>
+
+
+<h3>The <tt>pages</tt> Directory</h3>
+
+<p>
+The <tt>pages</tt> directory is the <i>root page directory</i> holding all <a href="http://www.pradosoft.com/demos/quickstart/?page=Fundamentals.Pages">pages</a> in a PRADO application. It bears an analogy to the <tt>htdocs</tt> directory for the Apache httpd Web server.
+</p>
+
+<p>
+We already see how to access the homepage. To access an arbitrary page located under <tt>pages</tt>, use the URL <tt>http://hostname/blog/index.php?page=path.to.PageName</tt>. According to this URL, PRADO will look for a page named <tt>PageName</tt> under the directory <tt>pages/path/to</tt>. The URL we used to access the homepage previously is equivalent to <tt>http://hostname/blog/index.php?page=Home</tt>.
+</p>
+
+
+<h2>Customization</h2>
+
+<p>
+It is possible to customize the name and location of the files and directories described above.
+</p>
+
+<p>
+For example, to improve security, one may want to move the whole <tt>protected</tt> directory to somewhere else that is not a Web folder. To do so, use the following PHP statement to create the application instance in the entry script:
+</p>
+
+<com:TTextHighlighter CssClass="source">
+$application = new TApplication( 'path/to/protected' );
+</com:TTextHighlighter>
+
+<p>
+To change the location of the root page directory and change the name of homepage, one can specify it in the application configuration <tt>application.xml</tt> as follows:
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="xml">
+<services>
+ <service id="page"
+ class="TPageService"
+ BasePath="path.to.pages"
+ DefaultPage="NewHome"
+ />
+</services>
+</com:TTextHighlighter>
+
+<p>
+As you learn more about PRADO, you will see that PRADO is such a flexible framework that it allows you to customize nearly every aspect. We will describe more customization techniques as we continue with our tutorial.
+</p>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day1/ShareLayout.page b/demos/blog-tutorial/protected/pages/Day1/ShareLayout.page
new file mode 100644
index 00000000..548cec1c
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day1/ShareLayout.page
@@ -0,0 +1,178 @@
+<com:TContent ID="Main">
+
+<h1>Sharing Common Layout</h1>
+
+<p>
+In this section, we will use the <a href="http://www.pradosoft.com/demos/quickstart/?page=Advanced.MasterContent">master/content</a> feature of PRADO to share common layout among pages. Common layout refers to the area that is the same or largely the same for a set of pages. For example, in our blog system, all pages will share the same header, footer and side-bar containing shortcut links. A straightforward implementation is to repeat the common layout in every page. However, this approach is prone to error and is hard to maintain. The <a href="http://www.pradosoft.com/demos/quickstart/?page=Advanced.MasterContent">master/content</a> feature allows us to treat the common layout as a control which centralizes the logic and presentation of the common layout for every page.
+</p>
+
+<com:InfoBox>
+It is also possible to share common layout via <a href="http://www.pradosoft.com/demos/quickstart/?page=Configurations.Templates1">template inclusion</a>, which is like PHP file inclusion. The drawback of template inclusion is that it is not self-contained and does not carry a class to contain the logic for the common layout.
+</com:InfoBox>
+
+
+<h2>Creating Master Control</h2>
+
+<p>
+We now create the master control <tt>MainLayout</tt> to represent the common layout shared by our blog pages. The <tt>MainLayout</tt> control is a template control extending from <tt>TTemplateControl</tt>. It requires a template file <tt>MainLayout.tpl</tt> and a class file <tt>MainLayout.php</tt> located under the same directory. To facilitate maintenance, we create a new directory <tt>protected/layouts</tt> to hold them.
+</p>
+
+<img src="<%~ directories3.gif %>" />
+
+<p>
+For the moment, <tt>MainLayout</tt> only contains a simple header and a footer, as shown in the following. In future, we will add a side-bar to it. Readers are also encouraged to enhance the layout with other features.
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="prado">
+<html>
+&lt;com:THead />
+<body>
+&lt;com:TForm>
+
+<div id="header">
+<h1>My PRADO Blog</h1>
+</div>
+
+<div id="main">
+&lt;com:TContentPlaceHolder ID="Main" />
+</div>
+
+<div id="footer">
+Powered by &lt;%= PRADO::poweredByPrado() %>
+</div>
+
+&lt;/com:TForm>
+</body>
+</html>
+</com:TTextHighlighter>
+
+<p>
+The above shows the content in the template file <tt>MainLayout.tpl</tt>. Three new tags are used:
+</p>
+<ul>
+<li><tt>&lt;com:TContentPlaceHolder&gt;</tt> represents <a href="http://www.pradosoft.com/docs/classdoc/TContentPlaceHolder">TContentPlaceHolder</a> control. It reserves the place in the template where content will be placed at. Here, the content comes from the pages who use this master control.</li>
+<li><tt>&lt;com:THead&gt;</tt> represents <a href="http://www.pradosoft.com/docs/classdoc/THead">THead</a> control which represents the &lt;head&gt; tag in HTML. It allows PRADO to manipulate the &lt;head&gt; tag as a component (e.g., setting page titles, adding custom CSS styles.)</li>
+<li><tt>&lt;%= %&gt;</tt> is an <a href="http://www.pradosoft.com/demos/quickstart/?page=Configurations.Templates2#et">expression tag</a>. It displays the evaluation result of the enclosed expression at the place where it appears.</li>
+</ul>
+
+<p>
+The class file <tt>MainLayout.php</tt> is very simple:
+</p>
+
+<com:TTextHighlighter CssClass="source">
+<?php
+class MainLayout extends TTemplateControl
+{
+}
+?>
+</com:TTextHighlighter>
+
+<com:InfoBox>
+The file extension name for page templates is <tt>.page</tt>, while for non-page templates it is <tt>.tpl</tt>. This is to differentiate pages from other controls. They both use the same <a href="http://www.pradosoft.com/demos/quickstart/?page=Configurations.Templates1">template syntax</a>. For pages, their class files are optional (default to <tt>TPage</tt>), while for non-page controls, their class files are mandatory. Similar to Java, the name of a class file must be the same as the class name. Be careful about the case-sensitivity on Linux/Unix systems.
+</com:InfoBox>
+
+
+<h2>Using Master Control</h2>
+<p>
+To use the newly created master control, we will modify <tt>Home.page</tt> and <tt>Contact.page</tt>. In particular, we need to remove the header and footer from them because the master control will be responsible for displaying them; and we need to tell the two pages that they should use <tt>MainLayout</tt> as their master.
+</p>
+
+<p>
+The following shows the content in <tt>Contact.page</tt> after the change:
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="prado">
+&lt;%@ MasterClass="Application.layouts.MainLayout" Title="My Blog - Contact" %>
+
+&lt;com:TContent ID="Main">
+
+<h1>Contact</h1>
+<p>Please fill out the following form to let me know your feedback on my blog. Thanks!</p>
+
+...textbox and validator for user's name...
+
+...textbox and validators for user's email...
+
+...textbox and validator for user's feedback content...
+
+&lt;com:TButton Text="Submit" OnClick="submitButtonClicked" />
+
+&lt;/com:TContent>
+</com:TTextHighlighter>
+
+<p>
+Content enclosed within the <tt>&lt;com:TContent&gt;</tt> tag will be inserted into the place that is reserved by <tt>&lt;com:TContentPlaceHolder&gt;</tt> in the master template.
+</p>
+
+<com:InfoBox>
+It is possible to have multiple <tt>TContentPlaceHolder</tt>'s in a master template and multiple <tt>TContent</tt>'s in a content template. They are matched to each other by their <tt>ID</tt> values. It is also possible to make a content template the master of another content template by placing a <tt>TContentPlaceHolder</tt> in the former. This is called <i>nested master</i>.
+</com:InfoBox>
+
+<p>
+Besides <tt>&lt;com:TContent&gt;</tt>, we also see another new tag <tt>&lt;%@ %&gt;</tt> in the above, which is called <a href="http://www.pradosoft.com/demos/quickstart/?page=Configurations.Templates1#tct">template control tag</a>. It contains name-value pairs which are used to initialize the corresponding properties for the template owner, namely, the <tt>Contact</tt> page.
+</p>
+
+<p>
+By setting <tt>MasterClass</tt> property as <tt>Application.layouts.MainLayout</tt>, we instruct the <tt>Contact</tt> page to use <tt>MainLayout</tt> as its master. Here, we are using the <a href="http://www.pradosoft.com/demos/quickstart/?page=Fundamentals.Components">namespace format</a> to refer to the <tt>MainLayout</tt> class.
+</p>
+
+<com:InfoBox>
+Namespace format is widely used in PRADO programming. It is used together with <a href="http://www.pradosoft.com/demos/quickstart/index.php?page=Fundamentals.Components">path aliases</a>. PRADO defines two path aliases: <tt>System</tt> refers to the <tt>framework</tt> directory of the PRADO installation, and <tt>Application</tt> refers to the <tt>protected</tt> directory. The namespace <tt>Application.layouts.MainLayout</tt> can thus be translated as <tt>protected/layouts/MainLayout</tt> which is exactly the file name (without the extension <tt>.php</tt>) for the <tt>MainLayout</tt> class.
+</com:InfoBox>
+
+
+<h2>Alternative Ways of Specifying Master</h2>
+
+<p>
+There are several additional ways to specify the master class for a page.
+</p>
+
+<p>
+We can specify master in code like the following to enable dynamic change of layout:
+</p>
+
+<com:TTextHighlighter CssClass="source">
+<?php
+class Contact extends TPage
+{
+ public function onPreInit($param)
+ {
+ parent::onPreInit($param);
+ $this->MasterClass='Path.To.NewLayout';
+ }
+
+ // ...
+}
+?>
+</com:TTextHighlighter>
+
+<p>
+In the above, we specify <tt>MasterClass</tt> in the <tt>onPreInit()</tt> method which is inherited from <tt>TPage</tt>. The method is invoked by PRADO right after the page instance is created. We thus can dynamically determine the layout to use when the page is requested. For example, when the page is requested by a registered user we use layout A, and layout B is used if a guest user is requesting the page.
+</p>
+
+<p>
+We can also specify master in <a href="http://www.pradosoft.com/demos/quickstart/?page=Configurations.AppConfig">application configuration</a> or <a href="http://www.pradosoft.com/demos/quickstart/?page=Configurations.PageConfig">page configuration</a>. The following shows the updated application configuration for our blog system:
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="xml">
+<?xml version="1.0" encoding="utf-8"?>
+<application id="blog" mode="Debug">
+ <!-- configuration for available services -->
+ <services>
+ <service id="page" class="TPageService" DefaultPage="Home">
+ <!-- initial properties set for all pages -->
+ <pages MasterClass="Application.layouts.MainLayout" />
+ </service>
+ </services>
+</application>
+</com:TTextHighlighter>
+
+<p>
+By doing so, we save the trouble of specifying master in every page template. If we decide to use a different master for the pages, we only need to change the application configuration. For this reason, in our blog system we will use this approach to specify master.
+</p>
+
+<com:InfoBox>
+There is an order determining which master is acutally applied when it is specified in multiple places. In particular, <tt>onPreInit()</tt> takes precedence over page template over application/page configuration. Therefore, if we specify <tt>MainLayout</tt> in the application/page configuration and we specify <tt>SpecialLayout</tt> in <tt>Contact.page</tt>, the effective master would be the latter.
+</com:InfoBox>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day1/directories.gif b/demos/blog-tutorial/protected/pages/Day1/directories.gif
new file mode 100644
index 00000000..884e15bc
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day1/directories.gif
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day1/directories2.gif b/demos/blog-tutorial/protected/pages/Day1/directories2.gif
new file mode 100644
index 00000000..edf264d0
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day1/directories2.gif
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day1/directories3.gif b/demos/blog-tutorial/protected/pages/Day1/directories3.gif
new file mode 100644
index 00000000..3451935f
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day1/directories3.gif
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day1/output.gif b/demos/blog-tutorial/protected/pages/Day1/output.gif
new file mode 100644
index 00000000..f3ece514
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day1/output.gif
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day2/ConnectDB.page b/demos/blog-tutorial/protected/pages/Day2/ConnectDB.page
new file mode 100644
index 00000000..26d8a751
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day2/ConnectDB.page
@@ -0,0 +1,8 @@
+<com:TContent ID="Main">
+
+<h1>Establishing DB Connection</h1>
+
+<p>
+</p>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day2/CreateDB.page b/demos/blog-tutorial/protected/pages/Day2/CreateDB.page
new file mode 100644
index 00000000..04dd0d90
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day2/CreateDB.page
@@ -0,0 +1,46 @@
+<com:TContent ID="Main">
+
+<h1>Creating Database</h1>
+
+<p>
+Most Web applications use database to keep data. Our blog system is not an exception. In this section, we will describe how to write database-driven pages for our blog system. We will use techniques including <a href="http://www.pradosoft.com/demos/quickstart/?page=Database.DAO">database access object (DAO)</a> and <a href="http://www.pradosoft.com/demos/quickstart/?page=Database.ActiveRecord">active record</a>.
+</p>
+
+<p>
+For tutorial purpose, we have simplified the requirements of our blog system so that it only needs to deal with user and post data. We thus create two database tables, <tt>users</tt> and <tt>posts</tt>, as shown in the following entity-relationship (ER) diagram.
+</p>
+
+<img src="<%~ ER.gif %>" />
+
+<p>
+The corresponding SQL statements for creating the tables are as follows,
+</p>
+
+<com:TTextHighlighter CssClass="source">
+CREATE TABLE users (
+ username VARCHAR(128) NOT NULL PRIMARY KEY,
+ email VARCHAR(128) NOT NULL UNIQUE,
+ password VARCHAR(128) NOT NULL,
+ first_name VARCHAR(128),
+ last_name VARCHAR(128)
+);
+
+CREATE TABLE posts (
+ post_id INTEGER NOT NULL PRIMARY KEY,
+ author VARCHAR(128) NOT NULL,
+ create_time INTEGER NOT NULL,
+ title VARCHAR(256) NOT NULL,
+ content TEXT NOT NULL,
+ CONSTRAINT "posts_fk" FOREIGN KEY ("author")
+ REFERENCES users ("username")
+ ON DELETE CASCADE
+ ON UPDATE CASCADE
+);
+</com:TTextHighlighter>
+
+<p>
+We use a SQLite 3 database to keep our data.
+</p>
+
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day2/ER.gif b/demos/blog-tutorial/protected/pages/Day2/ER.gif
new file mode 100644
index 00000000..53a7a695
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day2/ER.gif
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day2/ER.vsd b/demos/blog-tutorial/protected/pages/Day2/ER.vsd
new file mode 100644
index 00000000..52a08530
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day2/ER.vsd
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Overview.page b/demos/blog-tutorial/protected/pages/Overview.page
new file mode 100644
index 00000000..f66d0a44
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Overview.page
@@ -0,0 +1,21 @@
+<com:TContent ID="Main">
+
+<h1>Welcome to the PRADO Blog Tutorial</h1>
+
+<p>
+The purpose of this tutorial is to provide new PRADO users a step-by-step guidance on how to develop a blog system using PRADO. A more definitive guidance about PRADO is the <a href="http://www.pradosoft.com/demos/quickstart/">Quickstart Tutorial</a>, which readers can refer to when reading this tutorial.
+</p>
+
+<p>
+Readers of this tutorial are not required to have prior knowledge about PRADO. However, readers should have basic knowledge of object-oriented programming (OOP) and database programming.
+</p>
+
+<p>
+This tutorial is organized in a day-by-day fashion. Each day new PRADO concepts and techniques are introduced, and new features are added to the blog system. At the end, we will complete a simple blog application that meets the <a href="?page=Requirements">initial requirements</a>.
+</p>
+
+<p>
+In order to follow the tutorial to create and run the <a href="samples/">day-by-day examples</a>, readers should have access to a Web server installed with <b>PHP 5.1.0+</b> and <b>PRADO 3.1+</b>. Instructions for installing PRADO can be found at <a href="http://www.pradosoft.com/demos/quickstart/?page=GettingStarted.Installation">pradosoft.com</a>.
+</p>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Requirements.page b/demos/blog-tutorial/protected/pages/Requirements.page
new file mode 100644
index 00000000..497eba90
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Requirements.page
@@ -0,0 +1,38 @@
+<com:TContent ID="Main">
+
+<h1>Requirement Analysis</h1>
+
+<p>
+This page lists the requirements for the blog system that we are going to develop in this tutorial using PRADO. We are not including some popular blog features here (e.g. commenting, posts organizing, calendar, etc.), because we want to keep our tutorial short enough and we believe these features are easy to be added after you finish reading this tutorial.
+</p>
+
+<p>
+In general, the blog system should allow users to read blogs and authenticated users to publish blogs. It should separate presentation and logic, and it should support changing themes.
+</p>
+
+<h2>Post Management</h2>
+<ul>
+<li>The system shall allow listing posts by their creaing time in descending order with paging.</li>
+<li>The system shall allow viewing the detail of a selected post.</li>
+<li>The system shall allow creating a new post by an authenticated user.</li>
+<li>The system shall allow updating an existing post by its author or administrator.</li>
+<li>The system shall allow deleting an existing post by its author or administrator.</li>
+</ul>
+
+<h2>User Management</h2>
+<ul>
+<li>The system shall allow authenticating and authorizing users.</li>
+<li>The system shall allow the administrator to list all user accounts.</li>
+<li>The system shall allow the administrator to create a new user account.</li>
+<li>The system shall allow the administrator or the account holder to update an existing account.</li>
+<li>The system shall allow the administrator to delete a user account.</li>
+</ul>
+
+<h2>System Maintenance</h2>
+<ul>
+<li>The system shall provide a mechanism to collect users' feedback.</li>
+<li>The system shall be flexible enough to allow adding new portlets in future.</li>
+<li>The system shall provide ease of using a different theme which changes the styles of the UI elements.</li>
+</ul>
+
+</com:TContent> \ No newline at end of file