From 0da331cb45cf202bf7fbd519c8d65f5956c85b2b Mon Sep 17 00:00:00 2001
From: jrags <>
Date: Wed, 21 Feb 2007 16:31:50 +0000
Subject: Converted BlogDataModule Record classes to use active record, also
 changed the data module to load the database into the active record handler

---
 .../protected/App_Controls/BlogException.php       |  31 +
 .../activeblog/protected/App_Controls/BlogPage.php |  49 ++
 .../activeblog/protected/App_Controls/messages.txt |  12 +
 demos/activeblog/protected/App_Data/Settings.xml   |  18 +
 demos/activeblog/protected/App_Data/blog.db        | Bin 0 -> 19456 bytes
 .../protected/App_Modules/BlogDataModule.php       | 633 +++++++++++++++++++++
 .../protected/App_Modules/BlogErrorHandler.php     |  46 ++
 .../activeblog/protected/App_Modules/BlogUser.php  |  60 ++
 .../protected/App_Modules/BlogUserManager.php      |  73 +++
 demos/activeblog/protected/App_Modules/schema.sql  |  76 +++
 demos/activeblog/protected/App_Pages/Home.php      |  25 +-
 demos/activeblog/protected/application.xml         |  42 +-
 12 files changed, 1036 insertions(+), 29 deletions(-)
 create mode 100644 demos/activeblog/protected/App_Controls/BlogException.php
 create mode 100644 demos/activeblog/protected/App_Controls/BlogPage.php
 create mode 100644 demos/activeblog/protected/App_Controls/messages.txt
 create mode 100644 demos/activeblog/protected/App_Data/Settings.xml
 create mode 100644 demos/activeblog/protected/App_Data/blog.db
 create mode 100644 demos/activeblog/protected/App_Modules/BlogDataModule.php
 create mode 100644 demos/activeblog/protected/App_Modules/BlogErrorHandler.php
 create mode 100644 demos/activeblog/protected/App_Modules/BlogUser.php
 create mode 100644 demos/activeblog/protected/App_Modules/BlogUserManager.php
 create mode 100644 demos/activeblog/protected/App_Modules/schema.sql

(limited to 'demos')

