diff options
| author | wei <> | 2006-07-16 06:19:36 +0000 | 
|---|---|---|
| committer | wei <> | 2006-07-16 06:19:36 +0000 | 
| commit | c7d41e5bea4a5f96979a08da9cc9f79355edfe70 (patch) | |
| tree | 8f21cba052c1eae7c7204ac272dd8c5e9d6fe110 | |
| parent | af68030fcf0c266300feb2c100149ecadef7d364 (diff) | |
Update Time Tracker demo.
76 files changed, 1889 insertions, 374 deletions
diff --git a/.gitattributes b/.gitattributes index 3127d88f..6cdc6483 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1011,13 +1011,8 @@ demos/soap/protected/pages/Home.php -text  demos/soap/protected/webservices/SimpleService.php -text  demos/sqlmap/index.php -text  demos/sqlmap/protected/.htaccess -text +demos/sqlmap/protected/APP_CODE/Person.php -text  demos/sqlmap/protected/application.xml -text -demos/sqlmap/protected/business-objects/Person.php -text -demos/sqlmap/protected/controls/Layout.php -text -demos/sqlmap/protected/controls/Layout.tpl -text -demos/sqlmap/protected/controls/TopicList.php -text -demos/sqlmap/protected/controls/TopicList.tpl -text -demos/sqlmap/protected/pages/Home.page -text  demos/sqlmap/protected/pages/Manual/BigPicture.page -text  demos/sqlmap/protected/pages/Manual/BuildingTSqlMapper.page -text  demos/sqlmap/protected/pages/Manual/CacheModels.page -text @@ -1033,6 +1028,8 @@ demos/sqlmap/protected/pages/Manual/ImplicitResultMaps.page -text  demos/sqlmap/protected/pages/Manual/InheritanceMapping.page -text  demos/sqlmap/protected/pages/Manual/InlineParameterMaps.page -text  demos/sqlmap/protected/pages/Manual/Installing.page -text +demos/sqlmap/protected/pages/Manual/Layout.php -text +demos/sqlmap/protected/pages/Manual/Layout.tpl -text  demos/sqlmap/protected/pages/Manual/MappedStatements.page -text  demos/sqlmap/protected/pages/Manual/Overview.page -text  demos/sqlmap/protected/pages/Manual/ParameterMap.page -text @@ -1040,6 +1037,14 @@ demos/sqlmap/protected/pages/Manual/ResultMapAttributes.page -text  demos/sqlmap/protected/pages/Manual/ResultMaps.page -text  demos/sqlmap/protected/pages/Manual/StatementElementAttributes.page -text  demos/sqlmap/protected/pages/Manual/TheSQL.page -text +demos/sqlmap/protected/pages/Manual/TopicList.php -text +demos/sqlmap/protected/pages/Manual/TopicList.tpl -text +demos/sqlmap/protected/pages/Manual/Tutorial/TestAgain.page -text +demos/sqlmap/protected/pages/Manual/Tutorial/TestFirst.page -text +demos/sqlmap/protected/pages/Manual/Tutorial/TestSecond.page -text +demos/sqlmap/protected/pages/Manual/Tutorial/example1.png -text +demos/sqlmap/protected/pages/Manual/Tutorial/grid1.png -text +demos/sqlmap/protected/pages/Manual/Tutorial/grid2.png -text  demos/sqlmap/protected/pages/Manual/WorkingWithDataMaps.page -text  demos/sqlmap/protected/pages/Manual/diagram.png -text  demos/sqlmap/protected/pages/Sample/Home.page -text @@ -1049,22 +1054,19 @@ demos/sqlmap/protected/pages/Sample/crud1.page -text  demos/sqlmap/protected/pages/Sample/crud1.php -text  demos/sqlmap/protected/pages/Sample/crud2.page -text  demos/sqlmap/protected/pages/Sample/crud2.php -text -demos/sqlmap/protected/pages/Tutorial/TestAgain.page -text -demos/sqlmap/protected/pages/Tutorial/TestFirst.page -text -demos/sqlmap/protected/pages/Tutorial/TestSecond.page -text -demos/sqlmap/protected/pages/Tutorial/example1.png -text -demos/sqlmap/protected/pages/Tutorial/grid1.png -text -demos/sqlmap/protected/pages/Tutorial/grid2.png -text -demos/sqlmap/protected/pages/config.xml -text  demos/time-tracker/index.php -text  demos/time-tracker/protected/.htaccess -text  demos/time-tracker/protected/APP_CODE/BaseDao.php -text +demos/time-tracker/protected/APP_CODE/DaoManager.php -text  demos/time-tracker/protected/APP_CODE/Project.php -text  demos/time-tracker/protected/APP_CODE/ProjectDao.php -text  demos/time-tracker/protected/APP_CODE/TimeTrackerException.php -text  demos/time-tracker/protected/APP_CODE/TimeTrackerUser.php -text +demos/time-tracker/protected/APP_CODE/TimeTrackerUserTypeHandler.php -text +demos/time-tracker/protected/APP_CODE/UserDao.php -text +demos/time-tracker/protected/APP_CODE/UserManager.php -text  demos/time-tracker/protected/APP_CODE/exceptions.txt -text -demos/time-tracker/protected/data/time_tracker.db -text +demos/time-tracker/protected/App_Data/time_tracker.db -text  demos/time-tracker/protected/pages/Docs/CreateBusinessCode.page -text  demos/time-tracker/protected/pages/Docs/GettingStarted.page -text  demos/time-tracker/protected/pages/Docs/Home.page -text @@ -1087,13 +1089,28 @@ demos/time-tracker/protected/pages/Docs/project1.png -text  demos/time-tracker/protected/pages/Docs/unit_test1.png -text  demos/time-tracker/protected/pages/Docs/unit_test2.png -text  demos/time-tracker/protected/pages/Docs/unit_test3.png -text +demos/time-tracker/protected/pages/TimeTracker/Login.page -text +demos/time-tracker/protected/pages/TimeTracker/Login.php -text +demos/time-tracker/protected/pages/TimeTracker/Logout.page -text +demos/time-tracker/protected/pages/TimeTracker/Logout.php -text +demos/time-tracker/protected/pages/TimeTracker/MainLayout.php -text +demos/time-tracker/protected/pages/TimeTracker/MainLayout.tpl -text +demos/time-tracker/protected/pages/TimeTracker/SiteMap.php -text +demos/time-tracker/protected/pages/TimeTracker/SiteMap.tpl -text +demos/time-tracker/protected/pages/TimeTracker/UserCreate.page -text +demos/time-tracker/protected/pages/TimeTracker/UserCreate.php -text +demos/time-tracker/protected/pages/TimeTracker/UserList.page -text +demos/time-tracker/protected/pages/TimeTracker/config.xml -text +demos/time-tracker/protected/pages/Welcome.page -text  demos/time-tracker/tests/functional.php -text  demos/time-tracker/tests/functional/HelloPradoTestCase.php -text  demos/time-tracker/tests/unit.php -text -demos/time-tracker/tests/unit/AddUserToProjectTestCase.php -text -demos/time-tracker/tests/unit/CreateNewProjectTestCase.php -text -demos/time-tracker/tests/unit/ProjectDaoTestCase.php -text +demos/time-tracker/tests/unit/BaseTestCase.php -text  demos/time-tracker/tests/unit/ProjectTestCase.php -text +demos/time-tracker/tests/unit/UserDaoTestCase.php -text +demos/time-tracker/themes/TimeTracker/background.png -text +demos/time-tracker/themes/TimeTracker/site.css -text +demos/time-tracker/themes/TimeTracker/tabs.png -text  docs/application.xml -text  docs/specs/application.dtd -text  docs/specs/application.xsd -text diff --git a/buildscripts/texbuilder/quickstart/build.php b/buildscripts/texbuilder/quickstart/build.php index c0577c8f..79d6d7ec 100644 --- a/buildscripts/texbuilder/quickstart/build.php +++ b/buildscripts/texbuilder/quickstart/build.php @@ -8,7 +8,7 @@ $pdfTex = "$pdflatexExec -interaction=nonstopmode -max-print-line=120 %s";  $mainTexFile = dirname(__FILE__).'/quickstart.tex';
  //page root location
 -$base = realpath(dirname(__FILE__).'/../../demos/quickstart/protected/pages/');
 +$base = realpath(dirname(__FILE__).'/../../../demos/quickstart/protected/pages/');
  //-------------- END CONFIG ------------------
 diff --git a/buildscripts/texbuilder/sqlmap/build.php b/buildscripts/texbuilder/sqlmap/build.php index 5717c50c..46773390 100644 --- a/buildscripts/texbuilder/sqlmap/build.php +++ b/buildscripts/texbuilder/sqlmap/build.php @@ -8,7 +8,7 @@ $pdfTex = "$pdflatexExec -interaction=nonstopmode -max-print-line=120 %s";  $mainTexFile = dirname(__FILE__).'/sqlmap.tex';
  //page root location
 -$base = realpath(dirname(__FILE__).'/../protected/pages/');
 +$base = realpath(dirname(__FILE__).'/../../../demos/sqlmap/protected/pages/');
  //-------------- END CONFIG ------------------
 diff --git a/buildscripts/texbuilder/sqlmap/pages.php b/buildscripts/texbuilder/sqlmap/pages.php index 411ebc4c..adf788ff 100644 --- a/buildscripts/texbuilder/sqlmap/pages.php +++ b/buildscripts/texbuilder/sqlmap/pages.php @@ -13,9 +13,9 @@ $pages['Installation and Setup'] = array(  );
  $pages['SQLMap for PHP Tutorial'] = array(
 -	'Tutorial/TestFirst.page',
 -	'Tutorial/TestSecond.page',
 -	'Tutorial/TestAgain.page'
 +	'Manual/Tutorial/TestFirst.page',
 +	'Manual/Tutorial/TestSecond.page',
 +	'Manual/Tutorial/TestAgain.page'
  );
  $pages['Using SQLMap DataMapper'] = array(
 diff --git a/buildscripts/texbuilder/time-tracker/db.vsd b/buildscripts/texbuilder/time-tracker/db.vsd Binary files differindex aa32902d..b12bb87b 100644 --- a/buildscripts/texbuilder/time-tracker/db.vsd +++ b/buildscripts/texbuilder/time-tracker/db.vsd diff --git a/buildscripts/texbuilder/time-tracker/pages.php b/buildscripts/texbuilder/time-tracker/pages.php index ccad934d..5ec3335a 100644 --- a/buildscripts/texbuilder/time-tracker/pages.php +++ b/buildscripts/texbuilder/time-tracker/pages.php @@ -1,21 +1,17 @@  <?php
 -$pages['preface'] = array(
 -	'preface.page'
 -	);
 -
  //list page into chapters
  $pages['Getting Started'] = array(
 -	'Introduction.page',
 -	'GettingStarted.page',
 -	'WritingUnitTest.page',
 -	'WritingFunctionalTest.page'
 +	'Docs/Introduction.page',
 +	'Docs/GettingStarted.page',
 +	'Docs/WritingUnitTest.page',
 +	'Docs/WritingFunctionalTest.page'
  	);
  $pages['Testing Business Code'] = array(
 -	'CreateBusinessCode.page',
 -	'UsingSQLMap.page',
 -	'UserClassAndExceptions.page'
 +	'Docs/CreateBusinessCode.page',
 +	'Docs/UsingSQLMap.page',
 +	'Docs/UserClassAndExceptions.page'
  	);
  return $pages;
 diff --git a/buildscripts/texbuilder/time-tracker/time-tracker.tex b/buildscripts/texbuilder/time-tracker/time-tracker.tex index 739151a2..fcfb639a 100644 --- a/buildscripts/texbuilder/time-tracker/time-tracker.tex +++ b/buildscripts/texbuilder/time-tracker/time-tracker.tex @@ -42,6 +42,17 @@  \fancyhead[RE]{\nouppercase{\scshape\leftmark}}
  %-----------------------------------------------------------------------
 +
 +% boxes
 +
 +\newsavebox{\fmboxb}
 +\newenvironment{mybox}
 +    {\vspace{-2mm}\begin{center}\begin{lrbox}{\fmboxb}\hspace{2mm}
 +        \begin{minipage}{0.85\textwidth} \vspace{2mm}\small}
 +    {  \vspace{2mm} \end{minipage}
 +    \hspace{2mm}\end{lrbox}\fbox{\usebox{\fmboxb}}\end{center}}
 +
 +
  %----------------- TITLE --------------
  \title{\Huge{\bfseries{Time Tracker}}\\ \LARGE A PRADO Application
 diff --git a/demos/sqlmap/protected/business-objects/Person.php b/demos/sqlmap/protected/APP_CODE/Person.php index ad9da4b3..ad9da4b3 100644 --- a/demos/sqlmap/protected/business-objects/Person.php +++ b/demos/sqlmap/protected/APP_CODE/Person.php diff --git a/demos/sqlmap/protected/application.xml b/demos/sqlmap/protected/application.xml index 7cfb440f..7dcde037 100644 --- a/demos/sqlmap/protected/application.xml +++ b/demos/sqlmap/protected/application.xml @@ -1,16 +1,11 @@  <?xml version="1.0" encoding="utf-8"?>
  <application id="Database" Mode="Debug">
    <paths>
 -	<alias id="Example" path="business-objects" />
 +	<alias id="Example" path="APP_CODE" />
 +	<alias id="Quickstart" path="../../quickstart" />
 +	<using namespace="Quickstart.protected.controls.*" />
    </paths>
 -  <modules>
 -  	<module id="cache" class="System.Caching.TSqliteCache" />
 -  	<module id="petshop-sqlmap" 
 -  			enableConfigCache="true"
 -  			class="System.DataAccess.TSQLMap" 
 -  			configFile="Application.petshop-sqlmap" />
 -  	<module id="person-sample"
 -  			class="System.DataAccess.TSQLMap"
 -  			configFile="Application.person-sqlmap" />
 -  </modules>
 +  <services>
 +    <service id="page" class="TPageService" DefaultPage="Manual.Overview" />
 +  </services>  
  </application>
\ No newline at end of file diff --git a/demos/sqlmap/protected/pages/Home.page b/demos/sqlmap/protected/pages/Home.page deleted file mode 100644 index ff226d4e..00000000 --- a/demos/sqlmap/protected/pages/Home.page +++ /dev/null @@ -1 +0,0 @@ -<h1>Welcome to Prado!</h1>
\ No newline at end of file diff --git a/demos/sqlmap/protected/controls/Layout.php b/demos/sqlmap/protected/pages/Manual/Layout.php index e612d52d..e612d52d 100644 --- a/demos/sqlmap/protected/controls/Layout.php +++ b/demos/sqlmap/protected/pages/Manual/Layout.php diff --git a/demos/sqlmap/protected/controls/Layout.tpl b/demos/sqlmap/protected/pages/Manual/Layout.tpl index c62cc046..7c47646d 100644 --- a/demos/sqlmap/protected/controls/Layout.tpl +++ b/demos/sqlmap/protected/pages/Manual/Layout.tpl @@ -23,7 +23,7 @@  <table width="100%" border="0" cellspacing="0" cellpadding="0">
  <tr>
  <td valign="top" width="1">
 -<com:Application.controls.TopicList ID="TopicPanel" />
 +<com:Application.pages.Manual.TopicList ID="TopicPanel" />
  </td>
  <td valign="top">
  <div id="content">
 diff --git a/demos/sqlmap/protected/pages/Manual/Overview.page b/demos/sqlmap/protected/pages/Manual/Overview.page index 694daf68..258be782 100644 --- a/demos/sqlmap/protected/pages/Manual/Overview.page +++ b/demos/sqlmap/protected/pages/Manual/Overview.page @@ -34,7 +34,15 @@ material applies to both implementations.  SQLMap PHP Developer Guide.</p>
  <p>A Tutorial is also available. We recommend reviewing the Tutorial for your
 -platform before reading this Guide.</p>
 +platform before reading this Guide.
 +
 +<a href="?page=Tutorial.TestFirst">SQLMap Tutorial</a>
 +<ul>
 +	<li><a href="index.php?page=Sample.crud1">Tutorial 1 Sample</a></li>
 +	<li><a href="index.php?page=Sample.crud2">Tutorial 2 Sample</a></li>
 +	<li><a href="index.php?page=Sample.ProductList">Product List Sample</a></li>
 +</ul>	
 +</p>
  <h1>Support</h1>
 diff --git a/demos/sqlmap/protected/controls/TopicList.php b/demos/sqlmap/protected/pages/Manual/TopicList.php index ce827cc0..ce827cc0 100644 --- a/demos/sqlmap/protected/controls/TopicList.php +++ b/demos/sqlmap/protected/pages/Manual/TopicList.php diff --git a/demos/sqlmap/protected/controls/TopicList.tpl b/demos/sqlmap/protected/pages/Manual/TopicList.tpl index 6c7a3e9e..58e6d9ae 100644 --- a/demos/sqlmap/protected/controls/TopicList.tpl +++ b/demos/sqlmap/protected/pages/Manual/TopicList.tpl @@ -16,9 +16,9 @@  <div>SQLMap for PHP Tutorial</div>
  <ul>
 -	<li><a href="?page=Tutorial.TestFirst">Test First!</a></li>
 -	<li><a href="?page=Tutorial.TestSecond">Playtest second!</a></li>
 -	<li><a href="?page=Tutorial.TestAgain">Test, test, again ...</a></li>
 +	<li><a href="?page=Manual.Tutorial.TestFirst">Test First!</a></li>
 +	<li><a href="?page=Manual.Tutorial.TestSecond">Playtest second!</a></li>
 +	<li><a href="?page=Manual.Tutorial.TestAgain">Test, test, again ...</a></li>
  </ul>
  <div>Using SQLMap DataMapper</div>
 diff --git a/demos/sqlmap/protected/pages/Tutorial/TestAgain.page b/demos/sqlmap/protected/pages/Manual/Tutorial/TestAgain.page index 4adac73b..4adac73b 100644 --- a/demos/sqlmap/protected/pages/Tutorial/TestAgain.page +++ b/demos/sqlmap/protected/pages/Manual/Tutorial/TestAgain.page diff --git a/demos/sqlmap/protected/pages/Tutorial/TestFirst.page b/demos/sqlmap/protected/pages/Manual/Tutorial/TestFirst.page index 80a155cb..80a155cb 100644 --- a/demos/sqlmap/protected/pages/Tutorial/TestFirst.page +++ b/demos/sqlmap/protected/pages/Manual/Tutorial/TestFirst.page diff --git a/demos/sqlmap/protected/pages/Tutorial/TestSecond.page b/demos/sqlmap/protected/pages/Manual/Tutorial/TestSecond.page index 706b5220..706b5220 100644 --- a/demos/sqlmap/protected/pages/Tutorial/TestSecond.page +++ b/demos/sqlmap/protected/pages/Manual/Tutorial/TestSecond.page diff --git a/demos/sqlmap/protected/pages/Tutorial/example1.png b/demos/sqlmap/protected/pages/Manual/Tutorial/example1.png Binary files differindex b5241de6..b5241de6 100644 --- a/demos/sqlmap/protected/pages/Tutorial/example1.png +++ b/demos/sqlmap/protected/pages/Manual/Tutorial/example1.png diff --git a/demos/sqlmap/protected/pages/Tutorial/grid1.png b/demos/sqlmap/protected/pages/Manual/Tutorial/grid1.png Binary files differindex 845b9581..845b9581 100644 --- a/demos/sqlmap/protected/pages/Tutorial/grid1.png +++ b/demos/sqlmap/protected/pages/Manual/Tutorial/grid1.png diff --git a/demos/sqlmap/protected/pages/Tutorial/grid2.png b/demos/sqlmap/protected/pages/Manual/Tutorial/grid2.png Binary files differindex dcafc33d..dcafc33d 100644 --- a/demos/sqlmap/protected/pages/Tutorial/grid2.png +++ b/demos/sqlmap/protected/pages/Manual/Tutorial/grid2.png diff --git a/demos/sqlmap/protected/pages/config.xml b/demos/sqlmap/protected/pages/config.xml deleted file mode 100644 index e0850c2c..00000000 --- a/demos/sqlmap/protected/pages/config.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
 -
 -<configuration>
 -  <paths>
 -    <alias id="Pages" path="." />
 -  </paths>
 -  <pages MasterClass="Application.controls.Layout" Theme="PradoSoft" />
 -</configuration>
\ No newline at end of file diff --git a/demos/time-tracker/protected/APP_CODE/BaseDao.php b/demos/time-tracker/protected/APP_CODE/BaseDao.php index f9146b59..63b91def 100644 --- a/demos/time-tracker/protected/APP_CODE/BaseDao.php +++ b/demos/time-tracker/protected/APP_CODE/BaseDao.php @@ -1,14 +1,41 @@  <?php
 +/**
 + * Base DAO class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2006 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + */
 +/**
 + * Base DAO class.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + * @since 3.1
 + */
  class BaseDao
  {
 +	/**
 +	 * @var TSqlMapper sqlmap client.
 +	 */
  	private $_connection;
 +	/**
 +	 * @param TSqlMapper sqlmap client.
 +	 */
  	public function setConnection($connection)
  	{
  		$this->_connection = $connection;
  	}
 +	/**
 +	 * @return TSqlMapper sqlmap client.
 +	 */
  	protected function getConnection()
  	{
  		return $this->_connection;
 diff --git a/demos/time-tracker/protected/APP_CODE/DaoManager.php b/demos/time-tracker/protected/APP_CODE/DaoManager.php new file mode 100644 index 00000000..b8ac55af --- /dev/null +++ b/demos/time-tracker/protected/APP_CODE/DaoManager.php @@ -0,0 +1,126 @@ +<?php
 +/**
 + * DaoManager class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2006 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + */
 + 
 +/**
 + * DaoManager class.
 + * 
 + * A Registry for Dao and an implementation of that type.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + * @since 3.1
 + */
 +class DaoManager extends TModule
 +{
 +	/**
 +	 * @var TSqlMapper sqlmap client
 +	 */
 +	private $_connection;
 +	/**
 +	 * @var boolean if the module has been initialized
 +	 */
 +	private $_initialized=false;	
 +	/**
 +	 * @var array registered list of dao
 +	 */
 +	private $_dao=array();
 +	/**
 +	 * Initializes the module.
 +	 * This method is required by IModule and is invoked by application.
 +	 * It loads dao information from the module configuration.
 +	 * @param TXmlElement module configuration
 +	 */
 +	public function init($config)
 +	{ 	
 +		if($this->_connection === null)
 +			throw new TimeTrackerException('daomanager_connection_required');
 +		$app = $this->getApplication();
 +		if(is_string($this->_connection))
 +		{
 +			if(($conn=$app->getModule($this->_connection)->getClient())===null)
 +				throw new TimeTrackerException('daomanager_undefined_connection',$this->_connection);
 +			if(!($conn instanceof TSqlMapper))
 +				throw new TimeTrackerException('daomanager_invalid_connection',	$this->_connection);
 +			$this->_connection = $conn;
 +		}
 +		$this->includeDaoImplementation($config->getElementsByTagName('dao'));
 +		$this->_initialized = true;
 +	}
 +	
 +	/**
 +	 * Register the dao type and implementation class names.
 +	 * @param array list of TXmlDocument nodes.
 +	 */
 +	protected function includeDaoImplementation($nodes)
 +	{
 +		foreach($nodes as $node)
 +		{
 +			$id = $node->getAttribute('id');
 +			$class = $node->getAttribute('class');
 +			$this->_dao[$id] = array('class' => $class);
 +		}
 +	}
 +	
 +	/**
 +	 * @return array list of registered Daos
 +	 */
 +	public function getDaos()
 +	{
 +		return $this->_dao;
 +	}
 +	
 +	/**
 +	 * Returns an implementation of a Dao type, implements the Registery
 +	 * pattern. Multiple calls returns the same Dao instance.
 +	 * @param string Dao type to find.
 +	 * @return object instance of the Dao implementation.
 +	 */
 +	public function getDao($class)
 +	{
 +		if(isset($this->_dao[$class]))
 +		{
 +			if(!isset($this->_dao[$class]['instance']))
 +			{
 +				$dao = Prado::createComponent($this->_dao[$class]['class']);
 +				$dao->setConnection($this->getConnection());
 +				$this->_dao[$class]['instance'] = $dao;	
 +			}
 +			return $this->_dao[$class]['instance'];
 +		}
 +		else
 +			throw TimeTrackerException('daomanager_undefined_dao', $class);
 +	}
 +	
 +	/**
 +	 * @return TSqlMapper sqlmap client instance
 +	 */
 +	public function getConnection()
 +	{
 +		return $this->_connection;
 +	}
 +	
 +	/**
 +	 * Sets the connection for all Daos registered.
 +	 * @param string|TSqlMapper sqlmap client module id or TSqlMapper instance.
 +	 */
 +	public function setConnection($client)
 +	{
 +		if($this->_initialized)
 +			throw new TimeTrackerException('daomanager_unchangeable');
 +		if(!is_string($client) && !($client instanceof TSqlMapper))
 +			throw new TConfigurationException('daomanager_invalid_connection',$client);
 +		$this->_connection = $client;
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/demos/time-tracker/protected/APP_CODE/Project.php b/demos/time-tracker/protected/APP_CODE/Project.php index ad9f7d19..660fad04 100644 --- a/demos/time-tracker/protected/APP_CODE/Project.php +++ b/demos/time-tracker/protected/APP_CODE/Project.php @@ -1,5 +1,23 @@  <?php
 +/**
 + * Project class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2006 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + */
 +/**
 + * Time Tracker Project class.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + * @since 3.1
 + */
  class Project
  {
  	public $ActualDuration = 0;
 diff --git a/demos/time-tracker/protected/APP_CODE/ProjectDao.php b/demos/time-tracker/protected/APP_CODE/ProjectDao.php index 25a2845d..81902e0c 100644 --- a/demos/time-tracker/protected/APP_CODE/ProjectDao.php +++ b/demos/time-tracker/protected/APP_CODE/ProjectDao.php @@ -1,10 +1,26 @@  <?php
 +/**
 + * Project DAO class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2006 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + */
 -Prado::using('Application.APP_CODE.BaseDao');
 -
 +/**
 + * Project DAO class.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + * @since 3.1
 + */
  class ProjectDao extends BaseDao
  {
 -	public function createNewProject($project)
 +/*	public function createNewProject($project)
  	{
  		$sqlmap = $this->getConnection();
  		$creator = $sqlmap->queryForObject('GetUserByName', $project->CreatorUserName);
 @@ -71,6 +87,7 @@ class ProjectDao extends BaseDao  			return $sqlmap->insert('AddUserToProject', $param);
  		}	
  	}
 +*/
  }
  ?>
\ No newline at end of file diff --git a/demos/time-tracker/protected/APP_CODE/TimeTrackerException.php b/demos/time-tracker/protected/APP_CODE/TimeTrackerException.php index d715eefa..64b11405 100644 --- a/demos/time-tracker/protected/APP_CODE/TimeTrackerException.php +++ b/demos/time-tracker/protected/APP_CODE/TimeTrackerException.php @@ -1,5 +1,24 @@  <?php
 +/**
 + * TimeTrackerException class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2006 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + */
 +/**
 + * Generic time tracker application exception. Exception messages are saved in
 + * "exceptions.txt"
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + * @since 3.1
 + */
  class TimeTrackerException extends TException
  {
  	/**
 diff --git a/demos/time-tracker/protected/APP_CODE/TimeTrackerUser.php b/demos/time-tracker/protected/APP_CODE/TimeTrackerUser.php index 4b6987bd..99ac1209 100644 --- a/demos/time-tracker/protected/APP_CODE/TimeTrackerUser.php +++ b/demos/time-tracker/protected/APP_CODE/TimeTrackerUser.php @@ -1,31 +1,48 @@  <?php
 +/**
 + * TimeTrackerUser class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2006 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + */
 +/**
 + * Import TUser and TUserManager
 + */
  Prado::using('System.Security.TUser');
  Prado::using('System.Security.TUserManager');
 +/**
 + * User class for Time Tracker application.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + * @since 3.1
 + */
  class TimeTrackerUser extends TUser
  {
 -	private $_ID;
 +	private $_emailAddress;
 -	public function __construct()
 +	/**
 +	 * @param string user email address
 +	 */
 +	public function setEmailAddress($value)
  	{
 -		parent::__construct(new TUserManager());
 +		$this->_emailAddress = $value;
  	}
 -		
 -	public function getID(){ return $this->_ID; }
 -	public function setID($value)
 -	{ 
 -		if(is_null($this->_ID))
 -			$this->_ID = $value;
 -		else
 -			throw new TimeTrackerUserException(
 -				'timetracker_user_readonly_id');
 -	}
 -}
 -
 -class TimeTrackerUserException extends TimeTrackerException
 -{
 +	/**
 +	 * @return string user email address
 +	 */
 +	public function getEmailAddress()
 +	{
 +		return $this->_emailAddress;
 +	}
  }
  ?>
\ No newline at end of file diff --git a/demos/time-tracker/protected/APP_CODE/TimeTrackerUserTypeHandler.php b/demos/time-tracker/protected/APP_CODE/TimeTrackerUserTypeHandler.php new file mode 100644 index 00000000..07c46acc --- /dev/null +++ b/demos/time-tracker/protected/APP_CODE/TimeTrackerUserTypeHandler.php @@ -0,0 +1,54 @@ +<?php
 +/**
 + * TimeTrackerUserTypeHandler class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2006 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + */
 +
 +/**
 + * SQLMap type handler for TimeTrackerUser.
 + * The TimeTrackerUser requires an instance of IUserManager in constructor.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + * @since 3.1
 + */
 +class TimeTrackerUserTypeHandler implements ITypeHandlerCallback
 +{
 +	/**
 +	 * Not implemented.
 +	 */
 +	public function getParameter($object)
 +	{
 +		throw new TimeTrackerException('Not implemented');
 +	}
 +
 +	/**
 +	 * Not implemented.
 +	 */
 +	public function getResult($string)
 +	{
 +		throw new TimeTrackerException('Not implemented');		
 +	}
 +
 +	/**
 +	 * Creates a new instance of TimeTrackerUser
 +	 * @param array result data
 +	 * @return TimeTrackerUser new user instance
 +	 */
 +	public function createNewInstance($row=null)
 +	{
 +		$manager = Prado::getApplication()->getModule('users');
 +		if(is_null($manager))
 +			$manager = new UserManager();
 +		return new TimeTrackerUser($manager);
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/demos/time-tracker/protected/APP_CODE/UserDao.php b/demos/time-tracker/protected/APP_CODE/UserDao.php new file mode 100644 index 00000000..4dc39b2b --- /dev/null +++ b/demos/time-tracker/protected/APP_CODE/UserDao.php @@ -0,0 +1,155 @@ +<?php
 +/**
 + * User Dao class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2006 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + */
 +
 +/**
 + * UserDao class list, create, find and delete users. 
 + * In addition, it can validate username and password, and update
 + * the user roles. Furthermore, a unique new token can be generated,
 + * this token can be used to perform persistent cookie login.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + * @since 3.1
 + */
 +class UserDao extends BaseDao
 +{
 +	/**
 +	 * @param string username
 +	 * @return TimeTrackerUser find by user name, null if not found or disabled.
 +	 */
 +	public function getUserByName($username)
 +	{
 +		$sqlmap = $this->getConnection();
 +		return $sqlmap->queryForObject('GetUserByName', $username);	
 +	}
 +	
 +	/**
 +	 * @return array list of all enabled users.
 +	 */
 +	public function getAllUsers()
 +	{
 +		$sqlmap = $this->getConnection();
 +		return $sqlmap->queryForList('GetAllUsers');
 +	}
 +	
 +	/**
 +	 * @param TimeTrackerUser new user details.
 +	 * @param string new user password.
 +	 */
 +	public function addNewUser($user, $password)
 +	{
 +		$sqlmap = $this->getConnection();
 +		$param['user'] = $user;
 +		$param['password'] = md5($password);
 +		$sqlmap->insert('AddNewUser', $param);
 +		if(count($user->getRoles()) > 0)
 +			$this->updateUserRoles($user);
 +	}
 +	
 +	/**
 +	 * @param string username to delete
 +	 */
 +	public function deleteUserByName($username)
 +	{
 +		$sqlmap = $this->getConnection();
 +		$sqlmap->delete('DeleteUserByName', $username);
 +	}
 +
 +	/**
 +	 * Updates the user profile details, including user roles.
 +	 * @param TimeTrackerUser updated user details.
 +	 * @param string new user password, null to avoid updating password.
 +	 */
 +	public function updateUser($user,$password=null)
 +	{
 +		$sqlmap = $this->getConnection();
 +		if($password !== null)
 +		{
 +			$param['user'] = $user;
 +			$param['password'] = md5($password);
 +			$sqlmap->update('UpdateUserDetailsAndPassword', $param);
 +		}
 +		else
 +		{
 +			$sqlmap->update('UpdateUserDetails', $user);
 +		}
 +		$this->updateUserRoles($user);
 +	}
 +
 +	/**
 +	 * @param string username to be validated
 +	 * @param string matching password
 +	 * @return boolean true if the username and password matches.
 +	 */
 +	public function validateUser($username, $password)
 +	{
 +		$sqlmap = $this->getConnection();
 +		$param['username'] = $username;
 +		$param['password'] = md5($password);
 +		return $sqlmap->queryForObject('ValidateUser', $param);
 +	}
 +		
 +	/**
 +	 * @param string unique persistent session token
 +	 * @return TimeTrackerUser user details if valid token, null otherwise.
 +	 */
 +	public function validateSignon($token)
 +	{
 +		$sqlmap = $this->getConnection();
 +		$sqlmap->update('UpdateSignon', $token);
 +		return $sqlmap->queryForObject('ValidateAutoSignon', $token);
 +	}
 +	
 +	/**
 +	 * @param TimeTrackerUser user details to generate the token
 +	 * @return string unique persistent login token.
 +	 */
 +	public function createSignonToken($user)
 +	{
 +		$sqlmap = $this->getConnection();
 +		$param['username'] = $user->getName();
 +		$param['token'] = md5(microtime().$param['username']);
 +		$sqlmap->insert('RegisterAutoSignon', $param);
 +		return $param['token'];
 +	}
 +	
 +	/**
 +	 * @param TimeTrackerUser deletes all signon token for given user, null to delete all
 +	 * tokens.
 +	 */
 +	public function clearSignonTokens($user=null)
 +	{
 +		$sqlmap = $this->getConnection();
 +		if($user !== null)
 +			$sqlmap->delete('DeleteAutoSignon', $user->getName());
 +		else
 +			$sqlmap->delete('DeleteAllSignon');
 +	}
 +	
 +	/**
 +	 * @param TimeTrackerUser user details for updating the assigned roles.
 +	 */
 +	public function updateUserRoles($user)
 +	{
 +		$sqlmap = $this->getConnection();
 +		$sqlmap->delete('DeleteUserRoles', $user);
 +		foreach($user->getRoles() as $role)
 +		{
 +			$param['username'] = $user->getName();
 +			$param['role'] = $role;
 +			$sqlmap->update('AddUserRole', $param);
 +		}
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/demos/time-tracker/protected/APP_CODE/UserManager.php b/demos/time-tracker/protected/APP_CODE/UserManager.php new file mode 100644 index 00000000..1327dc3c --- /dev/null +++ b/demos/time-tracker/protected/APP_CODE/UserManager.php @@ -0,0 +1,68 @@ +<?php
 +/**
 + * UserManager class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2006 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + */
 +
 +/**
 + * User manager module class for time tracker application.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + * @since 3.1
 + */
 +class UserManager 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, null if the specified username is not in the user database.
 +	 */
 +	public function getUser($username=null)
 +	{
 +		if($username===null)
 +		{
 +			$user=new TUser($this);
 +			$user->setIsGuest(true);
 +			return $user;
 +		}
 +		else
 +		{
 +			$daos = $this->getApplication()->getModule('daos');
 +			$userDao = $daos->getDao('UserDao');
 +			$user = $userDao->getUserByName($username);
 +			$user->setIsGuest(false);
 +			return $user;
 +		}
 +	}
 +	
 +	/**
 +	 * 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)
 +	{
 +		$daos = $this->getApplication()->getModule('daos');
 +		$userDao = $daos->getDao('UserDao');
 +		return $userDao->validateUser($username, $password);
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/demos/time-tracker/protected/APP_CODE/exceptions.txt b/demos/time-tracker/protected/APP_CODE/exceptions.txt index e948f4d0..6568cc72 100644 --- a/demos/time-tracker/protected/APP_CODE/exceptions.txt +++ b/demos/time-tracker/protected/APP_CODE/exceptions.txt @@ -1,3 +1,7 @@  timetracker_user_readonly_id 	= Time tracker user ID is read-only.
  invalid_creator_and_manager		= Unable to find time tracker usernames '{1}' and '{2}' for project '{0}'.
 -project_exists					= Project '{0}' already exists.
\ No newline at end of file +project_exists					= Project '{0}' already exists.
 +daomanager_connection_required	= An TSqlMapper connection is required by Dao Manager.
 +daomanager_undefined_connection	= Connection '{0}' for Dao Manager is undefined.
 +daomanager_invalid_connection	= Connection '{0}' does not appear to ba a TSqlMapper in Dao Manager.
 +daomanager_undefined_dao		= Dao class '{0}' is not registered.
\ No newline at end of file diff --git a/demos/time-tracker/protected/data/time_tracker.db b/demos/time-tracker/protected/App_Data/time_tracker.db Binary files differindex 03fe9156..03fe9156 100644 --- a/demos/time-tracker/protected/data/time_tracker.db +++ b/demos/time-tracker/protected/App_Data/time_tracker.db diff --git a/demos/time-tracker/protected/pages/Docs/TopicList.tpl b/demos/time-tracker/protected/pages/Docs/TopicList.tpl index 5fa2adb5..53243578 100644 --- a/demos/time-tracker/protected/pages/Docs/TopicList.tpl +++ b/demos/time-tracker/protected/pages/Docs/TopicList.tpl @@ -14,7 +14,7 @@  <div>Testing Business Code</div>
  <ul>
 -	<li><a href="?page=Docs.CreateBusinessCode">Create Business Code</a></li>
 +	<li><a href="?page=Docs.DatabaseDesign">Database Design</a></li>
  	<li><a href="?page=Docs.UsingSQLMap">Using SQLMap Data Mapper</a></li>
  	<li><a href="?page=Docs.UserClassAndExceptions">User Class and Exceptions</a></li>
  	<li><a href="?page=Docs.MoreTests">More Tests</a></li>
 diff --git a/demos/time-tracker/protected/pages/Docs/WritingUnitTest.page b/demos/time-tracker/protected/pages/Docs/WritingUnitTest.page index 32c7bc79..77bdcbe6 100644 --- a/demos/time-tracker/protected/pages/Docs/WritingUnitTest.page +++ b/demos/time-tracker/protected/pages/Docs/WritingUnitTest.page @@ -1,13 +1,19 @@  <com:TContent ID="body">  <h1>Writing a Unit Test</h1> +<p>Before we begin to write our business logic and code, we shall  +proceed with the path of <a href="http://tdd.com">test driven development</a> (TDD), or at least take +some part of that process.</p> +  <p>Unit testing is a useful tool when we want to start to test  	our individual business logic classes.   -	The <tt>tests/unit</tt> directory will be used to hold the unit test cases and <tt>tests/functional</tt> directory -to hold the function test cases. +	The <tt>tests/unit</tt> directory will be used to hold the unit test  +	cases and <tt>tests/functional</tt> directory +	to hold the function test cases.  </p>  <h2>Write a unit test case</h2> -<p>We will start be writing a very simple unit test case.</p> +<p>We will start be writing a very simple unit test case. Notice +that we are writing the test case <b>first</b>.</p>  <com:TTextHighlighter Language="php" CssClass="source">  <?php  class ProjectTestCase extends UnitTestCase @@ -29,14 +35,16 @@ directory.</p>  <img src="<%~ unit_test1.png %>" class="figure"/>  <div class="caption"><b>Figure 1:</b> Unit test runner</div>  </p> -<p>Clicking on the <tt>ProjectTestCase.php</tt> like, you should see  +<p>Clicking on the <tt>ProjectTestCase.php</tt> link, you should see   <img src="<%~ unit_test2.png %>" class="figure"/>  <div class="caption"><b>Figure 2:</b> Unit test failure</div>  </p>  <h2>Smallest step to make the test pass.</h2> -<p>Obviously, we need create the class <tt>Project</tt>, so lets define the class.</p> +<p>Since we only wrote the test case and nothing else we expected +that the test case will fail at some point. Obviously, we need create  +a class <tt>Project</tt>, so lets define the <tt>Project</tt> class.</p>  <com:TTextHighlighter Language="php" CssClass="source">  <?php  class Project @@ -44,15 +52,11 @@ class Project  }  ?>  </com:TTextHighlighter> -<p>Save the above code as <tt>time-tracker/protected/pages/APP_CODE/Project.php</tt>. -	Where the <tt>APP_CODE</tt> directory will contain most of your business logic code for the Time Tracker application.</p> -<p>We also need to add the following line in our test case so as to include the <tt>Project</tt> class file when running the tests.</p> - -<p class="note"> -The statement <tt>Prado::using('Application.APP_CODE.Project')</tt> basically  -loads the <tt>Project.php</tt> class file. It assumes that a class name <tt>Project</tt> has filename <tt>Project.php</tt>. -For futher details regarding <tt>Prado::using</tt> can be found in <a href="http://www.pradosoft.com/demos/quickstart/index.php?page=Fundamentals.Components#704">Prado Namespaces</a> documentation. -</p> +<p>We save the above code as <tt>time-tracker/protected/pages/APP_CODE/Project.php</tt>. +	Where the <tt>APP_CODE</tt> directory will contain most of the business logic code  +	for the Time Tracker application.</p> +<p>Now, we also need to add the following line in our test case so as to  +include the <tt>Project</tt> class file when running the tests.</p>  <com:TTextHighlighter Language="php" CssClass="source">  <?php @@ -63,11 +67,20 @@ class ProjectTestCase extends UnitTestCase  }  ?>  </com:TTextHighlighter> + +<div class="info"><b>Info:</b> +The statement <tt>Prado::using('Application.APP_CODE.Project')</tt> basically  +loads the <tt>Project.php</tt> class file. It assumes that a class name <tt>Project</tt> has filename <tt>Project.php</tt>. +For futher details regarding <tt>Prado::using</tt> can be found in <a href="http://www.pradosoft.com/demos/quickstart/index.php?page=Fundamentals.Components#704">Prado Namespaces</a> documentation. +</div> +  <p>Run the unit test runner again, we see that the test has passed.  	<img src="<%~ unit_test3.png %>" class="figure"/>  	<div class="caption"><b>Figure 3:</b> Unit test success</div>  </p>	  <p> -Later on, we shall write more test cases. See the SimpleTest documentation for detailed tutorial on writing test cases.</p> +Later on, we shall write more test cases. See the  +<a href="http://www.lastcraft.com/simple_test.php">SimpleTest documentation</a>  +for detailed tutorial on writing test cases.</p>  </com:TContent>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/Docs/config.xml b/demos/time-tracker/protected/pages/Docs/config.xml index da4d3bfc..e8fdc3fe 100644 --- a/demos/time-tracker/protected/pages/Docs/config.xml +++ b/demos/time-tracker/protected/pages/Docs/config.xml @@ -1,8 +1,12 @@  <?xml version="1.0" encoding="utf-8"?>
  <configuration>
 -  <paths>
 -    <alias id="Pages" path="." />
 -  </paths>
 -  <pages MasterClass="Application.pages.Docs.Layout" />
 +
 +    <modules>
 +        <module id="theme"
 +                class="System.Web.UI.TThemeManager"
 +                BasePath="Quickstart.themes"
 +                BaseUrl="../quickstart/themes" />
 +    </modules>
 +  <pages MasterClass="Application.pages.Docs.Layout" Theme="PradoSoft"/>
  </configuration>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/Docs/db.png b/demos/time-tracker/protected/pages/Docs/db.png Binary files differindex f2209ef4..efdcc1e5 100644 --- a/demos/time-tracker/protected/pages/Docs/db.png +++ b/demos/time-tracker/protected/pages/Docs/db.png diff --git a/demos/time-tracker/protected/pages/TimeTracker/Login.page b/demos/time-tracker/protected/pages/TimeTracker/Login.page new file mode 100644 index 00000000..dbc16de1 --- /dev/null +++ b/demos/time-tracker/protected/pages/TimeTracker/Login.page @@ -0,0 +1,38 @@ +<%@ Title="My Company - Time Tracker - Site Logon" %>
 +<com:TContent ID="Main">
 +<h2>Time Tracker Website Login</h2>
 +
 +<fieldset class="login"><legend>User Login</legend>
 +  <div class="username">
 +	<com:TLabel ForControl="username" Text="User Name:" />
 +	<span class="required">*</span>
 +	<com:TTextBox ID="username" />
 +	<com:TRequiredFieldValidator
 +		ControlToValidate="username"
 +		ErrorMessage="Please enter your username."
 +		ControlCssClass="required-field" />
 +  </div>
 +  <div class="password">
 +  	<com:TLabel ForControl="password" Text="Password:" />
 +  	<span class="required">*</span>
 +  	<com:TTextBox ID="password" TextMode="Password" />
 +	<com:TRequiredFieldValidator
 +		ControlToValidate="password"
 +		ErrorMessage="Please enter your password."
 +		ControlCssClass="required-field" />
 +  </div>
 +  <div class="remember">
 +  	<com:TCheckBox ID="remember" Text="Remember me next time" />
 +  </div>
 +  <com:TCustomValidator
 +	ControlToValidate="password"
 +	Display="Dynamic"
 +	Text="Your login attempt was not successful. Please try again."
 +	OnServerValidate="validateUser" />
 +  <div class="signin">
 +  	<com:TButton Text="Log In" OnClick="doLogin" />
 +  </div>
 +  <div class="create">
 +  	<a href="?page=TimeTracker.UserCreate">Create New User</a>
 + </fieldset>
 + </com:TContent>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/TimeTracker/Login.php b/demos/time-tracker/protected/pages/TimeTracker/Login.php new file mode 100644 index 00000000..376953a5 --- /dev/null +++ b/demos/time-tracker/protected/pages/TimeTracker/Login.php @@ -0,0 +1,53 @@ +<?php
 +/**
 + * Login Page class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2006 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + */
 +
 +/**
 + * Login page class.
 + * 
 + * Validate the user credentials and redirect to requested page 
 + * if successful.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + * @since 3.1
 + */
 +class Login extends TPage
 +{
 +	/**
 +	 * Validates the username and password.
 +	 * @param TControl custom validator that created the event.
 +	 * @param TServerValidateEventParameter validation parameters. 
 +	 */
 +	public function validateUser($sender, $param)
 +	{
 +		$authManager=$this->Application->getModule('auth');
 +		if(!$authManager->login($this->username->Text,$this->password->Text))
 +			$param->IsValid=false;;
 +	}
 +	
 +	/**
 +	 * Redirect to the requested page if login is successful.
 +	 * @param TControl button control that created the event.
 +	 * @param TEventParameter event parameters.
 +	 */
 +	public function doLogin($sender, $param)
 +	{
 +		if($this->Page->IsValid)
 +		{
 +			$auth = $this->Application->getModule('auth');
 +			$this->Response->redirect($auth->getReturnUrl());
 +		}
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/TimeTracker/Logout.page b/demos/time-tracker/protected/pages/TimeTracker/Logout.page new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/demos/time-tracker/protected/pages/TimeTracker/Logout.page diff --git a/demos/time-tracker/protected/pages/TimeTracker/Logout.php b/demos/time-tracker/protected/pages/TimeTracker/Logout.php new file mode 100644 index 00000000..08fdfaf6 --- /dev/null +++ b/demos/time-tracker/protected/pages/TimeTracker/Logout.php @@ -0,0 +1,34 @@ +<?php
 +/**
 + * Logout class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2006 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + */
 +
 +/**
 + * Logout page class.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + * @since 3.1
 + */
 +class Logout extends TPage
 +{
 +	/**
 +	 * Logs out the current user and redirect to default page.
 +	 */
 +	function onLoad($param)
 +	{
 +		$this->Application->getModule('auth')->logout();
 +		$url = $this->Service->constructUrl($this->Service->DefaultPage);
 +		$this->Response->redirect($url);		
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/TimeTracker/MainLayout.php b/demos/time-tracker/protected/pages/TimeTracker/MainLayout.php new file mode 100644 index 00000000..253d6c03 --- /dev/null +++ b/demos/time-tracker/protected/pages/TimeTracker/MainLayout.php @@ -0,0 +1,7 @@ +<?php
 +
 +class MainLayout extends TTemplateControl
 +{
 +}
 +
 +?>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/TimeTracker/MainLayout.tpl b/demos/time-tracker/protected/pages/TimeTracker/MainLayout.tpl new file mode 100644 index 00000000..2d8bad44 --- /dev/null +++ b/demos/time-tracker/protected/pages/TimeTracker/MainLayout.tpl @@ -0,0 +1,40 @@ +<!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">
 +<com:THead Title="My Company - Time Tracker - Log" />
 +<body>
 +
 +<com:TForm>
 +
 +<h1 class="heading">
 +	<a href="index.php">My Company 
 +		<span class="subheading">Time Tracker</span>
 +	</a>
 +</h1>
 +<div class="minheading">
 +<h2 class="login">
 +	<com:TLabel CssClass="name" Text="Welcome <%= $this->User->Name %>" />
 +	<com:THyperLink 
 +		Text="Login"
 +		NavigateUrl=<%= $this->Service->constructUrl('TimeTracker.Login') %>
 +		Visible=<%= $this->User->getIsGuest() %> />
 +	<com:THyperLink 
 +		Text="Logout"
 +		NavigateUrl=<%= $this->Service->constructUrl('TimeTracker.Logout') %>
 +		Visible=<%= !$this->User->getIsGuest() %> />
 +</h2>
 +<h2 class="help"><a href="?page=Welcome">Help</a></h2>
 +<h2 class="guide"><a href="?page=Docs.Home">Implementation Guide</a></h2>
 +</div>
 +
 +<com:Application.pages.TimeTracker.SiteMap
 +	Visible=<%= !$this->User->getIsGuest() %> />
 +
 +<div class="main">
 +<com:TContentPlaceHolder ID="Main" />
 +</div>
 +
 +</com:TForm>
 +
 +</body>
 +</html>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/TimeTracker/SiteMap.php b/demos/time-tracker/protected/pages/TimeTracker/SiteMap.php new file mode 100644 index 00000000..0b71eb68 --- /dev/null +++ b/demos/time-tracker/protected/pages/TimeTracker/SiteMap.php @@ -0,0 +1,8 @@ +<?php
 +
 +class SiteMap extends TTemplateControl
 +{
 +	
 +}
 +
 +?>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/TimeTracker/SiteMap.tpl b/demos/time-tracker/protected/pages/TimeTracker/SiteMap.tpl new file mode 100644 index 00000000..48187b52 --- /dev/null +++ b/demos/time-tracker/protected/pages/TimeTracker/SiteMap.tpl @@ -0,0 +1,43 @@ +<com:TPanel CssClass="sitemap" Visible="true">
 +<ul class="level1">
 +	<li class="active"><a class="menuitem" href="?page=TimeTracker.TimeEntry">Log</a>
 +	</li>
 +	<li><span class="menuitem">Reports</span>
 +		<ul class="level2">
 +			<li><a href="?page=TimeTracker.ReportProject">Project Reports</a></li>
 +			<li><a href="?page=TimeTracker.ReportResource">Resources Report</a></li>
 +		</ul>
 +	</li>
 +	<li>
 +		<span class="menuitem">Projects</span>
 +		<ul class="level2">
 +			<li><a href="?page=TimeTracker.ProjectDetails">Create New Project</a></li>
 +			<li><a href="?page=TimeTracker.ProjectList">List Projects</a></li>
 +		</ul>
 +	</li>
 +	<li>
 +		<span class="menuitem">Adminstration</span>
 +		<ul class="level2">
 +			<li><a href="?page=TimeTracker.UserCreate">Create New User</a></li>
 +			<li><a href="?page=TimeTracker.UserList">List Users</a></li>
 +		</ul>
 +	</li>
 +</ul>
 +<com:TClientScript PradoScripts="prado">
 +	Event.OnLoad(function()
 +	{
 +		menuitems = $$(".menuitem");
 +		menuitems.each(function(el)
 +		{
 +			Event.observe(el, "mouseover", function(ev)
 +			{	
 +				menuitems.each(function(item)
 +				{
 +					Element.removeClassName(item.parentNode, "active");
 +				});
 +				Element.addClassName(Event.element(ev).parentNode, "active");
 +			});
 +		});
 +	});
 +</com:TClientScript>
 +</com:TPanel>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/TimeTracker/UserCreate.page b/demos/time-tracker/protected/pages/TimeTracker/UserCreate.page new file mode 100644 index 00000000..fda7ba9b --- /dev/null +++ b/demos/time-tracker/protected/pages/TimeTracker/UserCreate.page @@ -0,0 +1,65 @@ +<com:TContent ID="Main">
 +<h2>Create New User</h2>
 +
 +<fieldset class="signup"><legend>User Details</legend>
 +	<h4>Sign Up for Your New Account</h4>
 +	<div class="username">
 +		<com:TLabel ForControl="username" Text="User Name:" />
 +		<span class="required">*</span>
 +		<com:TTextBox ID="username" />
 +	<com:TRequiredFieldValidator
 +		ControlToValidate="username"
 +		Display="Dynamic"
 +		ErrorMessage="Please enter your username."
 +		ControlCssClass="required-field" />
 +  	<com:TCustomValidator
 +		ControlToValidate="username"
 +		Display="Dynamic"
 +		OnServerValidate="checkUsername" />	
 +	</div>
 +	<div class="password">
 +		<com:TLabel ForControl="password" Text="Password:" />
 +		<span class="required">*</span>
 +		<com:TTextBox ID="password" TextMode="Password" />
 +	<com:TRequiredFieldValidator
 +		ControlToValidate="password"
 +		Display="Dynamic"
 +		ErrorMessage="Please enter your password (6 or more characters)."
 +		ControlCssClass="required-field" />	
 +	<com:TRegularExpressionValidator
 +		ControlToValidate="password"
 +		Display="Dynamic"
 +		RegularExpression="\w{6,}"
 +		ErrorMessage="Please enter 6 or more characters."
 +		ControlCssClass="required-field" />			
 +	</div>	
 +	<div class="password">
 +		<com:TLabel ForControl="password2" Text="Confirm Password:" />
 +		<span class="required">*</span>
 +		<com:TTextBox ID="password2" TextMode="Password" />
 +	<com:TCompareValidator
 +		ControlToValidate="password"
 +		ControlToCompare="password2"
 +		ErrorMessage="The Password and Confirmation Password must match."
 +		ControlCssClass="required-field" />		
 +	</div>	
 +	<div class="email">
 +		<com:TLabel ForControl="email" Text="E-Mail Address:" />
 +		<span class="required">*</span>
 +		<com:TTextBox ID="email" Style="width:20em"/>
 +	<com:TRequiredFieldValidator
 +		ControlToValidate="email"
 +		Display="Dynamic"
 +		ErrorMessage="Please enter your E-Mail address."
 +		ControlCssClass="required-field" />			
 +	<com:TEmailAddressValidator
 +		ControlToValidate="email"
 +		Display="Dynamic"
 +		ErrorMessage="E-Mail address does not seem to be valid."
 +		ControlCssClass="required-field" />		</div>		
 +  	<div class="create">
 +  		<com:TButton Text="Create User" OnClick="createNewUser" />
 +  	</div>	
 +</fieldset>
 +
 +</com:TContent>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/TimeTracker/UserCreate.php b/demos/time-tracker/protected/pages/TimeTracker/UserCreate.php new file mode 100644 index 00000000..b337bfca --- /dev/null +++ b/demos/time-tracker/protected/pages/TimeTracker/UserCreate.php @@ -0,0 +1,78 @@ +<?php
 +/**
 + * UserCreate page class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2006 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + */
 +
 +/**
 + * Create new user page class. Validate that the usernames are unique
 + * and set the new user credentials as the current application credentials.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $16/07/2006: $
 + * @package Demos
 + * @since 3.1
 + */
 +class UserCreate extends TPage
 +{
 +	/**
 +	 * Verify that the username is not taken.
 +	 * @param TControl custom validator that created the event.
 +	 * @param TServerValidateEventParameter validation parameters.
 +	 */
 +	public function checkUsername($sender, $param)
 +	{
 +		$userDao = $this->Application->Modules['daos']->getDao('UserDao');
 +		$user = $userDao->getUserByName($this->username->Text);
 +		if(!is_null($user))
 +		{
 +			$param->IsValid = false;
 +			$sender->ErrorMessage = 
 +				"The user name is already taken, try '{$user->Name}01'";
 +		}
 +	}
 +	
 +	/**
 +	 * Create a new user if all data entered are valid.
 +	 * The default user roles are obtained from "config.xml". The new user
 +	 * details is saved to the database and the new credentials are used as the
 +	 * application user. The user is redirected to the requested page.
 +	 * @param TControl button control that created the event.
 +	 * @param TEventParameter event parameters.
 +	 */
 +	public function createNewUser($sender, $param)
 +	{
 +		if($this->IsValid)
 +		{
 +			$newUser = new TimeTrackerUser($this->User->Manager);
 +			$newUser->EmailAddress = $this->email->Text;
 +			$newUser->Name = $this->username->Text;
 +			$newUser->IsGuest = false;
 +			$newUser->Roles = $this->Application->Parameters['NewUserRoles'];
 +	
 +			//save the user
 +			$userDao = $this->Application->Modules['daos']->getDao('UserDao');
 +			$userDao->addNewUser($newUser, $this->password->Text);
 +	
 +			//update the user
 +			$auth = $this->Application->getModule('auth');
 +			$auth->updateSessionUser($newUser);
 +			$this->Application->User = $newUser;
 +			
 +			//return to requested page
 +			$this->Response->redirect($auth->getReturnUrl());
 +			
 +			//goto default page.
 +			//$url = $this->Service->constructUrl($this->Service->DefaultPage);
 +			//$this->Response->redirect($url);		
 +		}
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/TimeTracker/UserList.page b/demos/time-tracker/protected/pages/TimeTracker/UserList.page new file mode 100644 index 00000000..48b2bbc7 --- /dev/null +++ b/demos/time-tracker/protected/pages/TimeTracker/UserList.page @@ -0,0 +1,3 @@ +<com:TContent ID="Main">
 +<h1>List Users</h1>
 +</com:TContent>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/TimeTracker/config.xml b/demos/time-tracker/protected/pages/TimeTracker/config.xml new file mode 100644 index 00000000..dac6465d --- /dev/null +++ b/demos/time-tracker/protected/pages/TimeTracker/config.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?>
 +
 +<configuration>
 +
 +  <modules>
 +    <!-- user manager module -->
 +  	<module id="users" class="Application.App_Code.UserManager" />
 +    <!-- auth manager module -->
 +    <module id="auth" class="System.Security.TAuthManager" 
 +		UserManager="users" LoginPage="TimeTracker.Login" />
 +  </modules>
 +
 +  <authorization>
 +    <allow roles="admin" />
 +	<allow pages="UserCreate,Logout,Login" users="*" />
 +    <deny users="*" />
 +  </authorization>
 +
 +  <pages MasterClass="Application.pages.TimeTracker.MainLayout" Theme="TimeTracker" />
 +
 +  <parameters>
 +  	<parameter id="NewUserRoles" value="admin,manager,consultant" />
 +  </parameters>
 +</configuration>
\ No newline at end of file diff --git a/demos/time-tracker/protected/pages/Welcome.page b/demos/time-tracker/protected/pages/Welcome.page new file mode 100644 index 00000000..65ada02d --- /dev/null +++ b/demos/time-tracker/protected/pages/Welcome.page @@ -0,0 +1,168 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 +<html xmlns="http://www.w3.org/1999/xhtml" >
 +<head>
 +	<title>Welcome</title>
 +	<style type="text/css">
 +		table {
 +			border-collapse:collapse;
 +		}
 +		
 +		td, th {
 +			border:1px solid black;
 +			padding: 10px;
 +		}
 +		
 +		th {
 +			text-align:left;
 +		}		
 +	</style>
 +</head>
 +<body>
 +	<h1>Time Tracker Starter Kit</h1>
 +	<p>
 +		Welcome to your new <strong>Time Tracker</strong> sample application. The key features are:</p>
 +	<ul>
 +		<li><strong>Projects.</strong> Define project information like due dates, hours to complete,
 +			project resources, and more.</li>
 +		<li><strong>Track Time.</strong> Track time spent each day by category and project.</li>
 +		<li><strong>Reports.</strong> Generate progress and team resource reports across multiple projects.</li>
 +	</ul>
 +	<p>
 +		The <a href="index.php">Time Tracker site is ready to run!</a> No changes are needed.</p>
 +		
 +	<hr />
 +		
 +	<h2>Site Members and Roles</h2>
 +	<p>
 +		Your Time Tracker Web site allows visitors to register as members and then log in.
 +		Members have specific privileges defined by roles such as administrator or guest.
 +		Each Time Tracker Web site defines site-specific roles.
 +		The following table describes what features are available to visitors in different roles.</p>
 +	<table>
 +		<tr>
 +			<th>Visitor</th>
 +			<th>Privileges</th>
 +			<th>Default Login</th>
 +		</tr>
 +		<tr>
 +			<td>
 +				Not logged in</td>
 +			<td>
 +				No privileges.</td>
 +			<td></td>
 +		</tr>
 +		<tr>
 +			<td>Logged in</td>
 +			<td>
 +				No privileges. All members must be associated at least with the role <strong>Consultant</strong>.</td>
 +			<td>N/A</td> 
 +		</tr>
 +		<tr>
 +			<td>Logged in as <br />
 +				<strong>Consultant</strong></td>
 +			<td>May log time entries only.</td>
 +			<td>username: <tt>consultant</tt><br />
 +				password: <tt>consultant</tt></td>
 +		</tr>
 +		<tr>
 +			<td>
 +				Logged in as<br />
 +				<strong>Project Manager</strong></td>
 +			<td>
 +				May additionally edit all projects and view reports.</td>
 +			<td>username: <tt>manager</tt><br />
 +				password: <tt>manager</tt></td>
 +		</tr>
 +		<tr>
 +			<td>
 +				Logged in as<br />
 +				<strong>Project Administrator</strong></td>
 +			<td>
 +				May additionally view the list of all users.</td>
 +			<td>username: <tt>admin</tt><br />
 +				password: <tt>admin</tt></td>
 +		</tr>
 +	</table>
 +	<p>
 +		Be sure to create a user name for yourself and assign yourself to a role (such as administrator) that can manage the site.</p>
 +	<p>
 +		Visitors can register by clicking the <strong>Create new </strong>user link on the home page.
 +		New members are activated automatically, and are assigned to a role as specified in the <tt>application.xml</tt> file.
 +		You can manage users (for example, assign them to a role) when login as administrator.
 +		For details, see <a href="#AppendixA">Appendix A</a>.</p>
 +		
 +	<hr />
 +	
 +	<h2>Projects and Time Entries</h2>
 +	<h3>To add a project and categories</h3>
 +	<ol>
 +		<li>Log in to the site as a member in the role <strong>Project Manager</strong> or <strong>Project Administrator</strong>.</li>
 +		<li>Click the <strong>Projects</strong> tab and then click <strong>Create New Project</strong>.</li>
 +		<li>Specify a project name, project manager, estimated complete date, estimated duration, and description.</li>
 +		<li>Under <strong>Specify Project Members</strong>, select a resource. You must select at least one resource. </li>
 +		<li>Click <strong>Save</strong>. A category pane is displayed on the right.</li>
 +		<li>Specify a category name, category abbreviation, and duration.</li>
 +		<li>Click <strong>Add</strong>. The new category is displayed in the categories list. </li>
 +		<li>Repeat steps 6 and 7 to create additional categories.</li>
 +	</ol>
 +	<h3>Log a Time Entry</h3>
 +	<ol>
 +		<li>Log in to the site as a consultant (member in the role <strong>Consultant</strong>).</li>
 +		<li>Click the <strong>Log</strong> tab.</li>
 +		<li>Under <strong>Log your hours</strong>, choose a project and a category and fill in the day, hours, and description.</li>
 +		<li>Make sure the correct consultant is selected in the <strong>Time Sheet For</strong> list. </li>
 +		<li>Click <strong>Add Entry</strong>.</li>
 +	</ol>
 +
 +	<hr />
 +	
 +	<h2>Reports</h2>
 +	<h3>To create a project report</h3>
 +	<ol>
 +		<li>Log in to the site as a member in the role <strong>Project Manager</strong> or <strong>Project Administrator</strong>.</li>
 +		<li>Click the <strong>Reports</strong> tab and then click <strong>Project Reports</strong>. </li>
 +		<li>Under <strong>Select a project</strong>,<strong> </strong>choose one or more projects.</li>
 +		<li>Click <strong>Generate Report</strong>.</li>
 +	</ol>
 +	<h3>To create a resource report</h3>
 +	<ol>
 +		<li>Log in to the site as a member in the role <strong>Project Manager</strong> or <strong>Project Administrator</strong>.</li>
 +		<li>Click the <strong>Reports</strong> tab and then click <strong>Resources Report</strong>. </li>
 +		<li>Select one or more projects, select one or more resources, and then specify a date range. </li>
 +		<li>Click <strong>Generate Report</strong>.</li>
 +	</ol>
 +	
 +	<hr />
 +	
 +	<a name="AppendixA" />
 +	<h2>Appendix A - Manually Managing Members and Roles</h2>
 +	<p>
 +		Your Time Tracker Web site allows visitors to register as members.
 +		Members have specific privileges defined by a role you assign to them.
 +		A special administrative role has rights to perform all functions in the site.</p>
 +	<p>
 +		To create a user (member):</p>
 +	<ol>
 +		<li>Login as administrator, click <strong>Create New User</strong>.
 +		</li>
 +		<li>...</li>
 +	</ol>
 +	<p>
 +		To modify an existing member's role:</p>
 +	<ol>
 +		<li>Login as administrator, click <strong>List Users</strong>.
 +		</li>
 +		<li>...</li>
 +	</ol>
 +
 +	<hr />
 +	
 +	<h2>Appendix B - Publishing Your Site</h2>
 +	<p>
 +		When you are ready to share the Web site with others, you can copy it to your Web server.
 +		You need to know the File Transfer Protocol (FTP) address of your server, and if required, the user name and password assigned to you.</p>
 +	<ol>
 +		<li>...</li>
 +	</ol>
 +</body>
 +</html>
 diff --git a/demos/time-tracker/tests/functional.php b/demos/time-tracker/tests/functional.php index c216ada8..888b29db 100644 --- a/demos/time-tracker/tests/functional.php +++ b/demos/time-tracker/tests/functional.php @@ -1,6 +1,6 @@  <?php
 -include_once '../../prado-trunk\tests\test_tools\functional_tests.php';
 +include_once '../../../tests/test_tools/functional_tests.php';
  $test_cases = dirname(__FILE__)."/functional";
 diff --git a/demos/time-tracker/tests/unit.php b/demos/time-tracker/tests/unit.php index a920b205..20d56432 100644 --- a/demos/time-tracker/tests/unit.php +++ b/demos/time-tracker/tests/unit.php @@ -1,6 +1,6 @@  <?php
 -include_once '../../prado-trunk/tests/test_tools/unit_tests.php';
 +include_once '../../../tests/test_tools/unit_tests.php';
  $app_directory = "../protected";
  $test_cases = dirname(__FILE__)."/unit";
 diff --git a/demos/time-tracker/tests/unit/AddUserToProjectTestCase.php b/demos/time-tracker/tests/unit/AddUserToProjectTestCase.php deleted file mode 100644 index 36defc57..00000000 --- a/demos/time-tracker/tests/unit/AddUserToProjectTestCase.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php
 -
 -require_once(dirname(__FILE__).'/ProjectDaoTestCase.php');
 -
 -class AddUserToProjectTestCase extends ProjectDaoTestCase
 -{		
 -	function testCanAddNewUserToProject()
 -	{
 -		$project = $this->createNewTestProject();
 -		
 -		$user = new TimeTrackerUser();
 -		$user->ID = 3;
 -		$user->Name = "test user 1";
 -		
 -		if(($conn = $this->connection) instanceof MockTSqlMapper)
 -		{
 -			$this->setupMockConnectionFor($project);
 -			$conn->setReturnReference('queryForObject', $user, array('GetUserByName', $user->Name));
 -			$conn->setReturnValue('queryForList', array(), array('GetProjectMembers', $project));
 -			
 -			$param['project'] = $project;
 -			$param['user'] = $user;
 -			
 -			$conn->setReturnValue('insert', true, array('AddNewUserToProject', $param));
 -			
 -			$conn->expectAtLeastOnce('insert');
 -			$conn->expectAtLeastOnce('queryForList'); 
 -		}
 -		
 -		$this->assertTrue($this->dao->createNewProject($project));
 -		$this->assertTrue($this->dao->addUserToProject($project, $user));
 -	}
 -}
 -
 -?>
\ No newline at end of file diff --git a/demos/time-tracker/tests/unit/BaseTestCase.php b/demos/time-tracker/tests/unit/BaseTestCase.php new file mode 100644 index 00000000..8ce3cca8 --- /dev/null +++ b/demos/time-tracker/tests/unit/BaseTestCase.php @@ -0,0 +1,35 @@ +<?php
 +
 +class BaseTestCase extends UnitTestCase
 +{
 +	protected $sqlmap;
 +	
 +	function setup()
 +	{
 +		$app = Prado::getApplication();
 +		$this->sqlmap = $app->getModule('daos')->getConnection();
 +	}
 +	
 +	function flushDatabase()
 +	{
 +		$conn = $this->sqlmap->openConnection();
 +		$file = Prado::getPathOfNamespace('Application.App_Data.mysql-reset','.sql');
 +		if(is_file($file))
 +			$this->runScript($conn, $file);
 +		else
 +			throw new Exception('unable to find script file '.$file);
 +	}
 +	
 +	protected function runScript($connection, $script)
 +	{
 +		$sql = file_get_contents($script);
 +		$lines = explode(';', $sql);
 +		foreach($lines as $line)
 +		{
 +			$line = trim($line);
 +			if(strlen($line) > 0)
 +				$connection->execute($line);
 +		}
 +	}
 +}
 +?>
\ No newline at end of file diff --git a/demos/time-tracker/tests/unit/CreateNewProjectTestCase.php b/demos/time-tracker/tests/unit/CreateNewProjectTestCase.php deleted file mode 100644 index 0aa67405..00000000 --- a/demos/time-tracker/tests/unit/CreateNewProjectTestCase.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php
 -
 -require_once(dirname(__FILE__).'/ProjectDaoTestCase.php');
 -
 -class CreateNewProjectTestCase extends ProjectDaoTestCase
 -{
 -	function testProjectDaoCanCreateNewProject()
 -	{
 -		$project = $this->createNewTestProject();
 -	
 -		if(($conn = $this->connection) instanceof MockTSqlMapper)
 -		{
 -			$this->setupMockConnectionFor($project);
 -			$conn->expectMinimumCallCount('queryForObject', 3);
 -			$conn->expectAtLeastOnce('insert');
 -		}
 -		
 -		$this->assertProjectCreated($project);	
 -	}
 -	
 -	function testProjectExistsException()
 -	{
 -		$project = $this->createNewTestProject();
 -		
 -		if(($conn = $this->connection) instanceof MockTSqlMapper)
 -		{
 -			//make the project exist
 -			$conn->setReturnValue('queryForObject', 
 -					$project, array('GetProjectByName', 'Project 1'));
 -			$this->setupMockConnectionFor($project);
 -		}
 -		
 -		try
 -		{
 -			$this->assertProjectCreated($project);		
 -			$this->fail();
 -		}
 -		catch(TimeTrackerException $e)
 -		{
 -			$this->pass();
 -		}
 -	}
 -	function testProjectCustomerNotExistsException()
 -	{
 -		$project = $this->createNewTestProject();
 -		
 -		if(($conn = $this->connection) instanceof MockTSqlMapper)
 -		{
 -			//customer does not exist
 -			$conn->setReturnValue('queryForObject', 
 -					null, array('GetUserByName', 'Customer A'));
 -			$this->setupMockConnectionFor($project);	
 -		}
 -		
 -		try
 -		{
 -			$this->assertProjectCreated($project);
 -			$this->fail();
 -		}
 -		catch(TimeTrackerException $e)
 -		{
 -			$this->pass();
 -		}
 -	}
 -	
 -	function testProjectManagerNotExistsException()
 -	{
 -		$project = $this->createNewTestProject();
 -		
 -		if(($conn = $this->connection) instanceof MockTSqlMapper)
 -		{
 -			//manager does not exist
 -			$conn->setReturnValue('queryForObject', 
 -					null, array('GetUserByName', 'Manager A'));
 -			$this->setupMockConnectionFor($project);
 -		}
 -		
 -		try
 -		{
 -			$this->assertProjectCreated($project);
 -			$this->fail();
 -		}
 -		catch(TimeTrackerException $e)
 -		{
 -			$this->pass();
 -		}
 -	}
 -}
 -
 -?>
\ No newline at end of file diff --git a/demos/time-tracker/tests/unit/ProjectDaoTestCase.php b/demos/time-tracker/tests/unit/ProjectDaoTestCase.php deleted file mode 100644 index bc576630..00000000 --- a/demos/time-tracker/tests/unit/ProjectDaoTestCase.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php
 -
 -//formerly PradoDaoTestCase.php
 -
 -Prado::using('Application.APP_CODE.*');
 -Prado::using('System.DataAccess.SQLMap.TSqlMapper');
 -
 -Mock::generate('TSqlMapper');
 -
 -class ProjectDaoTestCase extends UnitTestCase
 -{
 -	protected $dao;
 -	protected $connection;
 -	
 -	function setup()
 -	{
 -		$this->dao= new ProjectDao();
 -		$this->connection = new MockTSqlMapper($this);
 -		$this->dao->setConnection($this->connection);
 -	}
 -
 -/*
 -  	//Simple test case, will not detect project existanc
 -  	//This case will clash with the more complete test case below. 
 -	function testProjectDaoCanCreateNewProject()
 -	{
 -		$project = new Project();
 -		$project->Name = "Project 1";
 - 
 -		if(($conn = $this->connection) instanceof MockTSqlMapper)
 -		{
 -			$conn->expectOnce('insert', array('CreateNewProject', $project));
 -			$conn->setReturnValue('insert', true);
 -			
 -			$conn->expectOnce('queryForObject', array('GetProjectByID', 1));
 -			$conn->setReturnReference('queryForObject', $project);
 -		}
 - 
 -		$this->assertTrue($this->dao->createNewProject($project));		
 -		$this->assertEqual($this->dao->getProjectByID(1), $project);
 -	}
 -*/
 -	function setupMockConnectionFor($project)
 -	{
 -		$customer = new TimeTrackerUser();
 -		$customer->ID = 1;
 -		$customer->Name = "Customer A";
 -		
 -		$manager = new TimeTrackerUser();
 -		$manager->ID = 2;
 -		$manager->Name = "Manager A";
 -		
 -		$conn = $this->connection;
 -		
 -		//return the customer and manager
 -		$conn->setReturnValue('queryForObject', 
 -					$customer, array('GetUserByName', 'Customer A'));
 -		$conn->setReturnValue('queryForObject', 
 -					$manager, array('GetUserByName', 'Manager A'));
 -		
 -		//project does not exist
 -		$conn->setReturnValue('queryForObject', 
 -					null, array('GetProjectByName', 'Project 1'));
 -		
 -		$param['project'] = $project;
 -		$param['creator'] = $customer->ID;
 -		$param['manager'] = $manager->ID; 
 -				
 -		$conn->setReturnValue('insert', 
 -					true, array('CreateNewProject', $param));
 -		$conn->setReturnReference('queryForObject', 
 -					$project, array('GetProjectByID', 1));	
 -	}
 -	
 -	function createNewTestProject()
 -	{
 -		$project = new Project();
 -		$project->Name = "Project 1";
 -		$project->CreatorUserName = "Customer A";
 -		$project->ManagerUserName = "Manager A";
 -		
 -		return $project;
 -	}
 -
 -	function assertProjectCreated($project)
 -	{
 -		$this->assertTrue($this->dao->createNewProject($project));		
 -		$this->assertEqual($this->dao->getProjectByID(1), $project);
 -	}
 -	
 -}
 -?>
\ No newline at end of file diff --git a/demos/time-tracker/tests/unit/ProjectTestCase.php b/demos/time-tracker/tests/unit/ProjectTestCase.php index a61c4f77..59f612bd 100644 --- a/demos/time-tracker/tests/unit/ProjectTestCase.php +++ b/demos/time-tracker/tests/unit/ProjectTestCase.php @@ -3,13 +3,17 @@  //import Project class.
  Prado::using('Application.APP_CODE.Project');
 -class ProjectTestCase extends UnitTestCase
 +require_once(dirname(__FILE__).'/BaseTestCase.php');
 +
 +class ProjectTestCase extends BaseTestCase
  {
  	function testProjectClassExists()
  	{
  		$project = new Project();
  		$this->pass();
  	}
 +	
 +	
  }
  ?>
\ No newline at end of file diff --git a/demos/time-tracker/tests/unit/UserDaoTestCase.php b/demos/time-tracker/tests/unit/UserDaoTestCase.php new file mode 100644 index 00000000..d1f3c728 --- /dev/null +++ b/demos/time-tracker/tests/unit/UserDaoTestCase.php @@ -0,0 +1,283 @@ +<?php
 +
 +require_once(dirname(__FILE__).'/BaseTestCase.php');
 +
 +class UserDaoTestCase extends BaseTestCase
 +{
 +	protected $userDao;
 +	
 +	function setup()
 +	{
 +		parent::setup();
 +		$app = Prado::getApplication();
 +		$this->userDao = $app->getModule('daos')->getDao('UserDao');
 +	}
 +	
 +	function assertIsAdmin($user)
 +	{
 +		if(!$user)
 +			return $this->fail();	
 +		$this->assertEqual($user->getName(), 'admin');
 +		$this->assertEqual($user->getEmailAddress(), 'admin@pradosoft.com');
 +	}
 +	
 +	function assertSameUser($user1, $user2)
 +	{
 +		if(is_null($user1) || is_null($user2))
 +			return $this->fail();
 +			
 +		$this->assertEqual($user1->getName(), $user2->getName());
 +		$this->assertEqual($user1->getEmailAddress(), $user2->getEmailAddress());
 +	}
 +	
 +	function assertIsAdminRole($user)
 +	{
 +		if(is_null($user))
 +			return $this->fail();	
 +				
 +		$this->assertTrue($user->isInRole('admin'));
 +	}
 +
 +	function assertIsManagerRole($user)
 +	{
 +		if(is_null($user))
 +			return $this->fail();	
 +				
 +		$this->assertTrue($user->isInRole('manager'));
 +	}
 +
 +	function assertIsConsultantRole($user)
 +	{
 +		if(is_null($user))
 +			return $this->fail();	
 +				
 +		$this->assertTrue($user->isInRole('consultant'));
 +	}
 +
 +	function assertNotConsultantRole($user)
 +	{
 +		if(is_null($user))
 +			return $this->fail();	
 +				
 +		$this->assertFalse($user->isInRole('consultant'));
 +	}
 +	
 +	function testGetUserByName()
 +	{	
 +		$user = $this->userDao->getUserByName('admin');
 +		$this->assertNotNull($user);	
 +		$this->assertIsAdmin($user);
 +	}
 +
 +	function testGetNonExistentUser()
 +	{
 +		$user = $this->userDao->getUserByName('none');
 +		$this->assertNull($user);
 +	}
 +	
 +	function testGetUsers()
 +	{
 +		$users = $this->userDao->getAllUsers();
 +		$this->assertEqual(count($users), 3);
 +	}
 +	
 +	function testUserLogon()
 +	{
 +		$success = $this->userDao->validateUser('admin', 'admin');
 +		$this->assertTrue($success);
 +	}
 +
 +	function testBadLogin()
 +	{
 +		$success = $this->userDao->validateUser('admin', 'hahah');
 +		$this->assertFalse($success);
 +	}
 +	
 +	
 +	function testAddNewUser()
 +	{
 +		$user = new TimeTrackerUser(new UserManager());
 +		$user->Name = "user1";
 +		$user->EmailAddress = 'user1@pradosoft.com';
 +		
 +		$this->userDao->addNewUser($user, 'password');
 +		
 +		$check = $this->userDao->getUserByName($user->Name);
 +		
 +		$this->assertSameUser($check, $user);
 +		$this->flushDatabase();
 +	}
 +	
 +	function testDeleteUserByName()
 +	{
 +		$this->userDao->deleteUserByName('admin');
 +		
 +		$admin = $this->userDao->getUserByName('admin');
 +		$this->assertNull($admin);
 +		
 +		$users = $this->userDao->getAllUsers();
 +		$this->assertEqual(count($users), 2);
 +		
 +		$this->flushDatabase();
 +	}
 +	
 +	function testAutoSignon()
 +	{
 +		$user = new TimeTrackerUser(new UserManager());
 +		$user->Name = "admin";
 +				
 +		$token = $this->userDao->createSignonToken($user);
 +		
 +		$check = $this->userDao->validateSignon($token);
 +		
 +		$this->assertIsAdmin($check);
 +		
 +		$this->flushDatabase(); 
 +	}
 +	
 +
 +	function testBadAutoSignon()
 +	{
 +		$user = new TimeTrackerUser(new UserManager());
 +		$user->Name = "admin";
 +				
 +		$token = $this->userDao->createSignonToken($user);
 +		
 +		$check = $this->userDao->validateSignon('adasd');
 +		$this->assertNull($check);
 +
 +		$this->flushDatabase(); 
 +	}
 +
 +	function testAdminRoles()
 +	{
 +		$user = $this->userDao->getUserByName('admin');
 +		$this->assertIsAdminRole($user);	
 +		$this->assertIsManagerRole($user);
 +		$this->assertIsConsultantRole($user);
 +	}
 +	
 +	function testSetUserRoles()
 +	{
 +		$user = new TimeTrackerUser(new UserManager());
 +		$user->Name = "user1";
 +		$user->EmailAddress = 'user1@pradosoft.com';
 +		$user->Roles = array("manager", "consultant");
 +
 +		$this->userDao->addNewUser($user, 'password');
 +		$check = $this->userDao->getUserByName('user1');
 +		
 +		$this->assertIsManagerRole($check);
 +		$this->assertIsConsultantRole($check);
 +		
 +		$this->flushDatabase();
 +	}
 +	
 +	function testSetUserRoleNoNullUser()
 +	{
 +		$user = new TimeTrackerUser(new UserManager());
 +		$user->Name = "user1";
 +		$user->EmailAddress = 'user1@pradosoft.com';
 +		$user->Roles = array("manager", "consultant");	
 +		
 +		try
 +		{
 +			$this->userDao->updateUserRoles($user);
 +			$this->fail();
 +		}
 +		catch(TDataMapperException $e)
 +		{
 +			$this->pass();
 +		}
 +		
 +		$check = $this->sqlmap->queryForObject('GetUserByName', 'user1');
 +		$this->assertNull($check);
 +	}
 +	
 +	function testUpdateUser()
 +	{
 +		$user = $this->userDao->getUserByName('admin');
 +		$user->EmailAddress = 'something@pradosoft.com';
 +		$user->Roles = array('manager', 'admin');
 +		
 +		$this->userDao->updateUser($user);
 +		
 +		$check = $this->userDao->getUserByName('admin');
 +		$this->assertIsAdminRole($check);
 +		$this->assertIsManagerRole($check);
 +		$this->assertNotConsultantRole($check);
 +		
 +		$this->flushDatabase();
 +	}
 +	
 +	function testUpdateUserPassword()
 +	{
 +		$user = $this->userDao->getUserByName('admin');
 +		$user->EmailAddress = 'something@pradosoft.com';
 +		$user->Roles = array('manager', 'admin');
 +		
 +		$pass = 'newpasword';
 +		
 +		$this->userDao->updateUser($user, $pass);
 +		
 +		$success = $this->userDao->validateUser('admin', $pass);
 +		
 +		$this->assertTrue($success);
 +		
 +		$this->flushDatabase();
 +	}
 +	
 +	function testClearSignonTokens()
 +	{
 +		$user = new TimeTrackerUser(new UserManager());
 +		$user->Name = "admin";
 +				
 +		$token1 = $this->userDao->createSignonToken($user);
 +		sleep(1);
 +		$token2 = $this->userDao->createSignonToken($user);
 +		$this->assertNotEqual($token1, $token2);
 +		
 +		$check1 = $this->userDao->validateSignon($token1);
 +		$check2 = $this->userDao->validateSignon($token2);
 +		
 +		$this->assertIsAdmin($check1);
 +		$this->assertIsAdmin($check2);
 +		
 +		$this->userDao->clearSignonTokens($user);
 +		
 +		$check3 = $this->userDao->validateSignon($token1);
 +		$check4 = $this->userDao->validateSignon($token2);
 +		
 +		$this->assertNull($check3);
 +		$this->assertNull($check4);
 +	}
 +	
 +	function testClearAllSigonTokens()
 +	{
 +		$user1 = new TimeTrackerUser(new UserManager());
 +		$user1->Name = "admin";
 +		
 +		$user2 = new TimeTrackerUser(new UserManager());
 +		$user2->Name = "manager";
 +		
 +		$token1 = $this->userDao->createSignonToken($user1);
 +		$token2 = $this->userDao->createSignonToken($user2);
 +		
 +		$check1 = $this->userDao->validateSignon($token1);
 +		$check2 = $this->userDao->validateSignon($token2);
 +		
 +		$this->assertIsAdmin($check1);
 +		$this->assertNotNull($check2);
 +		$this->assertEqual($check2->Name, $user2->Name);
 +		
 +		$this->userDao->clearSignonTokens();
 +		
 +		$check3 = $this->userDao->validateSignon($token1);
 +		$check4 = $this->userDao->validateSignon($token2);
 +		
 +		$this->assertNull($check3);
 +		$this->assertNull($check4);
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/demos/time-tracker/themes/TimeTracker/background.png b/demos/time-tracker/themes/TimeTracker/background.png Binary files differnew file mode 100644 index 00000000..ad339daf --- /dev/null +++ b/demos/time-tracker/themes/TimeTracker/background.png diff --git a/demos/time-tracker/themes/TimeTracker/site.css b/demos/time-tracker/themes/TimeTracker/site.css new file mode 100644 index 00000000..f426243e --- /dev/null +++ b/demos/time-tracker/themes/TimeTracker/site.css @@ -0,0 +1,217 @@ +html
 +{
 +	background-color: #eef;
 +}
 +body
 +{
 +	background: url(background.png) repeat-x top;
 +	margin: 0;
 +	padding: 2em;
 +	font-family: Tahoma, Arial, Helvetica, sans-serif;
 +}
 +
 +h1, h2, h3, h4
 +{
 +	color: #6495ED;
 +}
 +
 +div.main
 +{
 +
 +	background-color: White;
 +	padding: 30px 30px 200px 30px;
 +	margin-top: 1.8em;
 +	-moz-border-radius: 15px 15px 0 0;
 +}
 +
 +h1.heading, h1 a
 +{
 +	color: white;
 +	text-decoration: none;
 +	margin: -1.2em 0 1em 0;
 +	font-size: 1.25em;
 +}
 +
 +h1.heading, h1 a:hover
 +{
 +	color: white;
 +}
 +
 +h1 .subheading
 +{
 +	display: block;
 +	font-size: 0.96em;
 +	color: #E0FFFF;
 +}
 +
 +.minheading
 +{
 +	text-align: right;
 +	margin-top: -3.5em;
 +}
 +.minheading h2
 +{
 +	font-size: 0.9em;
 +	display: inline;
 +	padding-left: 1em;
 +}
 +
 +.minheading .name
 +{
 +	color: white;
 +	margin-right: 1em;
 +}
 +
 +.minheading a
 +{
 +	color: white;
 +}
 +
 +.minheading a:hover
 +{
 +	color: Yellow;
 +}
 +
 +a
 +{
 +	color: #f61;
 +}
 +
 +a:hover 
 +{
 +	color: red;
 +}
 +
 +/** menu **/
 +
 +.sitemap
 +{
 +	text-align: center;
 +	margin-top: 1.5em;
 +	margin-bottom: -1.5em;
 +}
 +
 +ul.level1
 +{
 +
 +}
 +
 +ul.level1, ul.level2
 +{
 +	margin: 0;
 +	padding: 0;
 +	list-style: none;
 +}
 +
 +ul.level1 li
 +{
 +	display: inline;
 +}
 +ul.level1 li .menuitem
 +{
 +	padding: 0.3em 20px 0.3em 20px;
 +	background-color: #B6CEF7;
 +	cursor: pointer;
 +	background-image: url(tabs.png);
 +	background-repeat: repeat-x;
 +	color: #f71;	
 +	font-weight: bold;
 +	letter-spacing: 2px;
 +}
 +
 +ul.level1 li.active .menuitem
 +{
 +	background-color: White;
 +	background-image: none;
 +}
 +
 +ul.level2
 +{
 +	display: none;
 +}
 +
 +li.active ul.level2
 +{
 +	float: left;
 +	display: block;
 +	width: 95%;
 +	margin: 1em 0 0 0;
 +	padding-bottom: 1em;
 +}
 +
 +li.active ul.level2 li a
 +{
 +	margin-left: 1em;
 +	color: #f61;
 +	text-decoration: none;
 +	border-bottom:1px dashed #f61;
 +}
 +
 +li.active ul.level2 li a:hover
 +{
 +	color: Red;
 +}
 +
 +
 +/** forms **/
 +
 +fieldset.login, fieldset.signup
 +{
 +	margin: 0;
 +	border: 1px solid #6495ED;
 +	padding: 1.5em;
 +}
 +
 +fieldset legend
 +{
 +	font-weight: bold;
 +	color: #4169E1;
 +	padding: 0.5em;
 +}
 +
 +fieldset.login label, fieldset.signup label
 +{
 +	float: left;
 +	color: #708090;
 +	width: 120px;
 +	text-align: right;
 +}
 +
 +fieldset.signup label
 +{
 +	width: 9em;
 +}
 +
 +fieldset span.required
 +{
 +	font-size: 0.85em;
 +	font-weight: bold;
 +	color: Red;
 +}
 +
 +fieldset.login div, fieldset.signup div
 +{
 +	padding: 0.25em;
 +}
 +
 +fieldset.login .remember label
 +{
 +	float:none;
 +	margin-left: 0.4em;
 +}
 +fieldset.login .remember input
 +{
 +	margin-left: 133px;
 +}
 +
 +fieldset.login .signin input
 +{
 +	padding: 0.1em 2em;
 +	margin-left: 133px;
 +}
 +
 +fieldset.signup .create
 +{
 +	margin: 1em;
 +	padding-left: 9em;
 +}
\ No newline at end of file diff --git a/demos/time-tracker/themes/TimeTracker/tabs.png b/demos/time-tracker/themes/TimeTracker/tabs.png Binary files differnew file mode 100644 index 00000000..7f1ca0bb --- /dev/null +++ b/demos/time-tracker/themes/TimeTracker/tabs.png diff --git a/framework/DataAccess/SQLMap/Configuration/TConfigDeserialize.php b/framework/DataAccess/SQLMap/Configuration/TConfigDeserialize.php index ee8f1744..2441dedf 100644 --- a/framework/DataAccess/SQLMap/Configuration/TConfigDeserialize.php +++ b/framework/DataAccess/SQLMap/Configuration/TConfigDeserialize.php @@ -104,6 +104,7 @@ class TConfigDeserialize  	public function resultMap($node, $sqlMap, $file)
  	{
  		$resultMap = new TResultMap;
 +		$resultMap->initialize($sqlMap);
  		$this->loadConfiguration($resultMap, $node, $file);
  		foreach($node->result as $result)
  		{
 diff --git a/framework/DataAccess/SQLMap/Configuration/TDomSqlMapBuilder.php b/framework/DataAccess/SQLMap/Configuration/TDomSqlMapBuilder.php index d3059dd7..ba8323cc 100644 --- a/framework/DataAccess/SQLMap/Configuration/TDomSqlMapBuilder.php +++ b/framework/DataAccess/SQLMap/Configuration/TDomSqlMapBuilder.php @@ -63,6 +63,9 @@ class TDomSqlMapBuilder  		if(isset($document->settings) && isset($document->settings->setting))
  			$this->configureSettings($document->settings);
 +			
 +		if(isset($document->typeHandler))
 +			$this->loadTypeHandler($document, $this->_configFile);			
  		//load database provider
  		if(isset($document->provider) && isset($document->provider->datasource))
 @@ -157,11 +160,19 @@ class TDomSqlMapBuilder  	{
  		//$id = (string)$node['id'];
  		$class = (string)$providerNode['class'];
 -		if(strlen($class) > 0 && class_exists($class,false))
 +		if(strlen($class) > 0)
  		{
 -			$provider = new $class;
 -			$this->_deserialize->loadConfiguration($provider, $node,$file);
 -			$this->_sqlMapper->setDataProvider($provider);
 +			if(class_exists($class,false))
 +			{
 +				$provider = new $class;
 +				$this->_deserialize->loadConfiguration($provider, $node,$file);
 +				$this->_sqlMapper->setDataProvider($provider);
 +			}
 +			else
 +			{
 +				throw new TSqlMapConfigurationException(
 +						'sqlmap_unable_find_provider_class_def', $file, $class);
 +			}
  		}
  		else
  		{
 @@ -170,11 +181,38 @@ class TDomSqlMapBuilder  		}
  		//var_dump($node);
  	}
 -/*
 -	protected function loadTypeHandlers()
 +
 +	protected function loadTypeHandler($nodes, $file)
  	{
 +		foreach($nodes->typeHandler as $node)
 +		{
 +			if(!is_null($node['type']) && !is_null($node['callback']))
 +			{
 +				$type = (string)$node['type'];
 +				$class = (string)$node['callback'];
 +				if(class_exists('Prado', false))
 +				{
 +					$handler = Prado::createComponent($class);
 +				}
 +				else
 +				{
 +					if(class_exists($class,false))
 +						$handler = new $class;
 +					else
 +					throw new TSqlMapConfigurationException(
 +							'sqlmap_type_handler_class_undef', $file, $class);
 +				}
 +				$factory = $this->_sqlMapper->getTypeHandlerFactory();
 +				$factory->register($type, $handler);
 +			}
 +			else
 +			{
 +				throw new TSqlMapConfigurationException(
 +					'sqlmap_type_handler_callback_undef', $file);
 +			}
 +		}
  	}
 -*/
 +
  	protected function loadSqlMappingFiles($sqlmappings)
  	{
  		foreach($sqlmappings->sqlMap as $node)
 diff --git a/framework/DataAccess/SQLMap/Configuration/TParameterMap.php b/framework/DataAccess/SQLMap/Configuration/TParameterMap.php index 8e1c757d..b3c6ed6e 100644 --- a/framework/DataAccess/SQLMap/Configuration/TParameterMap.php +++ b/framework/DataAccess/SQLMap/Configuration/TParameterMap.php @@ -56,7 +56,7 @@ class TParameterMap extends TComponent  		$typeHandler = $mapping->getTypeHandler();
  		try
  		{
 -			$value = TPropertyAccess::get($parameterValue, $mapping->getProperty());		
 +			$value = TPropertyAccess::get($parameterValue, $mapping->getProperty());	
  		}
  		catch (TInvalidPropertyException $e)
  		{
 diff --git a/framework/DataAccess/SQLMap/Configuration/TResultMap.php b/framework/DataAccess/SQLMap/Configuration/TResultMap.php index 0f09a1ba..b8032c81 100644 --- a/framework/DataAccess/SQLMap/Configuration/TResultMap.php +++ b/framework/DataAccess/SQLMap/Configuration/TResultMap.php @@ -8,6 +8,7 @@ class TResultMap extends TComponent  	private $_extendMap='';
  	private $_groupBy='';
  	private $_discriminator=null;
 +	private $_typeHandlerFactory=null;
  	public function __construct()
  	{
 @@ -32,6 +33,11 @@ class TResultMap extends TComponent  	public function getDiscriminator(){ return $this->_discriminator; }
  	public function setDiscriminator($value){ $this->_discriminator = $value; }
 +	public function initialize($sqlMap, $resultMap=null)
 +	{
 +		$this->_typeHandlerFactory = $sqlMap->getTypeHandlerFactory();
 +	}
 +
  	public function addResultProperty(TResultProperty $property)
  	{
  		$this->_columns->add($property->getProperty(), $property);
 @@ -39,7 +45,21 @@ class TResultMap extends TComponent  	public function createInstanceOfResult()
  	{
 -		return TTypeHandlerFactory::createInstanceOf($this->getClass());
 +		$handler = $this->_typeHandlerFactory->getTypeHandler($this->getClass());
 +
 +		try
 +		{
 +			if(!is_null($handler))
 +					return $handler->createNewInstance();		
 +			else
 +				return TTypeHandlerFactory::createInstanceOf($this->getClass());
 +		}
 +		catch (TDataMapperException $e)
 +		{
 +			throw new TSqlMapExecutionException(
 +				'sqlmap_unable_to_create_new_instance', 
 +					$this->getClass(), get_class($handler), $this->getID());
 +		}
  	}
  	public function resolveSubMap($row)
 diff --git a/framework/DataAccess/SQLMap/Configuration/TSqlMapStatement.php b/framework/DataAccess/SQLMap/Configuration/TSqlMapStatement.php index 228b37d6..414ad2f1 100644 --- a/framework/DataAccess/SQLMap/Configuration/TSqlMapStatement.php +++ b/framework/DataAccess/SQLMap/Configuration/TSqlMapStatement.php @@ -79,14 +79,14 @@ class TSqlMapStatement extends TComponent  		return array(); //new TList;
  	}
 -	protected function createInstanceOf($type)
 +	protected function createInstanceOf($type,$row=null)
  	{
  		$handler = $this->_typeHandler->getTypeHandler($type);
  		try
  		{
  			if(!is_null($handler))
 -					return $handler->createNewInstance();		
 +					return $handler->createNewInstance($row);		
  			else
  				return TTypeHandlerFactory::createInstanceOf($type);
  		}
 @@ -99,10 +99,10 @@ class TSqlMapStatement extends TComponent  	}
 -	public function createInstanceOfResultClass()
 +	public function createInstanceOfResultClass($row)
  	{
  		if(strlen($type= $this->getResultClass()) > 0)
 -			return $this->createInstanceOf($type);
 +			return $this->createInstanceOf($type,$row);
  	}
  }
 diff --git a/framework/DataAccess/SQLMap/DataMapper/TPropertyAccess.php b/framework/DataAccess/SQLMap/DataMapper/TPropertyAccess.php index 4bbe2cb5..e4f5c1fa 100644 --- a/framework/DataAccess/SQLMap/DataMapper/TPropertyAccess.php +++ b/framework/DataAccess/SQLMap/DataMapper/TPropertyAccess.php @@ -39,7 +39,7 @@ class TPropertyAccess  	 */
  	public static function get($object,$path)
  	{
 -		if(!is_array($object) || !is_object($object))
 +		if(!is_array($object) && !is_object($object))
  			return $object;
  		$properties = explode('.', $path);
  		foreach($properties as $prop)
 @@ -49,7 +49,7 @@ class TPropertyAccess  				if(isset($object[$prop]))
  					$object = $object[$prop];
  				else
 -					throw new TInvalidPropertyException('sqlmap_invalid_property',$path);
 +					throw new TInvalidPropertyException('sqlmap_invalid_property',$path);					
  			}
  			else if(is_object($object))
  			{
 @@ -69,7 +69,7 @@ class TPropertyAccess  	public static function has($object, $path)
  	{
 -		if(!is_array($object) || !is_object($object))
 +		if(!is_array($object) && !is_object($object))
  			return false;
  		$properties = explode('.', $path);
  		foreach($properties as $prop)
 diff --git a/framework/DataAccess/SQLMap/DataMapper/TTypeHandlerFactory.php b/framework/DataAccess/SQLMap/DataMapper/TTypeHandlerFactory.php index fcadea28..55fb1f20 100644 --- a/framework/DataAccess/SQLMap/DataMapper/TTypeHandlerFactory.php +++ b/framework/DataAccess/SQLMap/DataMapper/TTypeHandlerFactory.php @@ -55,8 +55,10 @@ class TTypeHandlerFactory  				case 'integer': case 'int': return 0;
  				case 'bool': case 'boolean': return false;
  			}
 -				
 -			if(class_exists($type, false)) //NO auto loading
 +			
 +			if(class_exists('Prado', false))
 +				return Prado::createComponent($type);
 +			else if(class_exists($type, false)) //NO auto loading
  				return new $type;
  			else
  				throw new TDataMapperException('sqlmap_unable_to_find_class', $type);
 @@ -125,10 +127,10 @@ interface ITypeHandlerCallback  	 * for this type (e.g. File type), you can simply return the String representation
  	 * as it was passed in.  It is not recommended to return null, unless null was passed
  	 * in.
 -	 * @param string nullValue.
 +	 * @param array result row.
  	 * @return mixed
  	 */
 -	public function createNewInstance();
 +	public function createNewInstance($row=null);
  }
  ?>
\ No newline at end of file diff --git a/framework/DataAccess/SQLMap/DataMapper/messages.txt b/framework/DataAccess/SQLMap/DataMapper/messages.txt index 6bf5f396..16be9c2b 100644 --- a/framework/DataAccess/SQLMap/DataMapper/messages.txt +++ b/framework/DataAccess/SQLMap/DataMapper/messages.txt @@ -17,6 +17,8 @@ map_item_unremovable					= The item cannot be removed from the map.  map_data_not_iterable					= Data must be either an array or an object implementing Traversable interface.
  map_readonly							= {0} is read-only.
 +sqlmap_type_handler_class_undef			= Unable to find type handler class named '{1}' in sqlmap configuration file '{0}'.
 +sqlmap_type_handler_callback_undef		= Attributes 'type' and 'callback' must be defined in typeHandler tag in configuration file '{0}'.
  sqlmap_contains_no_statement			= Unable to find SQLMap statement '{0}'.
  sqlmap_already_contains_statement		= Duplicate SQLMap statement found, '{0}' already exists.
  sqlmap_contains_no_result_map			= Unable to find SQLMap result map '{0}'.
 @@ -27,6 +29,7 @@ sqlmap_connection_already_exists		= SqlMap could not invoke OpenConnection(). A  sqlmap_unable_to_close_null_connection	= SqlMap could not invoke CloseConnection(). No connection was started. Call OpenConnection() first.
  sqlmap_undefined_attribute				= {0} attribute '{1}' is not defined for {2} in file {3}.
  sqlmap_unable_find_provider_class		= Unable to find a database provider in SQLMap configuration file {0}.
 +sqlmap_unable_find_provider_class_def	= Unable to load class database provider '{1}' in SQLMap configuration file {0}.
  sqlmap_unable_to_find_parent_parameter_map	= Unable to find parent parameter map extension '{0}' in file {1}.
  sqlmap_unable_to_find_parent_sql		= Unable to find parent sql statement extension '{0}' in file {1}.
  sqlmap_unable_to_find_result_mapping	= Unable to resolve SQLMap result mapping '{0}' in Result Map '{2}' using configuration file {1}.
 @@ -36,11 +39,11 @@ sqlmap_index_must_be_string_or_int		= Invalid index '{0}', must be an integes or  sqlmap_undefined_input_property			= Undefined array index '{0}' in retrieving property in SQLMap parameter map '{1}'.
  sqlmap_unable_to_find_class				= Unable to find result class '{0}' in TResultMap::createInstanceOfResult().
  sqlmap_can_not_instantiate				= Type handler '{0}' can not create new objects.
 -sqlmap_cannot_execute_query_for_map		= SQLMap statement class {0} can not query for map.
 -sqlmap_cannot_execute_update			= SQLMap statement class {0} can not execute update query.
 -sqlmap_cannot_execute_insert			= SQLMap statement class {0} can not execute insert.
 -sqlmap_cannot_execute_query_for_list	= SQLMap statement class {0} can not query for list.
 -sqlmap_cannot_execute_query_for_object	= SQLMap statement class {0} can not query for object
 +sqlmap_cannot_execute_query_for_map		= SQLMap statement class {0} can not query for map in statement '{1}'.
 +sqlmap_cannot_execute_update			= SQLMap statement class {0} can not execute update query in statement '{1}'.
 +sqlmap_cannot_execute_insert			= SQLMap statement class {0} can not execute insert in statement '{1}'.
 +sqlmap_cannot_execute_query_for_list	= SQLMap statement class {0} can not query for list in statement '{1}'.
 +sqlmap_cannot_execute_query_for_object	= SQLMap statement class {0} can not query for object in statement '{1}'.
  sqlmap_execution_error_no_record		= No record set found in executing statement '{0}': '{1}'.
  sqlmap_unable_to_create_new_instance	= Unable to create a new instance of '{0}' using type hander '{1}' for SQLMap statement with ID '{2}'.
  sqlmap_invalid_property					= Invalid property getter path '{0}'.
 diff --git a/framework/DataAccess/SQLMap/Statements/TInsertMappedStatement.php b/framework/DataAccess/SQLMap/Statements/TInsertMappedStatement.php index 7a444c89..51731a5c 100644 --- a/framework/DataAccess/SQLMap/Statements/TInsertMappedStatement.php +++ b/framework/DataAccess/SQLMap/Statements/TInsertMappedStatement.php @@ -6,26 +6,26 @@ class TInsertMappedStatement extends TMappedStatement  								$keyProperty, $valueProperty=null)
  	{
  		throw new TSqlMapExecutionException(
 -				'sqlmap_cannot_execute_query_for_map', get_class($this));
 +				'sqlmap_cannot_execute_query_for_map', get_class($this), $this->getID());
  	}
  	public function executeUpdate($connection, $parameter)
  	{
  		throw new TSqlMapExecutionException(
 -				'sqlmap_cannot_execute_update', get_class($this));
 +				'sqlmap_cannot_execute_update', get_class($this), $this->getID());
  	}
  	public function executeQueryForList($connection, $parameter, $result,
  										$skip=-1, $max=-1)
  	{
  		throw new TSqlMapExecutionException(
 -				'sqlmap_cannot_execute_query_for_list', get_class($this));
 +				'sqlmap_cannot_execute_query_for_list', get_class($this), $this->getID());
  	}
  	public function executeQueryForObject($connection, $parameter, $result)
  	{
  		throw new TSqlMapExecutionException(
 -				'sqlmap_cannot_execute_query_for_object', get_class($this));
 +				'sqlmap_cannot_execute_query_for_object', get_class($this), $this->getID());
  	}
  }
 diff --git a/framework/DataAccess/SQLMap/Statements/TMappedStatement.php b/framework/DataAccess/SQLMap/Statements/TMappedStatement.php index 483a315a..c621f285 100644 --- a/framework/DataAccess/SQLMap/Statements/TMappedStatement.php +++ b/framework/DataAccess/SQLMap/Statements/TMappedStatement.php @@ -375,18 +375,23 @@ class TMappedStatement extends TComponent implements IMappedStatement  	 * @return object the object.
  	 * @see executeQueryForObject()
  	 */
 -	public function runQueryForObject($connection, $sql, $result)
 +	public function runQueryForObject($connection, $sql, &$result)
  	{
  		$recordSet = $this->executeSQLQuery($connection, $sql);
 -		$object = $this->applyResultMap($recordSet->fetchRow(), $result);
 -		//get group by result
 +		$object = null;
 +		
 +		while($row = $recordSet->fetchRow())
 +			$object = $this->applyResultMap($row, $result);	
 +
  		foreach($this->getGroupbyResults() as $group)
  			$object = $group->updateProperties();
 +
  		$this->clearGroupByResults();
  		$this->executePostSelect($connection);
  		$this->onExecuteQuery($sql);
 +		
  		return $object;
  	}
 @@ -403,7 +408,7 @@ class TMappedStatement extends TComponent implements IMappedStatement  		$sql = $this->_command->create($connection, $this->_statement, $parameter);
 -		$this->executeSQLQuery($connection, $sql);
 +		$result = $this->executeSQLQuery($connection, $sql);
  		if(is_null($generatedKey))
  			$generatedKey = $this->getPostGeneratedSelectKey($connection, $parameter);
 @@ -525,7 +530,7 @@ class TMappedStatement extends TComponent implements IMappedStatement  	 * @param object the result object, will create if necessary.
  	 * @return object the result filled with data, null if not filled.
  	 */
 -	protected function applyResultMap($row, $resultObject=null)
 +	protected function applyResultMap($row, &$resultObject=null)
  	{
  		if($row === false) return null;
 @@ -550,7 +555,7 @@ class TMappedStatement extends TComponent implements IMappedStatement  	protected function fillResultClass($resultClass, $row, $resultObject)
  	{
  		if(is_null($resultObject))
 -			$resultObject = $this->_statement->createInstanceOfResultClass();
 +			$resultObject = $this->_statement->createInstanceOfResultClass($row);
  		if($resultObject instanceOf ArrayAccess)
  			return $this->fillResultArrayList($row, $resultObject);
 @@ -608,14 +613,13 @@ class TMappedStatement extends TComponent implements IMappedStatement  	 * @param object result object to fill, will create new instances if required.
  	 * @return object result object filled with data.
  	 */
 -	protected function fillResultMap($resultMapName, $row, $resultObject)
 +	protected function fillResultMap($resultMapName, $row, &$resultObject)
  	{
  		$resultMap = $this->_sqlMap->getResultMap($resultMapName);
  		$resultMap = $resultMap->resolveSubMap($row);
  		if(is_null($resultObject))
  			$resultObject = $resultMap->createInstanceOfResult();
 -
  		if(is_object($resultObject))
  		{
  			if(strlen($resultMap->getGroupBy()) > 0)
 @@ -641,21 +645,41 @@ class TMappedStatement extends TComponent implements IMappedStatement  	 * @see getGroupByResults()
  	 * @see runQueryForList()
  	 */
 -	protected function addResultMapGroupBy($resultMap, $row, $resultObject)
 +	protected function addResultMapGroupBy($resultMap, $row, &$resultObject)
  	{
  		$group = $this->getResultMapGroupKey($resultMap, $row, $resultObject);
 +		
  		foreach($resultMap->getColumns() as $property)
  		{
 -			$this->setObjectProperty($resultMap, $property, $row, $resultObject);
 +			$scalar = $this->setObjectProperty($resultMap, $property, $row, $resultObject);
  			if(strlen($property->getResultMapping()) > 0)
  			{
  				$key = $property->getProperty();
 -				$value = TPropertyAccess::get($resultObject, $key);
 -				$this->_groupBy[$group]->addValue($key, $value);
 +				$value = $this->extractGroupByValue($property, $resultObject);
 +				if(!empty($value))
 +					$this->_groupBy[$group]->addValue($key, $value);
  			}
  		}
 +		
  		return null;
  	}
 +	
 +	/**
 +	 * Extract value from the object for later adding to a GroupBy collection.
 +	 * @param TResultProperty result property
 +	 * @param mixed result object
 +	 * @return mixed collection element
 +	 */
 +	protected function extractGroupByValue($property, $resultObject)
 +	{
 +		$key = $property->getProperty();	
 +		$value = TPropertyAccess::get($resultObject, $key);
 +		$type = strtolower($property->getType());
 +		if(($type == 'array' || $type == 'map') && is_array($value) && count($value) == 1)
 +			return $value[0];
 +		else
 +			return $value;
 +	}
  	/**
  	 * Gets the result 'group by' groupping key for each row.
 @@ -747,7 +771,7 @@ class TMappedStatement extends TComponent implements IMappedStatement  	 * @param array a result set row retrieved from the database
  	 * @param object the result object
  	 */
 -	protected function setObjectProperty($resultMap, $property, $row, $resultObject)
 +	protected function setObjectProperty($resultMap, $property, $row, &$resultObject)
  	{
  		$select = $property->getSelect();
  		$key = $property->getProperty();
 @@ -756,8 +780,12 @@ class TMappedStatement extends TComponent implements IMappedStatement  		if(strlen($select) == 0 && is_null($nested))
  		{
  			$value = $property->getDatabaseValue($row);
 -			TPropertyAccess::set($resultObject, $key, $value);
 +			
  			$this->_IsRowDataFound = $this->_IsRowDataFound || ($value != null);
 +			if(is_array($resultObject) || is_object($resultObject))
 +				TPropertyAccess::set($resultObject, $key, $value);
 +			else
 +				$resultObject = $value;
  		}
  		else if(!is_null($nested))
  		{
 @@ -844,12 +872,12 @@ class TMappedStatement extends TComponent implements IMappedStatement  	 * @param object the result object
  	 * @return boolean true if the data was found, false otherwise.
  	 */
 -	protected function fillPropertyWithResultMap($resultMap, $row, $resultObject)
 +	protected function fillPropertyWithResultMap($resultMap, $row, &$resultObject)
  	{
  		$dataFound = false;
  		foreach($resultMap->getColumns() as $property)
  		{
 -			$this->_IsRowDataFound = false;
 +			$this->_IsRowDataFound = false;		
  			$this->setObjectProperty($resultMap, $property, $row, $resultObject);
  			$dataFound = $dataFound || $this->_IsRowDataFound;
  		}
 diff --git a/framework/DataAccess/SQLMap/Statements/TSelectMappedStatement.php b/framework/DataAccess/SQLMap/Statements/TSelectMappedStatement.php index 1171e28f..b6f179c0 100644 --- a/framework/DataAccess/SQLMap/Statements/TSelectMappedStatement.php +++ b/framework/DataAccess/SQLMap/Statements/TSelectMappedStatement.php @@ -5,13 +5,13 @@ class TSelectMappedStatement extends TMappedStatement  	public function executeInsert($connection, $parameter)
  	{
  		throw new TSqlMapExecutionException(
 -				'sqlmap_cannot_execute_insert', get_class($this));
 +				'sqlmap_cannot_execute_insert', get_class($this), $this->getID());
  	}
  	public function executeUpdate($connection, $parameter)
  	{
  		throw new TSqlMapExecutionException(
 -				'sqlmap_cannot_execute_update', get_class($this));
 +				'sqlmap_cannot_execute_update', get_class($this), $this->getID());
  	}
  }
 diff --git a/framework/DataAccess/SQLMap/Statements/TUpdateMappedStatement.php b/framework/DataAccess/SQLMap/Statements/TUpdateMappedStatement.php index cf16ee52..353f4b26 100644 --- a/framework/DataAccess/SQLMap/Statements/TUpdateMappedStatement.php +++ b/framework/DataAccess/SQLMap/Statements/TUpdateMappedStatement.php @@ -5,27 +5,27 @@ class TUpdateMappedStatement extends TMappedStatement  	public function executeInsert($connection, $parameter)
  	{
  		throw new TSqlMapExecutionException(
 -				'sqlmap_cannot_execute_insert', get_class($this));
 +				'sqlmap_cannot_execute_insert', get_class($this), $this->getID());
  	}
  	public function executeQueryForMap($connection, $parameter, $keyProperty, 
  											$valueProperty=null)
  	{
  		throw new TSqlMapExecutionException(
 -				'sqlmap_cannot_execute_query_for_map', get_class($this));
 +				'sqlmap_cannot_execute_query_for_map', get_class($this), $this->getID());
  	}
  	public function executeQueryForList($connection, $parameter, $result,
  										$skip=-1, $max=-1)
  	{
  		throw new TSqlMapExecutionException(
 -				'sqlmap_cannot_execute_query_for_list', get_class($this));
 +				'sqlmap_cannot_execute_query_for_list', get_class($this), $this->getID());
  	}
  	public function executeQueryForObject($connection, $parameter, $result)
  	{
  		throw new TSqlMapExecutionException(
 -				'sqlmap_cannot_execute_query_for_object', get_class($this));
 +				'sqlmap_cannot_execute_query_for_object', get_class($this), $this->getID());
  	}
  }
 diff --git a/tests/unit/SQLMap/BaseTest.php b/tests/unit/SQLMap/BaseTest.php index ebff9c6d..0f3ce1e2 100644 --- a/tests/unit/SQLMap/BaseTest.php +++ b/tests/unit/SQLMap/BaseTest.php @@ -175,7 +175,7 @@ class HundredsBool implements ITypeHandlerCallback  			return 200;
  	}
 -	public function createNewInstance()
 +	public function createNewInstance($data=null)
  	{
  		throw new TDataMapperException('can not create');
  	}
 @@ -203,7 +203,7 @@ class OuiNonBool implements ITypeHandlerCallback  			return self::NO;
  	}
 -	public function createNewInstance()
 +	public function createNewInstance($data=null)
  	{
  		throw new TDataMapperException('can not create');
  	}
 @@ -225,7 +225,7 @@ class TDateTimeHandler implements ITypeHandlerCallback  			return $parameter;
  	}
 -	public function createNewInstance()
 +	public function createNewInstance($data=null)
  	{
  		return new TDateTime;
  	}
 diff --git a/tests/unit/SQLMap/InheritanceTest.php b/tests/unit/SQLMap/InheritanceTest.php index 24e9f987..9ace1c29 100644 --- a/tests/unit/SQLMap/InheritanceTest.php +++ b/tests/unit/SQLMap/InheritanceTest.php @@ -138,7 +138,7 @@ class CustomInheritance implements ITypeHandlerCallback  		throw new TDataMapperException('not implemented');
  	}
 -	public function createNewInstance()
 +	public function createNewInstance($data=null)
  	{
  		throw new TDataMapperException('can not create');
  	}
 diff --git a/tests/unit/SQLMap/sqlite/tests.db b/tests/unit/SQLMap/sqlite/tests.db Binary files differindex fa66b2cc..380ef8fa 100644 --- a/tests/unit/SQLMap/sqlite/tests.db +++ b/tests/unit/SQLMap/sqlite/tests.db  | 
