summaryrefslogtreecommitdiff
path: root/demos/blog-tutorial/protected/pages
diff options
context:
space:
mode:
authorxue <>2007-06-29 17:41:20 +0000
committerxue <>2007-06-29 17:41:20 +0000
commit4a9dd5c8513ed96d1e0cf43e370b170dc38fb502 (patch)
treef41bbf25ac5bbc8d0b656c3e7c087e40b09b38b1 /demos/blog-tutorial/protected/pages
parent2d266a7994c57e9a13cccecacf8940e11263614f (diff)
finished blog-tutorial.
Diffstat (limited to 'demos/blog-tutorial/protected/pages')
-rw-r--r--demos/blog-tutorial/protected/pages/Day1/ShareLayout.page6
-rw-r--r--demos/blog-tutorial/protected/pages/Day4/CreateListPost.page2
-rw-r--r--demos/blog-tutorial/protected/pages/Day4/CreateNewPost.page3
-rw-r--r--demos/blog-tutorial/protected/pages/Day4/Overview.page2
-rw-r--r--demos/blog-tutorial/protected/pages/Day5/ErrorLogging.page159
-rw-r--r--demos/blog-tutorial/protected/pages/Day5/Performance.page67
-rw-r--r--demos/blog-tutorial/protected/pages/Day5/Summary.page36
-rw-r--r--demos/blog-tutorial/protected/pages/Day5/UseTheme.page138
-rw-r--r--demos/blog-tutorial/protected/pages/Day5/output.gifbin0 -> 4282 bytes
-rw-r--r--demos/blog-tutorial/protected/pages/Day5/output2.gifbin0 -> 7798 bytes
-rw-r--r--demos/blog-tutorial/protected/pages/Day5/output3.gifbin0 -> 5190 bytes
-rw-r--r--demos/blog-tutorial/protected/pages/Overview.page6
12 files changed, 410 insertions, 9 deletions
diff --git a/demos/blog-tutorial/protected/pages/Day1/ShareLayout.page b/demos/blog-tutorial/protected/pages/Day1/ShareLayout.page
index d6c4d29f..9cd0410b 100644
--- a/demos/blog-tutorial/protected/pages/Day1/ShareLayout.page
+++ b/demos/blog-tutorial/protected/pages/Day1/ShareLayout.page
@@ -28,6 +28,7 @@ For the moment, <tt>MainLayout</tt> only contains a simple header and a footer,
&lt;com:THead />
<body>
&lt;com:TForm>
+<div id="page">
<div id="header">
<h1>My PRADO Blog</h1>
@@ -41,6 +42,7 @@ For the moment, <tt>MainLayout</tt> only contains a simple header and a footer,
&lt;%= PRADO::poweredByPrado() %>
</div>
+</div>
&lt;/com:TForm>
</body>
</html>
@@ -113,7 +115,7 @@ Besides <tt>&lt;com:TContent&gt;</tt>, we also see another new tag <tt>&lt;%@ %&
</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.
+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>
@@ -140,7 +142,7 @@ class Contact extends TPage
parent::onPreInit($param);
$this->MasterClass='Path.To.NewLayout';
}
-
+
// ...
}
?>
diff --git a/demos/blog-tutorial/protected/pages/Day4/CreateListPost.page b/demos/blog-tutorial/protected/pages/Day4/CreateListPost.page
index e25c0609..1dada650 100644
--- a/demos/blog-tutorial/protected/pages/Day4/CreateListPost.page
+++ b/demos/blog-tutorial/protected/pages/Day4/CreateListPost.page
@@ -146,6 +146,7 @@ The expression <tt>$this->Data</tt> refers to the data item passed to the repeat
</p>
<com:TTextHighlighter CssClass="source" Language="prado">
+<div class="post-box">
<h3>
&lt;com:THyperLink Text="&lt;%# $this->Data->title %>"
NavigateUrl="&lt;%# $this->Service->constructUrl('posts.ReadPost',array('id'=>$this->Data->post_id)) %>" />
@@ -161,6 +162,7 @@ Time:
<p>
&lt;com:TLiteral Text="&lt;%# $this->Data->content %>" />
</p>
+</div>
</com:TTextHighlighter>
<h3>Creating Renderer Class</h3>
diff --git a/demos/blog-tutorial/protected/pages/Day4/CreateNewPost.page b/demos/blog-tutorial/protected/pages/Day4/CreateNewPost.page
index 5011c346..9020c517 100644
--- a/demos/blog-tutorial/protected/pages/Day4/CreateNewPost.page
+++ b/demos/blog-tutorial/protected/pages/Day4/CreateNewPost.page
@@ -25,7 +25,8 @@ As the number of our pages expands, we would like to modify <tt>MainLayout</tt>
<com:TTextHighlighter CssClass="source" Language="prado">
<div id="footer">
-<a href="&lt;%= $this->Service->DefaultPageUrl %>">Home</a>
+&lt;com:THyperLink Text="Home"
+ NavigateUrl="&lt;%= $this->Service->DefaultPageUrl %>" />
&lt;com:THyperLink Text="New Post"
NavigateUrl="&lt;%= $this->Service->constructUrl('posts.NewPost') %>"
diff --git a/demos/blog-tutorial/protected/pages/Day4/Overview.page b/demos/blog-tutorial/protected/pages/Day4/Overview.page
index cbff07c5..74e691e3 100644
--- a/demos/blog-tutorial/protected/pages/Day4/Overview.page
+++ b/demos/blog-tutorial/protected/pages/Day4/Overview.page
@@ -21,6 +21,6 @@ According to the requirements, we need to create the following pages organized u
After finishing this section, we shall expect to see the following directories and files:
</p>
-<img src="%~ directories.gif %>" class="output" />
+<img src="<%~ directories.gif %>" class="output" />
</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day5/ErrorLogging.page b/demos/blog-tutorial/protected/pages/Day5/ErrorLogging.page
new file mode 100644
index 00000000..52f7ef54
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day5/ErrorLogging.page
@@ -0,0 +1,159 @@
+<com:TContent ID="Main">
+
+<h1>Error Handling and Logging</h1>
+
+<p>
+If we try to access the URL <tt>http://hostname/blog/index.php?page=EditPost&id=100</tt>, we will see the following error page because the post with ID 100 does not exist in our blog system yet. We would like to customize this error page so that it looks more consistent with the other blog pages in layout. We also want to log this kind of errors to study user behaviors. In this section, we will accomplish these two tasks.
+</p>
+
+<img src="<%~ output2.gif %>" class="output" />
+
+<com:InfoBox>
+An important task in a Web application is <a href="http://www.pradosoft.com/demos/quickstart/?page=Advanced.Error">error handling</a> which is often associated <a href="http://www.pradosoft.com/demos/quickstart/?page=Advanced.Logging">logging</a>. There are two types of errors that may occur in a PRADO application: those caused by developers and those by end-users. The former should be resolved before the application is put into production, while the latter are usually within the initial design scope and should be handled nicely (e.g. log the error and display a special page instructing the end-user what to do next.) PRADO implements a very flexible yet powerful framework for error handling and logging.
+</com:InfoBox>
+
+
+<h2>Customizing Error Handling</h2>
+
+<p>
+PRADO implicitly loads a <tt>TErrorHandler</tt> module to handle errors. We would like to customize this module so that our blog system can display a customized page for errors caused by end-users. We thus modify the application configuration as follows:
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="xml">
+......
+<modules>
+ ......
+ <module class="Application.BlogErrorHandler" />
+ ......
+</modules>
+......
+</com:TTextHighlighter>
+
+<p>
+The class <tt>BlogErrorHandler</tt> as specified in the above is a new error handler module that we will create next. It extends and replaces the default <tt>TErrorHandler</tt> module.
+</p>
+
+<p>
+We create a file named <tt>protected/BlogErrorHandler.php</tt> as follows. The class <tt>BlogErrorHandler</tt> overrides two methods of <tt>TErrorHandler</tt>:
+</p>
+<ul>
+ <li><tt>getErrorTemplate()</tt> - this method returns the template string used for displaying a particular user error.</li>
+ <li><tt>handleExternalError()</tt> - this method is invoked when a user error occurs and displays the error.</li>
+</ul>
+<com:TTextHighlighter CssClass="source" Language="php">
+Prado::using('System.Exceptions.TErrorHandler');
+Prado::using('Application.BlogException');
+
+class BlogErrorHandler extends TErrorHandler
+{
+ /**
+ * Retrieves the template used for displaying external exceptions.
+ * This method overrides the parent implementation.
+ */
+ protected function getErrorTemplate($statusCode,$exception)
+ {
+ // use our own template for BlogException
+ if($exception instanceof BlogException)
+ {
+ // get the path of the error template file: protected/error.html
+ $templateFile=Prado::getPathOfNamespace('Application.error','.html');
+ return file_get_contents($templateFile);
+ }
+ else // otherwise use the template defined by PRADO
+ return parent::getErrorTemplate($statusCode,$exception);
+ }
+
+ /**
+ * Handles external error caused by end-users.
+ * This method overrides the parent implementation.
+ * It is invoked by PRADO when an external exception is thrown.
+ */
+ protected function handleExternalError($statusCode,$exception)
+ {
+ // log the error (only for BlogException)
+ if($exception instanceof BlogException)
+ Prado::log($exception->getErrorMessage(),TLogger::ERROR,'BlogApplication');
+ // call parent implementation to display the error
+ parent::handleExternalError($statusCode,$exception);
+ }
+}
+</com:TTextHighlighter>
+
+<p>
+In the above, we specify that when a <tt>BlogException</tt> is thrown, we use a new template <tt>protected/error.html</tt> to display the error. Therefore, we need to create the <tt>BlogException</tt> class and replace all the occurances of <tt>THttpException</tt> in our code (such as <a href="?page=Day3.CreateEditUser">EditUser</a> and <a href="?page=Day4.CreateReadPost">ReadPost</a> pages). We also need to create the error template <tt>protected/error.html</tt>. The <tt>BlogException</tt> class extends <tt>THttpException</tt> and is empty. The class file is saved as <tt>protected/BlogException.php</tt>.
+
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="php">
+class BlogException extends THttpException
+{
+}
+</com:TTextHighlighter>
+
+<p>
+Below is the content in our error template <tt>protected/error.html</tt>. Note, the template is not a PRADO template because it only recognizes very limited number of tokens, such as <tt>%%ErrorMessage%%</tt>, <tt>%%ServerAdmin%%</tt>.
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="xml">
+<html>
+<head>
+<title>%%ErrorMessage%%</title>
+</head>
+<body>
+<div id="page">
+<div id="header">
+<h1>My PRADO Blog</h1>
+</div>
+<div id="main">
+<p style="color:red">%%ErrorMessage%%</p>
+<p>
+The above error happened when the server was processing your request.
+</p>
+<p>
+If you think this is a server error, please contact the <a href="mailto:%%ServerAdmin%%">webmaster</a>.
+</p>
+</div>
+</body>
+</html>
+</com:TTextHighlighter>
+
+
+<h2>Logging Errors</h2>
+
+<p>
+In the <tt>handleExternalError()</tt> method of <tt>BlogErrorHandler</tt>, we invoke <tt>Prado::log()</tt> to log the error if it is of type <tt>BlogException</tt>. The error is logged in memory. To save the logs into permanent medium such as file or database, we need to enable appropriate error logging routes. This is done in the application configuration as follows:
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="xml">
+......
+<modules>
+ ......
+ <module id="log" class="System.Util.TLogRouter">
+ <route class="TFileLogRoute" Categories="BlogApplication" />
+ </module>
+ ......
+</modules>
+......
+</com:TTextHighlighter>
+
+<p>
+In the above, we add a log route that saves logs into a file. We also specify the category filter as <tt>BlogApplication</tt> such that only the log messages of the selected categories are saved. This helps reduce the size of the log file and also improves its readability.
+</p>
+
+<h2>Testing</h2>
+<p>
+To see how our blog systems reponds to an invalid user request, we test the URL <tt>http://hostname/blog/index.php?page=posts.ReadPost&id=100</tt>. We shall see the following error page which is different from what we saw earlier on.
+</p>
+
+<img src="<%~ output3.gif %>" class="output" />
+
+<p>
+If we search under the directory <tt>protected/runtime</tt>, we will find a file named <tt>prado.log</tt>. This is the log file that we just configured to save the error messages. The file may contain contents like the following,
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="text">
+Jun 28 22:15:27 [Error] [BlogApplication] Unable to find the specified post.
+Jun 29 08:42:57 [Error] [BlogApplication] Unable to find the specified post.
+</com:TTextHighlighter>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day5/Performance.page b/demos/blog-tutorial/protected/pages/Day5/Performance.page
new file mode 100644
index 00000000..cbaae7e4
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day5/Performance.page
@@ -0,0 +1,67 @@
+<com:TContent ID="Main">
+
+<h1>Performance Tuneup</h1>
+
+<p>
+Before we deploy our blog system, we would like to tuneup the system performance.
+</p>
+
+<h2>Changing Application Mode</h2>
+
+<p>
+A PRADO application may be configured to run in different mode. By default, it runs in debug mode which generates a lot of log messages and in case of errors, it displays full call stack of the error places. Such behavior is preferrable during development, but not so if the system is in production. To change the application mode from <tt>Debug</tt> to <tt>Normal</tt> (meaning production mode), we modify the application configuration as follows:
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="xml">
+<?xml version="1.0" encoding="utf-8"?>
+<application id="blog" mode="Normal">
+ ......
+</application>
+</com:TTextHighlighter>
+
+<h2>Enabling Caching</h2>
+
+<p>
+There are a lot of parsing work involved in a PRADO application: configuration XMLs, templates, theme skins, etc. For every user request, PRADO needs to redo the parsing. To save this effort, we can enable caching. To do so, we modify the application configuration as follows,
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="xml">
+......
+<modules>
+ ......
+ <module id="cache" class="System.Caching.TDbCache" />
+ ......
+</modules>
+......
+</com:TTextHighlighter>
+
+<p>
+Now after accessing any page in our blog system, we shall be able to find a file named <tt>sqlite3.cache</tt>. This is the database file that keeps the parsed page templates, configurations, etc.
+</p>
+
+<com:InfoBox>
+The cache module we just enabled uses database as persistent cache medium. PRADO also has other cache modules using faster cache medium, such as <tt>TMemCache</tt>, <tt>TAPCCache</tt>. They require installation of the corresponding PHP extensions.
+</com:InfoBox>
+
+
+<h2>Using <tt>pradolite.php</tt></h2>
+
+<p>
+Running a PRADO page involves including tens of PHP files, which could be very time-consuming. These files also carry a lot of comments for generating user-friendly API documentation. In order to reduce this cost, we modify <tt>index.php</tt> and replace the inclusion of <tt>prado.php</tt> with <tt>pradolite.php</tt>. The latter is a big file generated by merging necessary PRADO code files and stripping out comments. We thus modify <tt>index.php</tt> as follows,
+</p>
+
+<h2>Other Techniques</h2>
+
+<p>
+There are other techniques to further improve the performance of a PRADO application. According to our experience, one of the bottlenecks in a Web application is the database tier. The database queries often take a long time to complete, which greatly degrades the response time of a page request. Caching is the main solution for this problem. The cache module enabled in our application configuration can also be used for this purpose.
+</p>
+
+<p>
+For a page that is relatively stable yet frequently accessed, <a href="http://www.pradosoft.com/demos/quickstart/?page=Controls.OutputCache">output caching</a> should be considered. Output caching caches the HTML output of selected portions of a page. This may improve the performance of the cached pages significantly.
+</p>
+
+<p>
+Server caching techniques are proven to be very effective in improving the performance of PRADO applications. For example, we have observed that by using Zend Optimizer, the RPS (request per second) of a PRADO application can be increased by more than ten times. Of course, this is at the cost of stale output, while PRADO's caching techniques always ensure the correctness of the output.
+</p>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day5/Summary.page b/demos/blog-tutorial/protected/pages/Day5/Summary.page
new file mode 100644
index 00000000..3ea350eb
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day5/Summary.page
@@ -0,0 +1,36 @@
+<com:TContent ID="Main">
+
+<h1>Summary</h1>
+
+<p>
+We finally can deploy our blog system. To do so, we only need to copy the whole <tt>blog</tt> directory to the target Web directory. We may need to modify <tt>index.php</tt> so that it can locate the correct path where the PRADO framework is installed.
+</p>
+
+<p>
+So we have completed our blog system. The process may seem not trivial because it takes us nearly five days to reach here. However, as we stated at the beginning, the main purpose of this tutorial is to help PRADO developers get familiar with the commonly used PRADO techniques. The tutorial is not meant to finish a blog system in five minutes and then we learn nothing.
+</p>
+
+<p>
+In summary, developing a DB-driven PRADO application involves the following steps:
+</p>
+<ol>
+ <li>Design and create database</li>
+ <li>Create initial application layout using <tt>prado-cli</tt></li>
+ <li>Set up error handling process to deal with end-user errors</li>
+ <li>Create and set up themes</li>
+ <li>Design and create master classes to share common page layouts</li>
+ <li>Create database classes and set up database connections</li>
+ <li>Design and create various pages</li>
+ <li>Test and tune up performance</li>
+ <li>Deploy the application</li>
+</ol>
+
+<p>
+Unlike the order in our tutorial, error handling and creating theme are done earlier in the above process. This is because they often require global change in class code and template. For example, we need to replace <tt>THttpException</tt> with <tt>BlogException</tt> in our tutorial. If we define stylesheet classes earlier, we could more easily use them when creating page templates.
+</p>
+
+<p>
+As a final tip, try to think in object-oriented way during the design and implementation. Use class inheritance and composition wisely, and you will find the whole project is easier to be developed in parallel by multiple developers. The code also has more chance to be reused so that future projects can be finished much faster.
+</p>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day5/UseTheme.page b/demos/blog-tutorial/protected/pages/Day5/UseTheme.page
new file mode 100644
index 00000000..21bc9d81
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day5/UseTheme.page
@@ -0,0 +1,138 @@
+<com:TContent ID="Main">
+
+<h1>Using Themes and Skins</h1>
+
+<p>
+PRADO has intrinsic support for <a href="http://www.pradosoft.com/demos/quickstart/?page=Advanced.Themes">themes</a>. By using themes, we can better separate logic and presentation, and we can also change the overall appearance of our blog system more easily.
+</p>
+
+<h2>Creating Theme</h2>
+
+<p>
+We first create a new directory <tt>themes</tt>. This is the parent directory of all themes for a particular PRADO application. Any subdirectory under this directory will become a theme whose name is the subdirectory name.
+</p>
+
+<p>
+To create a theme named <tt>Basic</tt>, we create a subdirectory <tt>theme/Basic</tt>. Under this directory, we may place theme-dependent stylesheet files, Javascript files, images, and skin files.
+</p>
+
+<com:InfoBox>
+The <tt>themes</tt> directory must be Web-accessible, like the <tt>assets</tt> directory. Do not place sensitive data files under this directory. You can change the name or location of this directory by configuring the <a href="http://www.pradosoft.com/docs/classdoc/TThemeManager">TThemeManager</a> module in the application configuration.
+</com:InfoBox>
+
+
+<h3>Creating Stylesheet File</h2>
+
+<p>
+Under the <tt>themes/Basic</tt> directory, we create a CSS stylesheet file named <tt>style.css</tt>. When a page uses this theme, PRADO will automatically import this stylesheet to the page. The same occurs for Javascript files.
+</p>
+
+<p>
+The CSS file is shown as follows.
+</p>
+
+<com:TTextHighlighter CssClass="source">
+body {
+ font-family: verdana, 'trebuchet ms', sans-serif;
+ font-size: 10pt;
+ background: white;
+}
+#page {
+ margin: 0 auto 0 auto;
+ width: 600px;
+}
+#footer {
+ text-align: center;
+ margin-top: 10px;
+ padding: 10px;
+ border-top: 1px solid silver;
+}
+.post-box {
+ margin-bottom: 10px;
+ padding: 5px;
+}
+.post-box h3 {
+ padding: 5px;
+ font-size: 13pt;
+ background: lightgray;
+}
+.post-box a {
+ color: black;
+ text-decoration: none;
+}
+.post-box a:hover {
+ color: red;
+}
+</com:TTextHighlighter>
+
+
+<h3>Creating Skin File</h2>
+
+<p>
+We use skins to initialize the properties of PRADO controls. Skins are stored as skin files (suffix name <tt>.skin</tt>) under a theme directory. Each skin file can contain multiple skins for one or several types of control.
+</p>
+
+<p>
+As a test, we will try to create a skin that changes the background color of the link buttons in the page footer. We create a file named <tt>button.skin</tt> under the theme directory <tt>themes/Basic</tt>.
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="prado">
+&lt;com:THyperLink SkinID="MainMenu" BackColor="lightgreen" />
+</com:TTextHighlighter>
+
+<p>
+The <tt>button.skin</tt> skin file contains only one skin for <tt>THyperLink</tt> controls whose <tt>SkinID</tt> property is <tt>MainMenu</tt>. The skin sets the background color of the control to be light-green.
+</p>
+
+<p>
+Accordingly, we need to modify <tt>protected/common/MainLayout.tpl</tt> so that the link buttons in the footer use <tt>MainMenu</tt> as their <tt>SkinID</tt>.
+</p>
+<com:TTextHighlighter CssClass="source" Language="prado">
+......
+<div id="footer">
+......
+&lt;com:THyperLink Text="Home" SkinID="MainMenu"
+ NavigateUrl="&lt;%= $this->Service->DefaultPageUrl %>" />
+
+&lt;com:THyperLink Text="New Post" SkinID="MainMenu"
+ NavigateUrl="&lt;%= $this->Service->constructUrl('posts.NewPost') %>"
+ Visible="&lt;%= !$this->User->IsGuest %>" />
+......
+</div>
+......
+</com:TTextHighlighter>
+
+<com:InfoBox>
+The syntax for skin files is very similar to that of PRADO templates. Each <tt>&lt;com:&gt;</tt> tag defines a skin for a particular type of control. PRADO automatically aggregates all skin files in a theme and applies them when a themed page is being rendered.
+</com:InfoBox>
+
+
+<h2>Using Theme</h2>
+
+<p>
+To use the theme we just created, we modify the application configuration as follows. As we see, the <tt>Theme</tt> property for all pages is set as <tt>Basic</tt>, the name of the theme we created.
+</p>
+
+<com:TTextHighlighter CssClass="source" Language="xml">
+......
+ <services>
+ <service id="page" class="TPageService" DefaultPage="posts.ListPost">
+ <pages MasterClass="Application.layouts.MainLayout" Theme="Basic" />
+ </service>
+ </services>
+......
+</com:TTextHighlighter>
+
+<com:InfoBox>
+It is possible to specify different themes for different pages, and this can be done either in application/page configurations or programmatically (note <tt>Theme</tt> a page property). For the latter, it is must be done in <tt>onPreInit()</tt> method of the page because PRADO applies a theme to a page early in the page lifecycle.
+</com:InfoBox>
+
+
+<h2>Testing</h2>
+<p>
+To see how our blog pages look like, visit the URL <tt>http://hostname/blog/index.php</tt>. We shall see the font, layout, borders are changed in the page. Also, the link buttons in the footer have light-green background.
+</p>
+
+<img src="<%~ output.gif %>" class="output" />
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/blog-tutorial/protected/pages/Day5/output.gif b/demos/blog-tutorial/protected/pages/Day5/output.gif
new file mode 100644
index 00000000..67bd18a3
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day5/output.gif
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day5/output2.gif b/demos/blog-tutorial/protected/pages/Day5/output2.gif
new file mode 100644
index 00000000..16c81704
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day5/output2.gif
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Day5/output3.gif b/demos/blog-tutorial/protected/pages/Day5/output3.gif
new file mode 100644
index 00000000..6879bbdf
--- /dev/null
+++ b/demos/blog-tutorial/protected/pages/Day5/output3.gif
Binary files differ
diff --git a/demos/blog-tutorial/protected/pages/Overview.page b/demos/blog-tutorial/protected/pages/Overview.page
index 9dbf6dc0..bc895a33 100644
--- a/demos/blog-tutorial/protected/pages/Overview.page
+++ b/demos/blog-tutorial/protected/pages/Overview.page
@@ -2,16 +2,12 @@
<h1>Welcome to the PRADO Blog Tutorial</h1>
-<com:NoteBox>
-This tutorial is NOT completed yet. Please let us know you suggestions about this tutorial on <a href="http://www.pradosoft.com/forum/index.php?board=5.0">our forum</a>. Thanks!
-</com:NoteBox>
-
<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. 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. For a more definitive guidance about PRADO, readers may refer to the <a href="http://www.pradosoft.com/demos/quickstart/">Quickstart Tutorial</a>.
</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 a list of <a href="?page=Requirements">initial requirements</a>.
+This tutorial is organized in a day-by-day fashion. Each day new PRADO concepts and techniques are introduced, and new features of the blog system are implemented. At the end, we will complete a simple blog application that meets a list of <a href="?page=Requirements">initial requirements</a>.
</p>
<p>