diff --git a/demos/activeblog/protected/App_Controls/BlogException.php b/demos/activeblog/protected/App_Controls/BlogException.php
new file mode 100644
index 00000000..2501fa49
--- /dev/null
+++ b/demos/activeblog/protected/App_Controls/BlogException.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * BlogException class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id: BlogException.php 1398 2006-09-08 19:31:03Z xue $
+ */
+
+/**
+ * BlogException class
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ */
+class BlogException extends THttpException
+{
+	/**
+	 * @return string path to the error message file
+	 */
+	protected function getErrorMessageFile()
+	{
+		return dirname(__FILE__).'/messages.txt';
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/demos/activeblog/protected/App_Controls/BlogPage.php b/demos/activeblog/protected/App_Controls/BlogPage.php
new file mode 100644
index 00000000..61f7492d
--- /dev/null
+++ b/demos/activeblog/protected/App_Controls/BlogPage.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * BlogPage class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id: BlogPage.php 1509 2006-11-25 20:51:43Z xue $
+ */
+
+/**
+ * BlogPage class
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ */
+class BlogPage extends TPage
+{
+	public function onPreInit($param)
+	{
+		parent::onPreInit($param);
+		//		$this->setTheme($this->getApplication()->Parameters['ThemeName']);
+	}
+
+	public function getDataAccess()
+	{
+		return $this->getApplication()->getModule('data');
+	}
+
+	public function gotoDefaultPage()
+	{
+		$this->gotoPage($this->getService()->DefaultPage);
+	}
+
+	public function gotoPage($pagePath,$getParameters=null)
+	{
+		$this->getResponse()->redirect($this->getService()->constructUrl($pagePath,$getParameters,false));
+	}
+
+	public function reportError($errorCode)
+	{
+		$this->gotoPage('ErrorReport',array('id'=>$errorCode));
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/demos/activeblog/protected/App_Controls/messages.txt b/demos/activeblog/protected/App_Controls/messages.txt
new file mode 100644
index 00000000..2a18aac2
--- /dev/null
+++ b/demos/activeblog/protected/App_Controls/messages.txt
@@ -0,0 +1,12 @@
+blogdatamodule_dbconnect_failed			= Unable to connect to database: {0}
+blogdatamodule_dbfile_invalid			= BlogDataModule.DbFile='{0}' is invalid.
+blogdatamodule_createdatabase_failed	= BlogDataModule failed to create database when executing SQL: {1}. Last SQL error is: {0}.
+blogdatamodule_query_failed				= Failed to execute SQL: {1}. Last SQL error is: {0}.
+
+newuser_registration_disallowed			= The Weblog system is running in single user mode and does not allow new user registration.
+profile_edit_disallowed					= You are not allowed to modify user profile {0}.
+profile_id_invalid						= Unable to retrieve user profile {0}.
+
+post_id_invalid							= Unable to retrieve post {0}.
+post_edit_disallowed					= You are not allowed to modify post {0}.
+post_view_disallowed					= You are not allowed to read post {0}.
\ No newline at end of file
diff --git a/demos/activeblog/protected/App_Data/Settings.xml b/demos/activeblog/protected/App_Data/Settings.xml
new file mode 100644
index 00000000..d8b3c92b
--- /dev/null
+++ b/demos/activeblog/protected/App_Data/Settings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<parameters>
+    <parameter id="SiteTitle" value="My Blog" />
+    <parameter id="SiteSubtitle" value="A Prado-driven weblog" />
+    <parameter id="SiteOwner" value="Prado User" />
+    <parameter id="AdminEmail" value="admin@example.com" />
+    <parameter id="MultipleUser" value="false" />
+    <parameter id="AccountApproval" value="false" />
+    <parameter id="PostPerPage" value="6" />
+    <parameter id="RecentComments" value="6" />
+    <parameter id="PostApproval" value="false" />
+    <parameter id="ThemeName" value="Default" />
+    <parameter id="SiteOffline" value="False"/>
+ 	<!-- Are we allowing signups -->
+	<parameter id="AllowRegister" value="True"/>
+	<!-- Email Controls -->
+	<parameter id="DisableEmails" value="False"/>
+</parameters>
\ No newline at end of file
diff --git a/demos/activeblog/protected/App_Data/blog.db b/demos/activeblog/protected/App_Data/blog.db
new file mode 100644
index 00000000..ef3dbbfc
Binary files /dev/null and b/demos/activeblog/protected/App_Data/blog.db differ
diff --git a/demos/activeblog/protected/App_Modules/BlogDataModule.php b/demos/activeblog/protected/App_Modules/BlogDataModule.php
new file mode 100644
index 00000000..5065d239
--- /dev/null
+++ b/demos/activeblog/protected/App_Modules/BlogDataModule.php
@@ -0,0 +1,633 @@
+<?php
+/**
+ * BlogDataModule class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id: BlogDataModule.php 1398 2006-09-08 19:31:03Z xue $
+ */
+
+/**
+ * BlogDataModule class
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ */
+class BlogDataModule extends TModule
+{
+	const DB_FILE_EXT='.db';
+	const DEFAULT_DB_FILE='Application.App_Data.blog';
+	private $_db=null;
+	private $_dbFile=null;
+
+	public function init($config)
+	{
+		$this->connectDatabase();
+	}
+
+	public function getDbFile()
+	{
+		if($this->_dbFile===null)
+		$this->_dbFile=Prado::getPathOfNamespace(self::DEFAULT_DB_FILE,self::DB_FILE_EXT);
+		return $this->_dbFile;
+	}
+
+	public function setDbFile($value)
+	{
+		if(($this->_dbFile=Prado::getPathOfNamespace($value,self::DB_FILE_EXT))===null)
+		throw new BlogException(500,'blogdatamodule_dbfile_invalid',$value);
+	}
+
+	protected function createDatabase()
+	{
+		$schemaFile=dirname(__FILE__).'/schema.sql';
+		$statements=explode(';',file_get_contents($schemaFile));
+		foreach($statements as $statement)
+		{
+			if(trim($statement)!=='')
+			{
+				if(@sqlite_query($this->_db,$statement)===false)
+				throw new BlogException(500,'blogdatamodule_createdatabase_failed',sqlite_error_string(sqlite_last_error($this->_db)),$statement);
+			}
+		}
+	}
+
+	protected function connectDatabase()
+	{
+		$dbFile=$this->getDbFile();
+		$newDb=!is_file($dbFile);
+		$error='';
+
+		//create a connection and give it to the ActiveRecord manager.
+		$dsn = 'sqlite2:'.$dbFile; //Postgres SQL
+		$conn = new TDbConnection($dsn);
+		TActiveRecordManager::getInstance()->setDbConnection($conn);
+
+		if($newDb)
+		$this->createDatabase();
+	}
+
+	protected function generateModifier($filter,$orderBy,$limit)
+	{
+		$modifier='';
+		if($filter!=='')
+		$modifier=' WHERE '.$filter;
+		if($orderBy!=='')
+		$modifier.=' ORDER BY '.$orderBy;
+		if($limit!=='')
+		$modifier.=' LIMIT '.$limit;
+		return $modifier;
+	}
+
+	public function query($sql)
+	{
+		if(($result=@sqlite_query($this->_db,$sql))!==false)
+		return $result;
+		else
+		throw new BlogException(500,'blogdatamodule_query_failed',sqlite_error_string(sqlite_last_error($this->_db)),$sql);
+	}
+
+	protected function populateUserRecord($row)
+	{
+		$userRecord=new UserRecord;
+		$userRecord->ID=(integer)$row['id'];
+		$userRecord->Name=$row['name'];
+		$userRecord->FullName=$row['full_name'];
+		$userRecord->Role=(integer)$row['role'];
+		$userRecord->Password=$row['passwd'];
+		$userRecord->VerifyCode=$row['vcode'];
+		$userRecord->Email=$row['email'];
+		$userRecord->CreateTime=(integer)$row['reg_time'];
+		$userRecord->Status=(integer)$row['status'];
+		$userRecord->Website=$row['website'];
+		return $userRecord;
+	}
+
+	public function queryUsers($filter='',$orderBy='',$limit='')
+	{
+		if($filter!=='')
+		$filter='WHERE '.$filter;
+		$sql="SELECT * FROM tblUsers $filter $orderBy $limit";
+		$result=$this->query($sql);
+		$rows=sqlite_fetch_all($result,SQLITE_ASSOC);
+		$users=array();
+		foreach($rows as $row)
+		$users[]=$this->populateUserRecord($row);
+		return $users;
+	}
+
+	public function queryUserCount($filter)
+	{
+		if($filter!=='')
+		$filter='WHERE '.$filter;
+		$sql="SELECT COUNT(id) AS user_count FROM tblUsers $filter";
+		$result=$this->query($sql);
+		if(($row=sqlite_fetch_array($result,SQLITE_ASSOC))!==false)
+		return $row['user_count'];
+		else
+		return 0;
+	}
+
+	public function queryUserByID($id)
+	{
+		$sql="SELECT * FROM tblUsers WHERE id=$id";
+		$result=$this->query($sql);
+		if(($row=sqlite_fetch_array($result,SQLITE_ASSOC))!==false)
+		return $this->populateUserRecord($row);
+		else
+		return null;
+	}
+
+	public function queryUserByName($name)
+	{
+		$name=sqlite_escape_string($name);
+		$sql="SELECT * FROM tblUsers WHERE name='$name'";
+		$result=$this->query($sql);
+		if(($row=sqlite_fetch_array($result,SQLITE_ASSOC))!==false)
+		return $this->populateUserRecord($row);
+		else
+		return null;
+	}
+
+	public function insertUser($user)
+	{
+		$name=sqlite_escape_string($user->Name);
+		$fullName=sqlite_escape_string($user->FullName);
+		$passwd=sqlite_escape_string($user->Password);
+		$email=sqlite_escape_string($user->Email);
+		$website=sqlite_escape_string($user->Website);
+		$createTime=time();
+		$sql="INSERT INTO tblUsers ".
+		"(name,full_name,role,passwd,email,reg_time,status,website) ".
+		"VALUES ('$name','$fullName',{$user->Role},'$passwd','$email',$createTime,{$user->Status},'$website')";
+		$this->query($sql);
+		$user->ID=sqlite_last_insert_rowid($this->_db);
+	}
+
+	public function updateUser($user)
+	{
+		$name=sqlite_escape_string($user->Name);
+		$fullName=sqlite_escape_string($user->FullName);
+		$passwd=sqlite_escape_string($user->Password);
+		$email=sqlite_escape_string($user->Email);
+		$website=sqlite_escape_string($user->Website);
+		$sql="UPDATE tblUsers SET
+				name='$name',
+				full_name='$fullName',
+				role={$user->Role},
+				passwd='$passwd',
+				vcode='{$user->VerifyCode}',
+				email='$email',
+				status={$user->Status},
+				website='$website'
+				WHERE id={$user->ID}";
+		$this->query($sql);
+	}
+
+	public function deleteUser($id)
+	{
+		$this->query("DELETE FROM tblUsers WHERE id=$id");
+	}
+
+	protected function populatePostRecord($row)
+	{
+		$postRecord=new PostRecord;
+		$postRecord->ID=(integer)$row['id'];
+		$postRecord->AuthorID=(integer)$row['author_id'];
+		if($row['author_full_name']!=='')
+		$postRecord->AuthorName=$row['author_full_name'];
+		else
+		$postRecord->AuthorName=$row['author_name'];
+		$postRecord->CreateTime=(integer)$row['create_time'];
+		$postRecord->ModifyTime=(integer)$row['modify_time'];
+		$postRecord->Title=$row['title'];
+		$postRecord->Content=$row['content'];
+		$postRecord->Status=(integer)$row['status'];
+		$postRecord->CommentCount=(integer)$row['comment_count'];
+		return $postRecord;
+	}
+
+	public function queryPosts($postFilter,$categoryFilter,$orderBy,$limit)
+	{
+		$filter='';
+		if($postFilter!=='')
+		$filter.=" AND $postFilter";
+		if($categoryFilter!=='')
+		$filter.=" AND a.id IN (SELECT post_id AS id FROM tblPost2Category WHERE $categoryFilter)";
+		$sql="SELECT a.id AS id,
+					a.author_id AS author_id,
+					b.name AS author_name,
+					b.full_name AS author_full_name,
+					a.create_time AS create_time,
+					a.modify_time AS modify_time,
+					a.title AS title,
+					a.content AS content,
+					a.status AS status,
+					a.comment_count AS comment_count
+				FROM tblPosts a, tblUsers b
+				WHERE a.author_id=b.id $filter $orderBy $limit";
+		$result=$this->query($sql);
+		$rows=sqlite_fetch_all($result,SQLITE_ASSOC);
+		$posts=array();
+		foreach($rows as $row)
+		$posts[]=$this->populatePostRecord($row);
+		return $posts;
+	}
+
+	public function queryPostCount($postFilter,$categoryFilter)
+	{
+		$filter='';
+		if($postFilter!=='')
+		$filter.=" AND $postFilter";
+		if($categoryFilter!=='')
+		$filter.=" AND a.id IN (SELECT post_id AS id FROM tblPost2Category WHERE $categoryFilter)";
+		$sql="SELECT COUNT(a.id) AS post_count
+				FROM tblPosts a, tblUsers b
+				WHERE a.author_id=b.id $filter";
+		$result=$this->query($sql);
+		if(($row=sqlite_fetch_array($result,SQLITE_ASSOC))!==false)
+		return $row['post_count'];
+		else
+		return 0;
+	}
+
+	public function queryPostByID($id)
+	{
+		$sql="SELECT a.id AS id,
+		             a.author_id AS author_id,
+		             b.name AS author_name,
+		             b.full_name AS author_full_name,
+		             a.create_time AS create_time,
+		             a.modify_time AS modify_time,
+		             a.title AS title,
+		             a.content AS content,
+		             a.status AS status,
+		             a.comment_count AS comment_count
+		      FROM tblPosts a, tblUsers b
+		      WHERE a.id=$id AND a.author_id=b.id";
+		$result=$this->query($sql);
+		if(($row=sqlite_fetch_array($result,SQLITE_ASSOC))!==false)
+		return $this->populatePostRecord($row);
+		else
+		return null;
+	}
+
+	public function escapeString($string)
+	{
+		return sqlite_escape_string($string);
+	}
+
+	public function insertPost($post,$catIDs)
+	{
+		$title=sqlite_escape_string($post->Title);
+		$content=sqlite_escape_string($post->Content);
+		$sql="INSERT INTO tblPosts
+				(author_id,create_time,modify_time,title,content,status)
+				VALUES ({$post->AuthorID},{$post->CreateTime},{$post->ModifyTime},'$title','$content',{$post->Status})";
+		$this->query($sql);
+		$post->ID=sqlite_last_insert_rowid($this->_db);
+		foreach($catIDs as $catID)
+		$this->insertPostCategory($post->ID,$catID);
+	}
+
+	public function updatePost($post,$newCatIDs=null)
+	{
+		if($newCatIDs!==null)
+		{
+			$cats=$this->queryCategoriesByPostID($post->ID);
+			$catIDs=array();
+			foreach($cats as $cat)
+			$catIDs[]=$cat->ID;
+			$deleteIDs=array_diff($catIDs,$newCatIDs);
+			foreach($deleteIDs as $id)
+			$this->deletePostCategory($post->ID,$id);
+			$insertIDs=array_diff($newCatIDs,$catIDs);
+			foreach($insertIDs as $id)
+			$this->insertPostCategory($post->ID,$id);
+		}
+
+		$title=sqlite_escape_string($post->Title);
+		$content=sqlite_escape_string($post->Content);
+		$sql="UPDATE tblPosts SET
+				modify_time={$post->ModifyTime},
+				title='$title',
+				content='$content',
+				status={$post->Status}
+				WHERE id={$post->ID}";
+		$this->query($sql);
+	}
+
+	public function deletePost($id)
+	{
+		$cats=$this->queryCategoriesByPostID($id);
+		foreach($cats as $cat)
+		$this->deletePostCategory($id,$cat->ID);
+		$this->query("DELETE FROM tblComments WHERE post_id=$id");
+		$this->query("DELETE FROM tblPosts WHERE id=$id");
+	}
+
+	protected function populateCommentRecord($row)
+	{
+		$commentRecord=new CommentRecord;
+		$commentRecord->ID=(integer)$row['id'];
+		$commentRecord->PostID=(integer)$row['post_id'];
+		$commentRecord->AuthorName=$row['author_name'];
+		$commentRecord->AuthorEmail=$row['author_email'];
+		$commentRecord->AuthorWebsite=$row['author_website'];
+		$commentRecord->AuthorIP=$row['author_ip'];
+		$commentRecord->CreateTime=(integer)$row['create_time'];
+		$commentRecord->Content=$row['content'];
+		$commentRecord->Status=(integer)$row['status'];
+		return $commentRecord;
+	}
+
+	public function queryComments($filter,$orderBy,$limit)
+	{
+		if($filter!=='')
+		$filter='WHERE '.$filter;
+		$sql="SELECT * FROM tblComments $filter $orderBy $limit";
+		$result=$this->query($sql);
+		$rows=sqlite_fetch_all($result,SQLITE_ASSOC);
+		$comments=array();
+		foreach($rows as $row)
+		$comments[]=$this->populateCommentRecord($row);
+		return $comments;
+	}
+
+	public function queryCommentsByPostID($id)
+	{
+		$sql="SELECT * FROM tblComments WHERE post_id=$id ORDER BY create_time DESC";
+		$result=$this->query($sql);
+		$rows=sqlite_fetch_all($result,SQLITE_ASSOC);
+		$comments=array();
+		foreach($rows as $row)
+		$comments[]=$this->populateCommentRecord($row);
+		return $comments;
+	}
+
+	public function insertComment($comment)
+	{
+		$authorName=sqlite_escape_string($comment->AuthorName);
+		$authorEmail=sqlite_escape_string($comment->AuthorEmail);
+		$authorWebsite=sqlite_escape_string($comment->AuthorWebsite);
+		$content=sqlite_escape_string($comment->Content);
+		$sql="INSERT INTO tblComments
+				(post_id,author_name,author_email,author_website,author_ip,create_time,status,content)
+				VALUES ({$comment->PostID},'$authorName','$authorEmail','$authorWebsite','{$comment->AuthorIP}',{$comment->CreateTime},{$comment->Status},'$content')";
+		$this->query($sql);
+		$comment->ID=sqlite_last_insert_rowid($this->_db);
+		$this->query("UPDATE tblPosts SET comment_count=comment_count+1 WHERE id={$comment->PostID}");
+	}
+
+	public function updateComment($comment)
+	{
+		$authorName=sqlite_escape_string($comment->AuthorName);
+		$authorEmail=sqlite_escape_string($comment->AuthorEmail);
+		$content=sqlite_escape_string($comment->Content);
+		$sql="UPDATE tblComments SET status={$comment->Status} WHERE id={$comment->ID}";
+		$this->query($sql);
+	}
+
+	public function deleteComment($id)
+	{
+		$result=$this->query("SELECT post_id FROM tblComments WHERE id=$id");
+		if(($row=sqlite_fetch_array($result,SQLITE_ASSOC))!==false)
+		{
+			$postID=$row['post_id'];
+			$this->query("DELETE FROM tblComments WHERE id=$id");
+			$this->query("UPDATE tblPosts SET comment_count=comment_count-1 WHERE id=$postID");
+		}
+	}
+
+	protected function populateCategoryRecord($row)
+	{
+		$catRecord=new CategoryRecord;
+		$catRecord->ID=(integer)$row['id'];
+		$catRecord->Name=$row['name'];
+		$catRecord->Description=$row['description'];
+		$catRecord->PostCount=$row['post_count'];
+		return $catRecord;
+	}
+
+	public function queryCategories()
+	{
+		$sql="SELECT * FROM tblCategories ORDER BY name ASC";
+		$result=$this->query($sql);
+		$rows=sqlite_fetch_all($result,SQLITE_ASSOC);
+		$cats=array();
+		foreach($rows as $row)
+		$cats[]=$this->populateCategoryRecord($row);
+		return $cats;
+	}
+
+	public function queryCategoriesByPostID($postID)
+	{
+		$sql="SELECT a.id AS id,
+				a.name AS name,
+				a.description AS description,
+				a.post_count AS post_count
+				FROM tblCategories a, tblPost2Category b
+				WHERE a.id=b.category_id AND b.post_id=$postID ORDER BY a.name";
+		$result=$this->query($sql);
+		$rows=sqlite_fetch_all($result,SQLITE_ASSOC);
+		$cats=array();
+		foreach($rows as $row)
+		$cats[]=$this->populateCategoryRecord($row);
+		return $cats;
+	}
+
+	public function queryCategoryByID($id)
+	{
+		$sql="SELECT * FROM tblCategories WHERE id=$id";
+		$result=$this->query($sql);
+		if(($row=sqlite_fetch_array($result,SQLITE_ASSOC))!==false)
+		return $this->populateCategoryRecord($row);
+		else
+		return null;
+	}
+
+	public function queryCategoryByName($name)
+	{
+		$name=sqlite_escape_string($name);
+		$sql="SELECT * FROM tblCategories WHERE name='$name'";
+		$result=$this->query($sql);
+		if(($row=sqlite_fetch_array($result,SQLITE_ASSOC))!==false)
+		return $this->populateCategoryRecord($row);
+		else
+		return null;
+	}
+
+	public function insertCategory($category)
+	{
+		$name=sqlite_escape_string($category->Name);
+		$description=sqlite_escape_string($category->Description);
+		$sql="INSERT INTO tblCategories
+				(name,description)
+				VALUES ('$name','$description')";
+		$this->query($sql);
+		$category->ID=sqlite_last_insert_rowid($this->_db);
+	}
+
+	public function updateCategory($category)
+	{
+		$name=sqlite_escape_string($category->Name);
+		$description=sqlite_escape_string($category->Description);
+		$sql="UPDATE tblCategories SET name='$name', description='$description', post_count={$category->PostCount} WHERE id={$category->ID}";
+		$this->query($sql);
+	}
+
+	public function deleteCategory($id)
+	{
+		$sql="DELETE FROM tblPost2Category WHERE category_id=$id";
+		$this->query($sql);
+		$sql="DELETE FROM tblCategories WHERE id=$id";
+		$this->query($sql);
+	}
+
+	public function insertPostCategory($postID,$categoryID)
+	{
+		$sql="INSERT INTO tblPost2Category (post_id, category_id) VALUES ($postID, $categoryID)";
+		$this->query($sql);
+		$sql="UPDATE tblCategories SET post_count=post_count+1 WHERE id=$categoryID";
+		$this->query($sql);
+	}
+
+	public function deletePostCategory($postID,$categoryID)
+	{
+		$sql="DELETE FROM tblPost2Category WHERE post_id=$postID AND category_id=$categoryID";
+		if($this->query($sql)>0)
+		{
+			$sql="UPDATE tblCategories SET post_count=post_count-1 WHERE id=$categoryID";
+			$this->query($sql);
+		}
+	}
+
+	public function queryEarliestPostTime()
+	{
+		$sql="SELECT MIN(create_time) AS create_time FROM tblPosts";
+		$result=$this->query($sql);
+		if(($row=sqlite_fetch_array($result,SQLITE_ASSOC))!==false)
+		return $row['create_time'];
+		else
+		return time();
+	}
+}
+
+class UserRecord extends TActiveRecord
+{
+	const ROLE_USER=0;
+	const ROLE_ADMIN=1;
+	const STATUS_NORMAL=0;
+	const STATUS_DISABLED=1;
+	const STATUS_PENDING=2;
+	public $id;
+	public $name;
+	public $full_name;
+	public $role;
+	public $passwd;
+	public $vcode;
+	public $email;
+	public $reg_time;
+	public $status;
+	public $website;
+
+	public static $_tablename='tblUsers'; //table name
+
+	/**
+     * @return TActiveRecord active record finder instance
+     */
+	public static function finder()
+	{
+		return self::getRecordFinder('UserRecord');
+	}
+}
+
+class PostRecord extends TActiveRecord
+{
+	const STATUS_PUBLISHED=0;
+	const STATUS_DRAFT=1;
+	const STATUS_PENDING=2;
+	const STATUS_STICKY=3;
+	public $id;
+	public $author_id;
+	public $author_name;
+	public $create_time;
+	public $modify_time;
+	public $title;
+	public $content;
+	public $status;
+	public $comment_count;
+
+	public static $_tablename='tblPosts'; //table name
+
+	/**
+     * @return TActiveRecord active record finder instance
+     */
+	public static function finder()
+	{
+		return self::getRecordFinder('PostRecord');
+	}
+}
+
+class CommentRecord extends TActiveRecord
+{
+	public $id;
+	public $post_id;
+	public $author_name;
+	public $author_email;
+	public $author_website;
+	public $author_ip;
+	public $create_time;
+	public $status;
+	public $content;
+
+	public static $_tablename='tblComments'; //table name
+
+	/**
+     * @return TActiveRecord active record finder instance
+     */
+	public static function finder()
+	{
+		return self::getRecordFinder('CommentRecord');
+	}
+}
+
+class CategoryRecord extends TActiveRecord
+{
+	public $id;
+	public $name;
+	public $description;
+	public $post_count;
+
+	public static $_tablename='tblCategories'; //table name
+
+	/**
+     * @return TActiveRecord active record finder instance
+     */
+	public static function finder()
+	{
+		return self::getRecordFinder('CategoryRecord');
+	}
+}
+
+class Post2CategoryRecord extends TActiveRecord
+{
+	public $post_id;
+	public $category_id;
+	
+	public static $_tablename='tblPost2Category'; //table name
+
+	/**
+     * @return TActiveRecord active record finder instance
+     */
+	public static function finder()
+	{
+		return self::getRecordFinder('Post2CategoryRecord');
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/demos/activeblog/protected/App_Modules/BlogErrorHandler.php b/demos/activeblog/protected/App_Modules/BlogErrorHandler.php
new file mode 100644
index 00000000..dc8985d8
--- /dev/null
+++ b/demos/activeblog/protected/App_Modules/BlogErrorHandler.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * BlogErrorHandler class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id: BlogErrorHandler.php 1509 2006-11-25 20:51:43Z xue $
+ */
+
+Prado::using('System.Exceptions.TErrorHandler');
+Prado::using('Application.Common.BlogException');
+
+/**
+ * BlogErrorHandler class
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ */
+class BlogErrorHandler extends TErrorHandler
+{
+	/**
+	 * Displays error to the client user.
+	 * THttpException and errors happened when the application is in <b>Debug</b>
+	 * mode will be displayed to the client user.
+	 * @param integer response status code
+	 * @param Exception exception instance
+	 */
+	protected function handleExternalError($statusCode,$exception)
+	{
+		if($exception instanceof BlogException)
+		{
+			$message=$exception->getMessage();
+			Prado::log($message,TLogger::ERROR,'BlogApplication');
+			$message=urldecode($this->getApplication()->getSecurityManager()->hashData($message));
+			$this->Response->redirect($this->Service->constructUrl('ErrorReport',array('msg'=>$message),false));
+		}
+		else
+			parent::handleExternalError($statusCode,$exception);
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/demos/activeblog/protected/App_Modules/BlogUser.php b/demos/activeblog/protected/App_Modules/BlogUser.php
new file mode 100644
index 00000000..042ada86
--- /dev/null
+++ b/demos/activeblog/protected/App_Modules/BlogUser.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * BlogUser class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id: BlogUser.php 1398 2006-09-08 19:31:03Z xue $
+ */
+
+Prado::using('System.Security.TUser');
+
+/**
+ * BlogUser class
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ */
+class BlogUser extends TUser
+{
+	private $_id;
+
+	public function getID()
+	{
+		return $this->_id;
+	}
+
+	public function setID($value)
+	{
+		$this->_id=$value;
+	}
+
+	public function getIsAdmin()
+	{
+		return $this->isInRole('admin');
+	}
+
+	public function saveToString()
+	{
+		$a=array($this->_id,parent::saveToString());
+		return serialize($a);
+	}
+
+	public function loadFromString($data)
+	{
+		if(!empty($data))
+		{
+			list($id,$str)=unserialize($data);
+			$this->_id=$id;
+			return parent::loadFromString($str);
+		}
+		else
+			return $this;
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/demos/activeblog/protected/App_Modules/BlogUserManager.php b/demos/activeblog/protected/App_Modules/BlogUserManager.php
new file mode 100644
index 00000000..370966ef
--- /dev/null
+++ b/demos/activeblog/protected/App_Modules/BlogUserManager.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * BlogUserManager class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id: BlogUserManager.php 1398 2006-09-08 19:31:03Z xue $
+ */
+
+Prado::using('System.Security.IUserManager');
+Prado::using('Application.Common.BlogUser');
+
+/**
+ * BlogUserManager class
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ */
+class BlogUserManager extends TModule implements IUserManager
+{
+	public function getGuestName()
+	{
+		return 'Guest';
+	}
+
+	/**
+	 * Returns a user instance given the user name.
+	 * @param string user name, null if it is a guest.
+	 * @return TUser the user instance, null if the specified username is not in the user database.
+	 */
+	public function getUser($username=null)
+	{
+		if($username===null)
+			return new BlogUser($this);
+		else
+		{
+			$username=strtolower($username);
+			$db=$this->Application->getModule('data');
+			if(($userRecord=$db->queryUserByName($username))!==null)
+			{
+				$user=new BlogUser($this);
+				$user->setID($userRecord->ID);
+				$user->setName($username);
+				$user->setIsGuest(false);
+				$user->setRoles($userRecord->Role===UserRecord::ROLE_USER?'user':'admin');
+				return $user;
+			}
+			else
+				return null;
+		}
+	}
+
+	/**
+	 * Validates if the username and password are correct.
+	 * @param string user name
+	 * @param string password
+	 * @return boolean true if validation is successful, false otherwise.
+	 */
+	public function validateUser($username,$password)
+	{
+		$db=$this->Application->getModule('data');
+		if(($userRecord=$db->queryUserByName($username))!==null)
+			return $userRecord->Password===md5($password) && $userRecord->Status===UserRecord::STATUS_NORMAL;
+		else
+			return false;
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/demos/activeblog/protected/App_Modules/schema.sql b/demos/activeblog/protected/App_Modules/schema.sql
new file mode 100644
index 00000000..9c111f0c
--- /dev/null
+++ b/demos/activeblog/protected/App_Modules/schema.sql
@@ -0,0 +1,76 @@
+CREATE TABLE tblUsers (
+  id			INTEGER NOT NULL PRIMARY KEY,
+  name			VARCHAR(128) NOT NULL UNIQUE,
+  full_name		VARCHAR(128) DEFAULT '',
+  role          INTEGER NOT NULL DEFAULT 0, /* 0: user, 1: admin */
+  passwd		VARCHAR(128) NOT NULL,
+  vcode			VARCHAR(128) DEFAULT '',
+  email		    VARCHAR(128) NOT NULL,
+  reg_time		INTEGER NOT NULL,
+  status		INTEGER NOT NULL DEFAULT 0, /* 0: normal, 1: disabled, 2: pending approval */
+  website	    VARCHAR(128) DEFAULT ''
+);
+
+CREATE TABLE tblPosts (
+  id			INTEGER NOT NULL PRIMARY KEY,
+  author_id		INTEGER NOT NULL,
+  create_time	INTEGER NOT NULL,
+  modify_time	INTEGER DEFAULT 0,
+  title			VARCHAR(256) NOT NULL,
+  content		TEXT NOT NULL,
+  status		INTEGER NOT NULL DEFAULT 0, /* 0: published, 1: draft, 2: pending approval */
+  comment_count	INTEGER NOT NULL DEFAULT 0
+);
+
+CREATE TABLE tblComments (
+  id			INTEGER NOT NULL PRIMARY KEY,
+  post_id		INTEGER NOT NULL,
+  author_name	VARCHAR(64) NOT NULL,
+  author_email	VARCHAR(128) NOT NULL,
+  author_website VARCHAR(128) DEFAULT '',
+  author_ip		CHAR(16) NOT NULL,
+  create_time	INTEGER NOT NULL,
+  status		INTEGER NOT NULL DEFAULT 0, /* 0: published, 1: pending approval */
+  content		TEXT NOT NULL
+);
+
+CREATE TABLE tblCategories (
+  id			INTEGER NOT NULL PRIMARY KEY,
+  name			VARCHAR(128) NOT NULL UNIQUE,
+  description	TEXT DEFAULT '',
+  post_count	INTEGER NOT NULL DEFAULT 0
+);
+
+CREATE TABLE tblAttachments (
+  id			VARCHAR(128) NOT NULL PRIMARY KEY,
+  post_id		INTEGER NOT NULL,
+  create_time	INTEGER NOT NULL,
+  file_name		VARCHAR(128) NOT NULL,
+  file_size		INTEGER NOT NULL,
+  mime_type		VARCHAR(32) NOT NULL DEFAULT 'text/html',
+  download_count INTEGER NOT NULL DEFAULT 0
+);
+
+CREATE TABLE tblPost2Category (
+  post_id		INTEGER NOT NULL,
+  category_id	INTEGER NOT NULL,
+  PRIMARY KEY (post_id, category_id)
+);
+
+INSERT INTO tblUsers (id,name,full_name,role,status,passwd,email,reg_time,website)
+	VALUES (1,'admin','Prado User',1,0,'4d688da592969d0a56b5accec3ce8554','admin@example.com',1148819681,'http://www.pradosoft.com');
+
+INSERT INTO tblPosts (id,author_id,create_time,title,content,status)
+	VALUES (1,1,1148819691,'Welcome to Prado Weblog','Congratulations! You have successfully installed Prado Blog -- a PRADO-driven weblog system. A default administrator account has been created. Please login with <b>admin/prado</b> and update your password as soon as possible.',0);
+
+INSERT INTO tblCategories (name,description,post_count)
+	VALUES ('Miscellaneous','This category holds posts on any topic.',1);
+
+INSERT INTO tblCategories (name,description,post_count)
+	VALUES ('PRADO','Topics related with the PRADO framework.',0);
+
+INSERT INTO tblCategories (name,description,post_count)
+	VALUES ('PHP','Topics related with PHP.',0);
+
+INSERT INTO tblPost2Category (post_id,category_id)
+	VALUES (1,1);
diff --git a/demos/activeblog/protected/App_Pages/Home.php b/demos/activeblog/protected/App_Pages/Home.php
index e4bda2c3..0012e073 100644
--- a/demos/activeblog/protected/App_Pages/Home.php
+++ b/demos/activeblog/protected/App_Pages/Home.php
@@ -1,6 +1,27 @@
 <?php
-class Home extends TPage 
+class Home extends BlogPage
 {
-	
+	public function onLoad($param)
+	{
+		parent::onLoad($param);
+
+		//		sqlite_open(dirname(__FILE__).'/../App_Data/blog.db');
+
+		//		$finder = UserRecord::finder();
+		//		$user = $finder->findByPk(1);
+		//		echo TVarDumper::dump($user,10,true);
+		//
+		//		$finder = PostRecord::finder();
+		//		$post = $finder->findByPk(1);
+		//		echo TVarDumper::dump($post,10,true);
+		//
+		//		$finder = CategoryRecord::finder();
+		//		$categories = $finder->findAll();
+		//		echo TVarDumper::dump($categories,10,true);
+		//
+		//		$finder = Post2CategoryRecord::finder();
+		//		$post2category = $finder->findByPk(1,1);
+		//		echo TVarDumper::dump($post2category,10,true);
+	}
 }
 ?>
\ No newline at end of file
diff --git a/demos/activeblog/protected/application.xml b/demos/activeblog/protected/application.xml
index 7b038a2e..ce3906d5 100644
--- a/demos/activeblog/protected/application.xml
+++ b/demos/activeblog/protected/application.xml
@@ -5,34 +5,20 @@
 <!--<application id="activeblog" Mode="Normal">-->
 <!--<application id="activeblog" Mode="Performance">-->
  	<paths>
- 		<!-- Alias back to the WebRoot -->
- 		<alias id="WebRoot" path=".." />
- 		
  		<!-- System Namespaces -->
  		<using namespace="System.Util.TVarDumper" />
-<!-- 		<using namespace="System.Security.IUserManager" />-->
-<!-- 		<using namespace="System.Security.TUser" />-->
  		<using namespace="System.Web.UI.ActiveControls.*" />
+ 		<using namespace="System.Data.ActiveRecord.*" />
  		
  		<!-- Application Namespaces -->
+ 		<using namespace="Application.App_Controls.BlogException"/>
  		<using namespace="Application.App_Controls.*"/>
  		<using namespace="Application.App_Modules.*"/>
  		<using namespace="Application.App_Portlets.*"/>
  		<using namespace="Application.App_Services.*"/>
- 		
- 		<!-- DAO Namespaces -->
-<!-- 		<using namespace="Application.App_Data.classes.*"/>-->
  	</paths>
- 	
- 	<parameters>
- 		<parameter id ="SiteName" value="Prado Active Blog"/>
- 		<parameter id="SiteOwner" value="Your Name Here"/>
- 		<parameter id="SiteOffline" value="False"/>
- 		<!-- Are we allowing signups -->
-		<parameter id="AllowRegister" value="True"/>
-		<!-- Email Controls -->
-		<parameter id="DisableEmails" value="False"/>
- 	</parameters>
+
+ 	<module class="System.Util.TParameterModule" ParameterFile="Application.Data.Settings" />
  	
  	<!-- modules configured and loaded for all services -->
   	<modules>
@@ -44,8 +30,8 @@
   			UrlFormat="Path" 
   			EnableCookieValidation="True"
   			UrlManager="friendly-url"/>
-		
-		<module id="ErrorHandler" class="System.Exceptions.TErrorHandler" />
+
+		<module id="ErrorHandler" class="Application.App_Modules.BlogErrorHandler" />
 		
 		<!-- Custom Session Module -->
     	<module 
@@ -55,17 +41,12 @@
     		UseCustomStorage="True" />
   			
   		<!-- user manager module -->
-<!--    	<module id="users" class="Application.App_Modules.JUserManager"/>-->
-    			
+		
     	<!-- auth manager module -->
-<!-- 		<module 
- 			id="auth" 
- 			class="Application.App_Modules.JAuthManager" 
- 			UserManager="users" 
- 			LoginPage="/Home"/>-->
   			
   		<!-- Modules for caching -->
 <!--    	<module id="SqliteCache" PrimaryCache="True" class="System.Caching.TSqliteCache"/>-->
+
   	</modules>
   	
   	<services>
@@ -86,10 +67,17 @@
       					LogFile="Application.log" 
       					Categories="Application" 
       					Levels="Info,Notice,Warning,Error,Alert,Fatal"/>
+      				<route 
+      					class="TFileLogRoute" 
+      					LogFile="BlogApplication.log" 
+      					Categories="BlogApplication" />
 				</module>
 				
 				<!-- Theme manager module -->
     			<module id="themes" class="System.Web.UI.TThemeManager" />
+    			
+    			<!-- Data Module -->
+    			<module id="data" class="Application.App_Modules.BlogDataModule" />
 			</modules>
 			
 			<pages MasterClass="Application.App_Layouts.MainLayout" Theme="Default" />
-- 
cgit v1.2.3