',
+ ),
+ ),
+ */
+ 'db'=>array(
+ 'connectionString' => 'sqlite:'.dirname(__FILE__).'/../data/testdrive.db',
+ ),
+ // uncomment the following to use a MySQL database
+ /*
+ 'db'=>array(
+ 'connectionString' => 'mysql:host=localhost;dbname=testdrive',
+ 'emulatePrepare' => true,
+ 'username' => 'root',
+ 'password' => '',
+ 'charset' => 'utf8',
+ ),
+ */
+ 'errorHandler'=>array(
+ // use 'site/error' action to display errors
+ 'errorAction'=>'site/error',
+ ),
+ 'log'=>array(
+ 'class'=>'CLogRouter',
+ 'routes'=>array(
+ array(
+ 'class'=>'CFileLogRoute',
+ 'levels'=>'error, warning',
+ ),
+ // uncomment the following to show log messages on web pages
+ /*
+ array(
+ 'class'=>'CWebLogRoute',
+ ),
+ */
+ ),
+ ),
+ ),
+
+ // application-level parameters that can be accessed
+ // using Yii::app()->params['paramName']
+ 'params'=>array(
+ // this is used in contact page
+ 'adminEmail'=>'webmaster@example.com',
+ ),
+);
\ No newline at end of file
diff --git a/protected/config/test.php b/protected/config/test.php
new file mode 100644
index 0000000..fd7085a
--- /dev/null
+++ b/protected/config/test.php
@@ -0,0 +1,17 @@
+array(
+ 'fixture'=>array(
+ 'class'=>'system.test.CDbFixtureManager',
+ ),
+ /* uncomment the following to provide test database connection
+ 'db'=>array(
+ 'connectionString'=>'DSN for test database',
+ ),
+ */
+ ),
+ )
+);
diff --git a/protected/controllers/SiteController.php b/protected/controllers/SiteController.php
new file mode 100644
index 0000000..8d3084c
--- /dev/null
+++ b/protected/controllers/SiteController.php
@@ -0,0 +1,103 @@
+array(
+ 'class'=>'CCaptchaAction',
+ 'backColor'=>0xFFFFFF,
+ ),
+ // page action renders "static" pages stored under 'protected/views/site/pages'
+ // They can be accessed via: index.php?r=site/page&view=FileName
+ 'page'=>array(
+ 'class'=>'CViewAction',
+ ),
+ );
+ }
+
+ /**
+ * This is the default 'index' action that is invoked
+ * when an action is not explicitly requested by users.
+ */
+ public function actionIndex()
+ {
+ // renders the view file 'protected/views/site/index.php'
+ // using the default layout 'protected/views/layouts/main.php'
+ $this->render('index');
+ }
+
+ /**
+ * This is the action to handle external exceptions.
+ */
+ public function actionError()
+ {
+ if($error=Yii::app()->errorHandler->error)
+ {
+ if(Yii::app()->request->isAjaxRequest)
+ echo $error['message'];
+ else
+ $this->render('error', $error);
+ }
+ }
+
+ /**
+ * Displays the contact page
+ */
+ public function actionContact()
+ {
+ $model=new ContactForm;
+ if(isset($_POST['ContactForm']))
+ {
+ $model->attributes=$_POST['ContactForm'];
+ if($model->validate())
+ {
+ $headers="From: {$model->email}\r\nReply-To: {$model->email}";
+ mail(Yii::app()->params['adminEmail'],$model->subject,$model->body,$headers);
+ Yii::app()->user->setFlash('contact','Thank you for contacting us. We will respond to you as soon as possible.');
+ $this->refresh();
+ }
+ }
+ $this->render('contact',array('model'=>$model));
+ }
+
+ /**
+ * Displays the login page
+ */
+ public function actionLogin()
+ {
+ $model=new LoginForm;
+
+ // if it is ajax validation request
+ if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')
+ {
+ echo CActiveForm::validate($model);
+ Yii::app()->end();
+ }
+
+ // collect user input data
+ if(isset($_POST['LoginForm']))
+ {
+ $model->attributes=$_POST['LoginForm'];
+ // validate user input and redirect to the previous page if valid
+ if($model->validate() && $model->login())
+ $this->redirect(Yii::app()->user->returnUrl);
+ }
+ // display the login form
+ $this->render('login',array('model'=>$model));
+ }
+
+ /**
+ * Logs out the current user and redirect to homepage.
+ */
+ public function actionLogout()
+ {
+ Yii::app()->user->logout();
+ $this->redirect(Yii::app()->homeUrl);
+ }
+}
\ No newline at end of file
diff --git a/protected/data/schema.mysql.sql b/protected/data/schema.mysql.sql
new file mode 100644
index 0000000..32788bd
--- /dev/null
+++ b/protected/data/schema.mysql.sql
@@ -0,0 +1,28 @@
+CREATE TABLE tbl_user (
+ id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ username VARCHAR(128) NOT NULL,
+ password VARCHAR(128) NOT NULL,
+ email VARCHAR(128) NOT NULL
+);
+
+INSERT INTO tbl_user (username, password, email) VALUES ('test1', 'pass1', 'test1@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test2', 'pass2', 'test2@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test3', 'pass3', 'test3@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test4', 'pass4', 'test4@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test5', 'pass5', 'test5@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test6', 'pass6', 'test6@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test7', 'pass7', 'test7@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test8', 'pass8', 'test8@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test9', 'pass9', 'test9@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test10', 'pass10', 'test10@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test11', 'pass11', 'test11@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test12', 'pass12', 'test12@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test13', 'pass13', 'test13@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test14', 'pass14', 'test14@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test15', 'pass15', 'test15@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test16', 'pass16', 'test16@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test17', 'pass17', 'test17@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test18', 'pass18', 'test18@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test19', 'pass19', 'test19@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test20', 'pass20', 'test20@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test21', 'pass21', 'test21@example.com');
diff --git a/protected/data/schema.sqlite.sql b/protected/data/schema.sqlite.sql
new file mode 100644
index 0000000..e5e0830
--- /dev/null
+++ b/protected/data/schema.sqlite.sql
@@ -0,0 +1,28 @@
+CREATE TABLE tbl_user (
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ username VARCHAR(128) NOT NULL,
+ password VARCHAR(128) NOT NULL,
+ email VARCHAR(128) NOT NULL
+);
+
+INSERT INTO tbl_user (username, password, email) VALUES ('test1', 'pass1', 'test1@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test2', 'pass2', 'test2@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test3', 'pass3', 'test3@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test4', 'pass4', 'test4@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test5', 'pass5', 'test5@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test6', 'pass6', 'test6@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test7', 'pass7', 'test7@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test8', 'pass8', 'test8@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test9', 'pass9', 'test9@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test10', 'pass10', 'test10@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test11', 'pass11', 'test11@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test12', 'pass12', 'test12@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test13', 'pass13', 'test13@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test14', 'pass14', 'test14@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test15', 'pass15', 'test15@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test16', 'pass16', 'test16@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test17', 'pass17', 'test17@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test18', 'pass18', 'test18@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test19', 'pass19', 'test19@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test20', 'pass20', 'test20@example.com');
+INSERT INTO tbl_user (username, password, email) VALUES ('test21', 'pass21', 'test21@example.com');
diff --git a/protected/data/testdrive.db b/protected/data/testdrive.db
new file mode 100755
index 0000000..0672b21
Binary files /dev/null and b/protected/data/testdrive.db differ
diff --git a/protected/models/ContactForm.php b/protected/models/ContactForm.php
new file mode 100644
index 0000000..86541cb
--- /dev/null
+++ b/protected/models/ContactForm.php
@@ -0,0 +1,42 @@
+!CCaptcha::checkRequirements()),
+ );
+ }
+
+ /**
+ * Declares customized attribute labels.
+ * If not declared here, an attribute would have a label that is
+ * the same as its name with the first letter in upper case.
+ */
+ public function attributeLabels()
+ {
+ return array(
+ 'verifyCode'=>'Verification Code',
+ );
+ }
+}
\ No newline at end of file
diff --git a/protected/models/LoginForm.php b/protected/models/LoginForm.php
new file mode 100644
index 0000000..eb36e4a
--- /dev/null
+++ b/protected/models/LoginForm.php
@@ -0,0 +1,77 @@
+'Remember me next time',
+ );
+ }
+
+ /**
+ * Authenticates the password.
+ * This is the 'authenticate' validator as declared in rules().
+ */
+ public function authenticate($attribute,$params)
+ {
+ if(!$this->hasErrors())
+ {
+ $this->_identity=new UserIdentity($this->username,$this->password);
+ if(!$this->_identity->authenticate())
+ $this->addError('password','Incorrect username or password.');
+ }
+ }
+
+ /**
+ * Logs in the user using the given username and password in the model.
+ * @return boolean whether login is successful
+ */
+ public function login()
+ {
+ if($this->_identity===null)
+ {
+ $this->_identity=new UserIdentity($this->username,$this->password);
+ $this->_identity->authenticate();
+ }
+ if($this->_identity->errorCode===UserIdentity::ERROR_NONE)
+ {
+ $duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days
+ Yii::app()->user->login($this->_identity,$duration);
+ return true;
+ }
+ else
+ return false;
+ }
+}
diff --git a/protected/tests/WebTestCase.php b/protected/tests/WebTestCase.php
new file mode 100644
index 0000000..d252bba
--- /dev/null
+++ b/protected/tests/WebTestCase.php
@@ -0,0 +1,25 @@
+setBrowserUrl(TEST_BASE_URL);
+ }
+}
diff --git a/protected/tests/bootstrap.php b/protected/tests/bootstrap.php
new file mode 100644
index 0000000..4142451
--- /dev/null
+++ b/protected/tests/bootstrap.php
@@ -0,0 +1,10 @@
+open('');
+ $this->assertTextPresent('Welcome');
+ }
+
+ public function testContact()
+ {
+ $this->open('?r=site/contact');
+ $this->assertTextPresent('Contact Us');
+ $this->assertElementPresent('name=ContactForm[name]');
+
+ $this->type('name=ContactForm[name]','tester');
+ $this->type('name=ContactForm[email]','tester@example.com');
+ $this->type('name=ContactForm[subject]','test subject');
+ $this->click("//input[@value='Submit']");
+ $this->assertTextPresent('Body cannot be blank.');
+ }
+
+ public function testLoginLogout()
+ {
+ $this->open('');
+ // ensure the user is logged out
+ if($this->isTextPresent('Logout'))
+ $this->clickAndWait('link=Logout (demo)');
+
+ // test login process, including validation
+ $this->clickAndWait('link=Login');
+ $this->assertElementPresent('name=LoginForm[username]');
+ $this->type('name=LoginForm[username]','demo');
+ $this->click("//input[@value='Login']");
+ $this->assertTextPresent('Password cannot be blank.');
+ $this->type('name=LoginForm[password]','demo');
+ $this->clickAndWait("//input[@value='Login']");
+ $this->assertTextNotPresent('Password cannot be blank.');
+ $this->assertTextPresent('Logout');
+
+ // test logout process
+ $this->assertTextNotPresent('Login');
+ $this->clickAndWait('link=Logout (demo)');
+ $this->assertTextPresent('Login');
+ }
+}
diff --git a/protected/tests/phpunit.xml b/protected/tests/phpunit.xml
new file mode 100644
index 0000000..22c96ff
--- /dev/null
+++ b/protected/tests/phpunit.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/protected/views/layouts/column1.php b/protected/views/layouts/column1.php
new file mode 100644
index 0000000..7b268a8
--- /dev/null
+++ b/protected/views/layouts/column1.php
@@ -0,0 +1,7 @@
+beginContent('//layouts/main'); ?>
+
+endContent(); ?>
\ No newline at end of file
diff --git a/protected/views/layouts/column2.php b/protected/views/layouts/column2.php
new file mode 100644
index 0000000..62df16f
--- /dev/null
+++ b/protected/views/layouts/column2.php
@@ -0,0 +1,23 @@
+beginContent('//layouts/main'); ?>
+
+endContent(); ?>
\ No newline at end of file
diff --git a/protected/views/layouts/main.php b/protected/views/layouts/main.php
new file mode 100644
index 0000000..2150a1b
--- /dev/null
+++ b/protected/views/layouts/main.php
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pageTitle); ?>
+
+
+
+
+
+
+
+
+
+ widget('zii.widgets.CMenu',array(
+ 'items'=>array(
+ array('label'=>'Home', 'url'=>array('/site/index')),
+ array('label'=>'About', 'url'=>array('/site/page', 'view'=>'about')),
+ array('label'=>'Contact', 'url'=>array('/site/contact')),
+ array('label'=>'Login', 'url'=>array('/site/login'), 'visible'=>Yii::app()->user->isGuest),
+ array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('/site/logout'), 'visible'=>!Yii::app()->user->isGuest)
+ ),
+ )); ?>
+
+ breadcrumbs)):?>
+ widget('zii.widgets.CBreadcrumbs', array(
+ 'links'=>$this->breadcrumbs,
+ )); ?>
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/protected/views/site/contact.php b/protected/views/site/contact.php
new file mode 100644
index 0000000..51f90a9
--- /dev/null
+++ b/protected/views/site/contact.php
@@ -0,0 +1,81 @@
+pageTitle=Yii::app()->name . ' - Contact Us';
+$this->breadcrumbs=array(
+ 'Contact',
+);
+?>
+
+Contact Us
+
+user->hasFlash('contact')): ?>
+
+
+ user->getFlash('contact'); ?>
+
+
+
+
+
+If you have business inquiries or other questions, please fill out the following form to contact us. Thank you.
+
+
+
+
+beginWidget('CActiveForm', array(
+ 'id'=>'contact-form',
+ 'enableClientValidation'=>true,
+ 'clientOptions'=>array(
+ 'validateOnSubmit'=>true,
+ ),
+)); ?>
+
+
Fields with * are required.
+
+ errorSummary($model); ?>
+
+
+ labelEx($model,'name'); ?>
+ textField($model,'name'); ?>
+ error($model,'name'); ?>
+
+
+
+ labelEx($model,'email'); ?>
+ textField($model,'email'); ?>
+ error($model,'email'); ?>
+
+
+
+ labelEx($model,'subject'); ?>
+ textField($model,'subject',array('size'=>60,'maxlength'=>128)); ?>
+ error($model,'subject'); ?>
+
+
+
+ labelEx($model,'body'); ?>
+ textArea($model,'body',array('rows'=>6, 'cols'=>50)); ?>
+ error($model,'body'); ?>
+
+
+
+
+ labelEx($model,'verifyCode'); ?>
+
+ widget('CCaptcha'); ?>
+ textField($model,'verifyCode'); ?>
+
+
Please enter the letters as they are shown in the image above.
+ Letters are not case-sensitive.
+ error($model,'verifyCode'); ?>
+
+
+
+
+
+
+
+endWidget(); ?>
+
+
+
+
\ No newline at end of file
diff --git a/protected/views/site/error.php b/protected/views/site/error.php
new file mode 100644
index 0000000..4607ff3
--- /dev/null
+++ b/protected/views/site/error.php
@@ -0,0 +1,12 @@
+pageTitle=Yii::app()->name . ' - Error';
+$this->breadcrumbs=array(
+ 'Error',
+);
+?>
+
+Error
+
+
+
+
\ No newline at end of file
diff --git a/protected/views/site/index.php b/protected/views/site/index.php
new file mode 100644
index 0000000..b44b2e6
--- /dev/null
+++ b/protected/views/site/index.php
@@ -0,0 +1,16 @@
+pageTitle=Yii::app()->name; ?>
+
+Welcome to name); ?>
+
+Congratulations! You have successfully created your Yii application.
+
+You may change the content of this page by modifying the following two files:
+
+ View file:
+ Layout file: getLayoutFile('main'); ?>
+
+
+For more details on how to further develop this application, please read
+the documentation .
+Feel free to ask in the forum ,
+should you have any questions.
\ No newline at end of file
diff --git a/protected/views/site/login.php b/protected/views/site/login.php
new file mode 100644
index 0000000..c53bf62
--- /dev/null
+++ b/protected/views/site/login.php
@@ -0,0 +1,49 @@
+pageTitle=Yii::app()->name . ' - Login';
+$this->breadcrumbs=array(
+ 'Login',
+);
+?>
+
+Login
+
+Please fill out the following form with your login credentials:
+
+
diff --git a/protected/views/site/pages/about.php b/protected/views/site/pages/about.php
new file mode 100644
index 0000000..c6c05dc
--- /dev/null
+++ b/protected/views/site/pages/about.php
@@ -0,0 +1,10 @@
+pageTitle=Yii::app()->name . ' - About';
+$this->breadcrumbs=array(
+ 'About',
+);
+?>
+About
+
+This is a "static" page. You may change the content of this page
+by updating the file .
\ No newline at end of file
diff --git a/protected/yiic b/protected/yiic
new file mode 100755
index 0000000..7f56f54
--- /dev/null
+++ b/protected/yiic
@@ -0,0 +1,4 @@
+#!/usr/bin/env php
+