diff options
author | wei <> | 2007-01-04 11:23:26 +0000 |
---|---|---|
committer | wei <> | 2007-01-04 11:23:26 +0000 |
commit | dd028bec3822d1d9c28c35d599d687e038c7705f (patch) | |
tree | f3d2fb7f95073ea481a4dec86f0f0d30c7fe3588 /demos/chat | |
parent | cac90ea6547fe194ab6ab101dfe11a0b751823ca (diff) |
Add chat demo and tutorial.
Diffstat (limited to 'demos/chat')
-rw-r--r-- | demos/chat/index.php | 29 | ||||
-rw-r--r-- | demos/chat/protected/.htaccess | 1 | ||||
-rw-r--r-- | demos/chat/protected/App_Code/ChatBufferRecord.php | 64 | ||||
-rw-r--r-- | demos/chat/protected/App_Code/ChatUserManager.php | 63 | ||||
-rw-r--r-- | demos/chat/protected/App_Code/ChatUserRecord.php | 41 | ||||
-rw-r--r-- | demos/chat/protected/App_Code/chat.db | bin | 0 -> 4096 bytes | |||
-rw-r--r-- | demos/chat/protected/application.xml | 24 | ||||
-rw-r--r-- | demos/chat/protected/pages/Home.page | 51 | ||||
-rw-r--r-- | demos/chat/protected/pages/Home.php | 56 | ||||
-rw-r--r-- | demos/chat/protected/pages/Login.page | 35 | ||||
-rw-r--r-- | demos/chat/protected/pages/Login.php | 40 | ||||
-rw-r--r-- | demos/chat/protected/pages/config.xml | 15 | ||||
-rw-r--r-- | demos/chat/protected/pages/send.gif | bin | 0 -> 993 bytes | |||
-rw-r--r-- | demos/chat/protected/pages/send.png | bin | 0 -> 32586 bytes | |||
-rw-r--r-- | demos/chat/protected/pages/style.css | 82 |
15 files changed, 501 insertions, 0 deletions
diff --git a/demos/chat/index.php b/demos/chat/index.php new file mode 100644 index 00000000..17ed21d0 --- /dev/null +++ b/demos/chat/index.php @@ -0,0 +1,29 @@ +<?php
+
+$frameworkPath='../../framework/prado.php';
+
+/** The directory checks may be removed if performance is required **/
+$basePath=dirname(__FILE__);
+$assetsPath=$basePath."/assets";
+$runtimePath=$basePath."/protected/runtime";
+
+$sqliteDbDir = $basePath."/protected/App_Code";
+$sqliteDb = $sqliteDbDir."/chat.db";
+
+if(!is_file($frameworkPath))
+ die("Unable to find prado framework path $frameworkPath.");
+if(!is_writable($assetsPath))
+ die("Please make sure that the directory $assetsPath is writable by Web server process.");
+if(!is_writable($runtimePath))
+ die("Please make sure that the directory $runtimePath is writable by Web server process.");
+if(!is_writable($sqliteDbDir))
+ die("Please make sure that the directory $sqliteDbDir is writable by Web server process.");
+if(!is_writable($sqliteDb))
+ die("Please make sure that the sqlite file $sqliteDb is writable by Web server process.");
+
+require_once($frameworkPath);
+
+$application=new TApplication;
+$application->run();
+
+?>
\ No newline at end of file diff --git a/demos/chat/protected/.htaccess b/demos/chat/protected/.htaccess new file mode 100644 index 00000000..3418e55a --- /dev/null +++ b/demos/chat/protected/.htaccess @@ -0,0 +1 @@ +deny from all
\ No newline at end of file diff --git a/demos/chat/protected/App_Code/ChatBufferRecord.php b/demos/chat/protected/App_Code/ChatBufferRecord.php new file mode 100644 index 00000000..cf3c651f --- /dev/null +++ b/demos/chat/protected/App_Code/ChatBufferRecord.php @@ -0,0 +1,64 @@ +<?php
+
+class ChatBufferRecord extends TActiveRecord
+{
+ public $id;
+ public $for_user;
+ public $from_user;
+ public $message;
+ private $_created_on;
+
+ public static $_tablename='chat_buffer';
+
+ public function getCreated_On()
+ {
+ if($this->_created_on === null)
+ $this->_created_on = time();
+ return $this->_created_on;
+ }
+
+ public function setCreated_On($value)
+ {
+ $this->_created_on = $value;
+ }
+
+ public static function finder()
+ {
+ return parent::getRecordFinder('ChatBufferRecord');
+ }
+
+ public function saveMessage()
+ {
+ foreach(ChatUserRecord::finder()->findAll() as $user)
+ {
+ $message = new self;
+ $message->for_user = $user->username;
+ $message->from_user = $this->from_user;
+ $message->message = $this->message;
+ $message->save();
+ if($user->username == $this->from_user)
+ {
+ $user->last_activity = time(); //update the last activity;
+ $user->save();
+ }
+ }
+ }
+
+ public function getUserMessages($user)
+ {
+ $content = '';
+ foreach($this->findAll('for_user = ?', $user) as $message)
+ $content .= $this->formatMessage($message);
+ $this->deleteAll('for_user = ? OR created_on < ?', $user, time() - 300); //5 min inactivity
+ return $content;
+ }
+
+ protected function formatMessage($message)
+ {
+ $user = htmlspecialchars($message->from_user);
+ $content = htmlspecialchars($message->message);
+ return "<div class=\"message\"><strong>{$user}:</strong> <span>{$content}</span></div>";
+ }
+}
+
+?>
\ No newline at end of file diff --git a/demos/chat/protected/App_Code/ChatUserManager.php b/demos/chat/protected/App_Code/ChatUserManager.php new file mode 100644 index 00000000..f8fe09cc --- /dev/null +++ b/demos/chat/protected/App_Code/ChatUserManager.php @@ -0,0 +1,63 @@ +<?php
+
+class ChatUserManager extends TModule implements IUserManager
+{
+ /**
+ * @return string name for a guest user.
+ */
+ 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
+ */
+ public function getUser($username=null)
+ {
+ $user=new TUser($this);
+ $user->setIsGuest(true);
+ if($username !== null)
+ {
+ $user->setIsGuest(false);
+ $user->setName($username);
+ $user->setRoles(array('normal'));
+ }
+ return $user;
+ }
+
+ /**
+ * Add a new user to the database.
+ * @param string username.
+ */
+ public function addNewUser($username)
+ {
+ $user = new ChatUserRecord();
+ $user->username = $username;
+ $user->save();
+ }
+
+ /**
+ * @return boolean true if username already exists, false otherwise.
+ */
+ public function usernameExists($username)
+ {
+ return ChatUserRecord::finder()->findByUsername($username) instanceof ChatUserRecord;
+ }
+
+ /**
+ * Validates if the username exists.
+ * @param string user name
+ * @param string password
+ * @return boolean true if validation is successful, false otherwise.
+ */
+ public function validateUser($username,$password)
+ {
+ return $this->usernameExists($username);
+ }
+}
+
+
+?>
\ No newline at end of file diff --git a/demos/chat/protected/App_Code/ChatUserRecord.php b/demos/chat/protected/App_Code/ChatUserRecord.php new file mode 100644 index 00000000..9bfb11cd --- /dev/null +++ b/demos/chat/protected/App_Code/ChatUserRecord.php @@ -0,0 +1,41 @@ +<?php
+
+class ChatUserRecord extends TActiveRecord
+{
+ public $username;
+ private $_last_activity;
+
+ public static $_tablename='chat_users';
+
+ public function getLast_Activity()
+ {
+ if($this->_last_activity === null)
+ $this->_last_activity = time();
+ return $this->_last_activity;
+ }
+
+ public function setLast_Activity($value)
+ {
+ $this->_last_activity = $value;
+ }
+
+ public static function finder()
+ {
+ return parent::getRecordFinder('ChatUserRecord');
+ }
+
+ public function getUserList()
+ {
+ $this->deleteAll('last_activity < ?', time()-300); //5 min inactivity
+ $content = '<ul>';
+ foreach($this->findAll() as $user)
+ {
+ $content .= '<li>'.htmlspecialchars($user->username).'</li>';
+ }
+ $content .= '</ul>';
+
+ return $content;
+ }
+}
+
+?>
\ No newline at end of file diff --git a/demos/chat/protected/App_Code/chat.db b/demos/chat/protected/App_Code/chat.db Binary files differnew file mode 100644 index 00000000..f8e3660f --- /dev/null +++ b/demos/chat/protected/App_Code/chat.db diff --git a/demos/chat/protected/application.xml b/demos/chat/protected/application.xml new file mode 100644 index 00000000..7153d5af --- /dev/null +++ b/demos/chat/protected/application.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?>
+<application id="Chat" Mode="Debug">
+
+ <paths>
+ <using namespace="Application.App_Code.*" />
+ <using namespace="System.Data.*" />
+ <using namespace="System.Data.ActiveRecord.*" />
+ <using namespace="System.Security.*" />
+ <using namespace="System.Web.UI.ActiveControls.*" />
+ </paths>
+
+ <modules>
+ <!-- active record database connection configuration -->
+<!-- <module class="TActiveRecordConfig" EnableCache="true"
+ Database.ConnectionString="mysql:host=localhost;dbname=prado_chat"
+ Database.Username="prado"
+ Database.Password="prado" />
+-->
+ <module class="TActiveRecordConfig" EnableCache="true"
+ Database.ConnectionString="sqlite:protected/App_Code/chat.db" />
+
+ </modules>
+
+</application>
\ No newline at end of file diff --git a/demos/chat/protected/pages/Home.page b/demos/chat/protected/pages/Home.page new file mode 100644 index 00000000..b896cd28 --- /dev/null +++ b/demos/chat/protected/pages/Home.page @@ -0,0 +1,51 @@ +<!doctype html public "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Prado Chat Demo</title>
+ <link rel="stylesheet" type="text/css" href="<%~ style.css %>" />
+</head>
+
+<body>
+<com:TForm>
+<h1>Prado Chat Demo</h1>
+<noscript>Javascript is required for the chat demo to function.</noscript>
+<div id="messages" class="messages">
+ <com:TPlaceHolder ID="messageList" />
+</div>
+<div id="users" class="user-list">
+ <com:TPlaceHolder ID="userList" />
+</div>
+<div class="message-input">
+ <com:TActiveTextBox ID="userinput"
+ Columns="40" Rows="2" TextMode="MultiLine" />
+
+ <com:TActiveImageButton ID="sendButton" CssClass="send-button"
+ ImageUrl=<%~ send.gif %> OnClick="processMessage"/>
+</div>
+
+<com:TTimeTriggeredCallback OnCallback="refresh"
+ Interval="2" StartTimerOnLoad="true" />
+
+<com:TClientScript>
+ Event.observe($("<%= $this->userinput->ClientID %>"), "keypress", function(ev)
+ {
+ if(Event.keyCode(ev) == Event.KEY_RETURN)
+ {
+ if(Event.element(ev).value.length > 0)
+ new Prado.Callback("<%= $this->sendButton->UniqueID %>");
+ Event.stop(ev);
+ }
+ });
+</com:TClientScript>
+</com:TForm>
+ <com:TJavascriptLogger Visible="false"/>
+
+<div id="footer">
+Copyright © 2007 <a href="http://www.pradosoft.com">PradoSoft</a>.
+<br/><br/>
+<%= Prado::poweredByPrado() %>
+</div>
+
+</body>
+</html>
\ No newline at end of file diff --git a/demos/chat/protected/pages/Home.php b/demos/chat/protected/pages/Home.php new file mode 100644 index 00000000..65cb22dc --- /dev/null +++ b/demos/chat/protected/pages/Home.php @@ -0,0 +1,56 @@ +<?php
+
+class Home extends TPage
+{
+ public function onLoad($param)
+ {
+ $username = $this->Application->User->Name;
+ if(!$this->Application->Modules['users']->usernameExists($username))
+ {
+ $auth = $this->Application->Modules['auth'];
+ $auth->logout();
+
+ //redirect to login page.
+ $this->Response->Redirect($this->Service->ConstructUrl($auth->LoginPage));
+ }
+ }
+
+ function processMessage($sender, $param)
+ {
+ if(strlen($this->userinput->Text) > 0)
+ {
+ $record = new ChatBufferRecord();
+ $record->message = $this->userinput->Text;
+ $record->from_user = $this->Application->User->Name;
+ $record->saveMessage();
+ $this->userinput->Text = '';
+ $this->refresh($sender, $param);
+ $this->CallbackClient->focus($this->userinput);
+ }
+ }
+
+ function refresh($sender, $param)
+ {
+ //refresh the message list
+ $content = ChatBufferRecord::finder()->getUserMessages($this->Application->User->Name);
+ if(strlen($content) > 0)
+ {
+ $client = $this->Page->CallbackClient;
+ $anchor = (string)time();
+ $content .= "<a href=\"#\" id=\"{$anchor}\"> </a>";
+ $client->appendContent("messages", $content);
+ $client->focus($anchor);
+ }
+
+ //refresh the user list
+ $lastUpdate = $this->getViewState('userList','');
+ $users = ChatUserRecord::finder()->getUserList();
+ if($lastUpdate != $users)
+ {
+ $this->Page->CallbackClient->update('users', $users);
+ $this->setViewstate('userList', $users);
+ }
+ }
+}
+
+?>
\ No newline at end of file diff --git a/demos/chat/protected/pages/Login.page b/demos/chat/protected/pages/Login.page new file mode 100644 index 00000000..0d0a3fa8 --- /dev/null +++ b/demos/chat/protected/pages/Login.page @@ -0,0 +1,35 @@ +<!doctype html public "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Prado Chat Demo Login</title>
+ <link rel="stylesheet" type="text/css" href="<%~ style.css %>" />
+</head>
+
+<body>
+
+<com:TForm>
+ <h1 class="login">Prado Chat Demo Login</h1>
+ <fieldset class="login">
+ <legend>Please enter your name:</legend>
+ <div class="username">
+ <com:TLabel ForControl="username" Text="Username:" />
+ <com:TTextBox ID="username" MaxLength="20" />
+ <com:TRequiredFieldValidator
+ ControlToValidate="username"
+ Display="Dynamic"
+ ErrorMessage="Please provide a username." />
+ <com:TCustomValidator
+ ControlToValidate="username"
+ Display="Dynamic"
+ OnServerValidate="checkUsername"
+ ErrorMessage="The username is already taken." />
+ </div>
+
+ <div class="login-button">
+ <com:TButton Text="Login" OnClick="createNewUser" />
+ </div>
+</com:TForm>
+
+</body>
+</html>
\ No newline at end of file diff --git a/demos/chat/protected/pages/Login.php b/demos/chat/protected/pages/Login.php new file mode 100644 index 00000000..831ab925 --- /dev/null +++ b/demos/chat/protected/pages/Login.php @@ -0,0 +1,40 @@ +<?php
+
+class Login extends TPage
+{
+ /**
+ * Check that the username is not already taken.
+ * @param TControl custom validator that created the event.
+ * @param TServerValidateEventParameter validation parameters.
+ */
+ function checkUsername($sender, $param)
+ {
+ $manager = $this->Application->Modules['users'];
+ if($manager->usernameExists($this->username->Text))
+ $param->IsValid = false;
+ }
+
+ /**
+ * Create and login a new user, then redirect to the requested page.
+ * @param TControl button control that created the event.
+ * @param TEventParameter event parameters.
+ */
+ function createNewUser($sender, $param)
+ {
+ if($this->Page->IsValid)
+ {
+ $manager = $this->Application->Modules['users'];
+ $manager->addNewUser($this->username->Text);
+
+ //do manual login
+ $user = $manager->getUser($this->username->Text);
+ $auth = $this->Application->Modules['auth'];
+ $auth->updateSessionUser($user);
+ $this->Application->User = $user;
+
+ $this->Response->redirect($auth->ReturnUrl);
+ }
+ }
+}
+
+?>
\ No newline at end of file diff --git a/demos/chat/protected/pages/config.xml b/demos/chat/protected/pages/config.xml new file mode 100644 index 00000000..c9fbdaae --- /dev/null +++ b/demos/chat/protected/pages/config.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+
+ <modules>
+ <module id="users" class="ChatUserManager" />
+ <module id="auth" class="TAuthManager" UserManager="users" LoginPage="Login" />
+ </modules>
+
+ <authorization>
+ <allow pages="Login" users="?" />
+ <allow roles="normal" />
+ <deny users="*" />
+ </authorization>
+
+</configuration>
\ No newline at end of file diff --git a/demos/chat/protected/pages/send.gif b/demos/chat/protected/pages/send.gif Binary files differnew file mode 100644 index 00000000..b3c5219d --- /dev/null +++ b/demos/chat/protected/pages/send.gif diff --git a/demos/chat/protected/pages/send.png b/demos/chat/protected/pages/send.png Binary files differnew file mode 100644 index 00000000..3025b77d --- /dev/null +++ b/demos/chat/protected/pages/send.png diff --git a/demos/chat/protected/pages/style.css b/demos/chat/protected/pages/style.css new file mode 100644 index 00000000..884aff7c --- /dev/null +++ b/demos/chat/protected/pages/style.css @@ -0,0 +1,82 @@ +body
+{
+ width: 700px;
+ margin: 2em auto;
+ font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
+}
+
+h1
+{
+ font-size: 1.5em;
+ color: #444;
+}
+
+.login
+{
+ width: 500px;
+ margin: 1em auto;
+}
+
+.login .username
+{
+ margin: 1em;
+}
+
+.login .login-button
+{
+ padding-left: 7em;
+}
+
+.messages
+{
+ width: 500px;
+ height: 300px;
+ float: left;
+ border: 1px solid ButtonFace;
+ overflow: auto;
+}
+
+.messages .message
+{
+ margin: 0.4em 1em;
+ font-size: 0.85em;
+}
+
+.user-list
+{
+ margin-left: 2px;
+ float: left;
+ width: 180px;
+ height: 300px;
+ border: 1px solid ButtonFace;
+ overflow: auto;
+ font-size: 0.85em;
+}
+
+.message-input
+{
+ float: left;
+}
+
+.message-input textarea
+{
+ margin-top: 3px;
+ padding: 0.4em 0.2em;
+ width: 493px;
+ font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
+ font-size: 0.85em;
+ height: 40px;
+}
+
+.send-button
+{
+ margin: 0.5em;
+}
+
+#footer
+{
+ clear: both;
+ font-size: 0.7em;
+ text-align: center;
+ padding-top: 50px;
+}
\ No newline at end of file |