summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes3
-rw-r--r--.gitignore1
-rw-r--r--build.xml41
-rw-r--r--buildscripts/jsbuilder/build.php121
-rw-r--r--buildscripts/jsbuilder/jsmin.php931
-rw-r--r--buildscripts/phing/tasks/PradoPackageTask.php3
-rw-r--r--framework/3rdParty/geshi/geshi/prado.php2
-rw-r--r--framework/Data/ActiveRecord/TActiveRecord.php83
-rw-r--r--framework/Data/ActiveRecord/TActiveRecordCriteria.php22
-rw-r--r--framework/Data/ActiveRecord/TActiveRecordGateway.php149
-rw-r--r--framework/Data/ActiveRecord/TActiveRecordManager.php66
-rw-r--r--framework/Data/Common/Mssql/TMssqlMetaData.php24
-rw-r--r--framework/Data/Common/Mssql/TMssqlTableColumn.php9
-rw-r--r--framework/Data/Common/Mssql/TMssqlTableInfo.php4
-rw-r--r--framework/Data/Common/Mysql/TMysqlMetaData.php2
-rw-r--r--framework/Data/Common/Pgsql/TPgsqlMetaData.php2
-rw-r--r--framework/Data/Common/Sqlite/TSqliteMetaData.php2
-rw-r--r--framework/Data/Common/Sqlite/TSqliteTableColumn.php3
-rw-r--r--framework/Data/Common/TDbMetaData.php2
-rw-r--r--framework/Data/Common/TDbTableColumn.php2
-rw-r--r--framework/Data/DataGateway/TDataGatewayCommand.php213
-rw-r--r--framework/Data/DataGateway/TSqlCriteria.php4
-rw-r--r--framework/Data/DataGateway/TTableGateway.php146
-rw-r--r--framework/Exceptions/messages.txt3
-rw-r--r--tests/simple_unit/ActiveRecord/RecordEventTestCase.php16
-rw-r--r--tests/simple_unit/SqlMap/ActiveRecordSqlMapTest.php4
-rw-r--r--tests/simple_unit/TableGateway/BaseGatewayTest.php2
-rw-r--r--tests/simple_unit/TableGateway/TableInfoGatewayTest.php17
28 files changed, 570 insertions, 1307 deletions
diff --git a/.gitattributes b/.gitattributes
index 289f27a2..c12fa6b2 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -356,8 +356,6 @@ buildscripts/index/api_index.php -text
buildscripts/index/build.php -text
buildscripts/index/quickstart_index.php -text
buildscripts/index/search.php -text
-buildscripts/jsbuilder/build.php -text
-buildscripts/jsbuilder/jsmin.php -text
buildscripts/phing/CREDITS -text
buildscripts/phing/LICENSE -text
buildscripts/phing/README -text
@@ -2792,6 +2790,7 @@ tests/simple_unit/TableGateway/CountTest.php -text
tests/simple_unit/TableGateway/DeleteByPkTest.php -text
tests/simple_unit/TableGateway/MagicCallTest.php -text
tests/simple_unit/TableGateway/TableGatewayPgsqlTest.php -text
+tests/simple_unit/TableGateway/TableInfoGatewayTest.php -text
tests/simple_unit/TableGateway/TestFindByPk.php -text
tests/simple_unit/application.xml -text
tests/simple_unit/unit.php -text
diff --git a/.gitignore b/.gitignore
index 354a0eba..498499ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,5 @@
/.project
/assets
-buildscripts/jsbuilder/JSDoc
demos/quickstart/assets/274d44dc
demos/quickstart/assets/56624407
demos/quickstart/assets/587c9c16
diff --git a/build.xml b/build.xml
index 8b6db816..6f2a8635 100644
--- a/build.xml
+++ b/build.xml
@@ -9,10 +9,11 @@
<project name="prado" basedir="." default="help">
<taskdef name="prado-version-check" classname="PradoVersionTask" classpath="buildscripts/phing/tasks"/>
<taskdef name="prado-doc" classname="PradoDocTask" classpath="buildscripts/phing/tasks"/>
- <taskdef name="prado-pear" classname="PradoPearTask" classpath="buildscripts/phing/tasks"/>
+<!-- <taskdef name="prado-pear" classname="PradoPearTask" classpath="buildscripts/phing/tasks"/>-->
<taskdef name="prado-quickstart-index" classname="QuickstartIndexTask" classpath="buildscripts/phing/tasks"/>
<taskdef name="prado-api-index" classname="ManualIndexTask" classpath="buildscripts/phing/tasks"/>
- <taskdef name="prado-test" classname="PradoTestTask" classpath="buildscripts/phing/tasks"/>
+<!-- <taskdef name="prado-test" classname="PradoTestTask" classpath="buildscripts/phing/tasks"/>-->
+ <taskdef name="compact-package" classname="PradoPackageTask" classpath="buildscripts/phing/tasks"/>
<!-- generates ${prado.version} and ${prado.revision} -->
<prado-version-check />
@@ -36,7 +37,7 @@
<property name="build.test.dir" value="${build.base.dir}/test-reports"/>
<property name="build.coverage.dir" value="${build.base.dir}/code-coverage"/>
<property name="build.snapshot.dir" value="${build.base.dir}/snapshot"/>
- <property name="build.compact.dir" value="${build.base.dir}/compact/${pkgname}" />
+ <property name="build.compact.dir" value="${build.base.dir}/${pkgname}/compact" />
<!--
All Source Files in framework
@@ -134,7 +135,6 @@
For all PRADO developers:
- test : run unit tests (results are under /build/test-reports);
- - js : generate Javascript distribution files;
For PRADO release manager:
- dist : create release files;
@@ -152,8 +152,8 @@
<target name="compact-collections" description="Collections">
<mkdir dir="${build.compact.dir}" />
<compact-package output="${build.compact.dir}/collections.php" strip="${compact-strip-comments}">
- <filelist dir="framework" files="PradoBase.php,TComponent.php,Exceptions/TException.php" />
- <filelist dir="framework/Collections" files="TList.php,TMap.php,TAttributeCollection.php" />
+ <filelist dir="framework" files="PradoBase.php,TComponent.php,Exceptions/TException.php,interfaces.php" />
+ <filelist dir="framework/Collections" files="TList.php,TMap.php,TAttributeCollection.php,TPagedList.php,TPagedDataSource.php" />
</compact-package>
<delete file="${build.compact.dir}/messages.txt" />
<copy file="framework/Exceptions/messages.txt" tofile="${build.compact.dir}/messages.txt" />
@@ -220,9 +220,25 @@
destfile="${build.compact.dir}/messages.txt" />
</target>
+ <target name="compact-sqlmap" description="Package Active Record" depends="compact-db-all">
+ <compact-package output="${build.compact.dir}/sqlmap.php" strip="${compact-strip-comments}">
+ <filelist dir="framework/Data/SqlMap" files="TSqlMapManager.php,TSqlMapGateway.php" />
+ <filelist dir="framework/Data/SqlMap/DataMapper"
+ files="TSqlMapException.php,TSqlMapTypeHandlerRegistry.php,TSqlMapCache.php,TPropertyAccess.php,TLazyLoadList.php,TSqlMapPagedList.php"/>
+ <filelist dir="framework/Data/SqlMap/Configuration"
+ files="TSqlMapStatement.php,TDiscriminator.php,TInlineParameterMapParser.php,TParameterMap.php,TParameterProperty.php,TResultMap.php,TResultProperty.php,TSimpleDynamicParser.php,TSqlMapCacheModel.php,TSqlMapXmlConfiguration.php" />
+ <filelist dir="framework/Data/SqlMap/Statements"
+ files="IMappedStatement.php,TMappedStatement.php,TCachingStatement.php,TUpdateMappedStatement.php,TDeleteMappedStatement.php,TInsertMappedStatement.php,TPreparedCommand.php,TPreparedStatement.php,TPreparedStatementFactory.php,TSelectMappedStatement.php,TSimpleDynamicSql.php,TStaticSql.php"/>
+ </compact-package>
+ <append file="framework/Data/SqlMap/DataMapper/messages.txt"
+ destfile="${build.compact.dir}/messages.txt" />
+ </target>
+
+ <target name="compact-all" description="All packages" depends="compact-active-record,compact-sqlmap" />
+
<!-- end compact packaging -->
- <target name="build" depends="js" description="Building standard PRADO package v${prado.version}.${prado.revision}">
+ <target name="build" description="Building standard PRADO package v${prado.version}.${prado.revision}">
<echo>Building pradolite.php...</echo>
<delete file="framework/pradolite.php"/>
<exec command="${php} build.php" dir="buildscripts/phpbuilder" passthru="true"/>
@@ -234,7 +250,7 @@
<fileset refid="framework"/>
<fileset refid="misc"/>
<fileset refid="test-tools" />
- </copy>
+ </copy>
<copy file="buildscripts/classtree/DWExtensionReadme.txt" tofile="${build.src.dir}/editors/Dreamweaver/readme.txt" />
<copy file="framework/pradolite.php" tofile="${build.src.dir}/framework/pradolite.php" />
@@ -290,7 +306,7 @@
<echo>Generating CHM Content (Quickstart + ClassDocs)</echo>
<exec command="${php} build.php" dir="buildscripts/chmbuilder" passthru="true"/>
- <!-- done on project website
+ <!-- done on project website
<echo>Generating CHM Content (WIKI)</echo>
<exec command="${php} build.php" dir="buildscripts/wikibuilder" passthru="true"/>
-->
@@ -366,11 +382,6 @@ the PRADO distribution:
</echo>
</target>
- <target name="js" description="Compiling Javascript distribution files">
- <delete file="framework/Web/Javascripts/js/*.js" />
- <exec command="${php} build.php" dir="buildscripts/jsbuilder" passthru="true"/>
- </target>
-
<target name="test" description="Running unit tests">
<delete dir="${build.test.dir}"/>
<mkdir dir="${build.test.dir}"/>
@@ -425,7 +436,7 @@ the PRADO distribution:
<mkdir dir="${reports.dir}"/>
<delete dir="${reports.unit.dir}"/>
<delete dir="${reports.codecoverage.dir}"/>
-
+
<if>
<equals arg1="${codecoverage}" arg2="true"/>
<then>
diff --git a/buildscripts/jsbuilder/build.php b/buildscripts/jsbuilder/build.php
deleted file mode 100644
index ead55ae2..00000000
--- a/buildscripts/jsbuilder/build.php
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/php
-<?php
-/**
- * Javascript build file.
- *
- * This script compresses a list of javascript source files
- * and merges them into a few for redistribution.
- *
- * By default, all libraries will be built.
- * You may, however, specify one or several to be built (to save time during development).
- * To do so, pass the library names (without .js) as command line arguments.
- * For example: php build.php base dom
- *
- * @author Xiang Wei Zhuo <weizhuo@gmail.com>, Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package Tools
- */
-
-/**
- * The root directory for storing all source js files
- */
-define('SOURCE_DIR',realpath(dirname(__FILE__).'/../../framework/Web/Javascripts/source'));
-/**
- * The directory for storing compressed js files
- */
-define('TARGET_DIR',realpath(dirname(__FILE__).'/../../framework/Web/Javascripts/js'));
-
-define('JSMIN_AS_LIB',true);
-
-include(dirname(__FILE__).'/jsmin.php');
-
-if(SOURCE_DIR===false || TARGET_DIR===false)
- die('Unable to determine the build path.');
-if(!is_writable(TARGET_DIR))
- die('Unable to create files under '.TARGET_DIR.'.');
-
-/**
- * list of js library files to be compressed and built
- */
-$libraries = array(
- 'prado.js' => array(
- 'prototype/prototype.js',
- 'scriptaculous/builder.js',
- 'prado/prado.js',
- 'prado/scriptaculous-adapter.js',
- 'prado/controls/controls.js',
- 'prado/ratings/ratings.js',
- ),
-
- 'effects.js' => array(
- 'scriptaculous/effects.js'
- ),
-
- 'logger.js' => array(
- 'prado/logger/logger.js',
- ),
-
- 'validator.js' => array(
- 'prado/validator/validation3.js'
- ),
-
- 'datepicker.js' => array(
- 'prado/datepicker/datepicker.js'
- ),
-
- 'colorpicker.js' => array(
- 'prado/colorpicker/colorpicker.js'
- ),
-
- 'ajax.js' => array(
- 'scriptaculous/controls.js',
- 'prado/activecontrols/json.js',
- 'prado/activecontrols/ajax3.js',
- 'prado/activecontrols/activecontrols3.js',
- 'prado/activecontrols/inlineeditor.js',
- 'prado/activeratings/ratings.js'
- )
-);
-
-/**
- * Collect specific libraries to be built from command line
- */
-$requestedLibs=array();
-for($i=1;$i<$argc;++$i)
- $requestedLibs[]=$argv[$i].'.js';
-
-$builds = 0;
-/**
- * loop through all target files and build them one by one
- */
-foreach($libraries as $jsFile => $sourceFiles)
-{
- if(!empty($requestedLibs) && !in_array($jsFile,$requestedLibs))
- continue;
- //$libFile=TARGET_DIR.'/'.$jsFile;
- echo "\nBuilding $jsFile...\n";
- $contents='';
- foreach($sourceFiles as $sourceJsFile)
- {
- $sourceFile=SOURCE_DIR.'/'.$sourceJsFile;
- if(!is_file($sourceFile))
- echo "Source file not found: $sourceFile\n";
-
- echo "...adding $sourceJsFile\n";
- $contents.=file_get_contents($sourceFile)."\n\n";
- }
- $debugFile=TARGET_DIR.'/debug/'.$jsFile;
- $compressFile=TARGET_DIR.'/compressed/'.$jsFile;
- file_put_contents($debugFile,$contents);
- $jsMin = new JSMin($debugFile, $compressFile);
- $jsMin -> minify();
- unset($jsMin);
- //@unlink($tempFile);
- echo "Saving file {$jsFile}\n";
- $builds++;
-}
-
-?> \ No newline at end of file
diff --git a/buildscripts/jsbuilder/jsmin.php b/buildscripts/jsbuilder/jsmin.php
deleted file mode 100644
index bc63dd4e..00000000
--- a/buildscripts/jsbuilder/jsmin.php
+++ /dev/null
@@ -1,931 +0,0 @@
-<?php
-/**
-* JSMin_lib.php (for PHP 4, 5)
-*
-* PHP adaptation of JSMin, published by Douglas Crockford as jsmin.c, also based
-* on its Java translation by John Reilly.
-*
-* Permission is hereby granted to use the PHP version under the same conditions
-* as jsmin.c, which has the following notice :
-*
-* ----------------------------------------------------------------------------
-*
-* Copyright (c) 2002 Douglas Crockford (www.crockford.com)
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy of
-* this software and associated documentation files (the "Software"), to deal in
-* the Software without restriction, including without limitation the rights to
-* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-* of the Software, and to permit persons to whom the Software is furnished to do
-* so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in all
-* copies or substantial portions of the Software.
-*
-* The Software shall be used for Good, not Evil.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*
-* ----------------------------------------------------------------------------
-*
-* @copyright No new copyright ; please keep above and following information.
-* @author David Holmes <dholmes@cfdsoftware.net> of CFD Labs, France
-* @author Gaetano Giunta
-* @version $Id: $
-*
-* Please note, this is a brutal and simple conversion : it could undoubtedly be
-* improved, as a PHP implementation, by applying more PHP-specific programming
-* features.
-*
-* Exceptions and all PHP 5 - only features ahve been removed for compat with PHP 4
-*
-* Note : whereas jsmin.c works specifically with the standard input and output
-* streams, this implementation only falls back on them if file pathnames are
-* not provided to the JSMin() constructor.
-*
-* Examples comparing with the application compiled from jsmin.c :
-*
-* jsmin < orig.js > mini.js JSMin.php orig.js mini.js
-* JSMin.php orig.js > mini.js
-* JSMin.php - mini.js < orig.js
-* jsmin < orig.js JSMin.php orig.js
-* JSMin.php orig.js -
-* jsmin > mini.js JSMin.php - mini.js
-* JSMin.php > mini.js
-* jsmin comm1 comm2 < a.js > b.js JSMin.php a.js b.js comm1 comm2
-* JSMin.php a.js b.js -c comm1 comm2
-* JSMin.php a.js --comm comm1 comm2 > b.js
-* JSMin.php -c comm1 comm2 < a.js > b.js
-* (etc...)
-*
-* See JSMin.php -h (or --help) for command-line documentation.
-*
-* NEW AND IMPROVED in version 0.2:
-* to take advantage of this file in your own code, you can do the following:
-*
-* define('JSMIN_AS_LIB', true); // prevents auto-run on include
-* include('jsmin.php');
-* // the JSMin class now works on php strings, too
-* $jsMin = new JSMin(file_get_contents('e:/htdocs/awstats_misc_tracker.js'), false);
-* // in that case, the modifies string is returned by minify():
-* $out = $jsMin->minify();
-*
-*/
-
-/**
-* Version of this PHP translation.
-*/
-
-define('JSMIN_VERSION', '0.2');
-
-/**
-* How fgetc() reports an End Of File.
-* N.B. : use === and not == to test the result of fgetc() ! (see manual)
-*/
-
-define('EOF', FALSE);
-
-/**
-* Some ASCII character ordinals.
-* N.B. : PHP identifiers are case-insensitive !
-*/
-
-define('ORD_NL', ord("\n"));
-define('ORD_space', ord(' '));
-define('ORD_cA', ord('A'));
-define('ORD_cZ', ord('Z'));
-define('ORD_a', ord('a'));
-define('ORD_z', ord('z'));
-define('ORD_0', ord('0'));
-define('ORD_9', ord('9'));
-
-/**
-* Generic exception class related to JSMin.
-*/
-/*
-class JSMinException extends Exception {
-}
-*/
-class JSMinException {
-}
-
-/**
-* A JSMin exception indicating that a file provided for input or output could not be properly opened.
-*/
-
-class FileOpenFailedJSMinException extends JSMinException {
-}
-
-/**
-* A JSMin exception indicating that an unterminated comment was encountered in input.
-*/
-
-class UnterminatedCommentJSMinException extends JSMinException {
-}
-
-/**
-* A JSMin exception indicatig that an unterminated string literal was encountered in input.
-*/
-
-class UnterminatedStringLiteralJSMinException extends JSMinException {
-}
-
-/**
-* A JSMin exception indicatig that an unterminated regular expression lieteral was encountered in input.
-*/
-
-class UnterminatedRegExpLiteralJSMinException extends JSMinException {
-}
-
-/**
- * Constant describing an {@link action()} : Output A. Copy B to A. Get the next B.
- */
-
-define ('JSMIN_ACT_FULL', 1);
-
-/**
- * Constant describing an {@link action()} : Copy B to A. Get the next B. (Delete A).
- */
-
-define ('JSMIN_ACT_BUF', 2);
-
-/**
- * Constant describing an {@link action()} : Get the next B. (Delete B).
- */
-
-define ('JSMIN_ACT_IMM', 3);
-
-/**
-* Main JSMin application class.
-*
-* Example of use :
-*
-* $jsMin = new JSMin(...input..., ...output...);
-* $jsMin->minify();
-*
-* Do not specify input and/or output (or default to '-') to use stdin and/or stdout.
-*/
-
-class JSMin {
-
- /**
- * The input stream, from which to read a JS file to minimize. Obtained by fopen().
- * NB: might be a string instead of a stream
- * @var SplFileObject | string
- */
- var $in;
-
- /**
- * The output stream, in which to write the minimized JS file. Obtained by fopen().
- * NB: might be a string instead of a stream
- * @var SplFileObject | string
- */
- var $out;
-
- /**
- * Temporary I/O character (A).
- * @var string
- */
- var $theA;
-
- /**
- * Temporary I/O character (B).
- * @var string
- */
- var $theB;
-
- /** variables used for string-based parsing **/
- var $inLength = 0;
- var $inPos = 0;
- var $isString = false;
-
- /**
- * Indicates whether a character is alphanumeric or _, $, \ or non-ASCII.
- *
- * @param string $c The single character to test.
- * @return boolean Whether the char is a letter, digit, underscore, dollar, backslash, or non-ASCII.
- */
- function isAlphaNum($c) {
-
- // Get ASCII value of character for C-like comparisons
-
- $a = ord($c);
-
- // Compare using defined character ordinals, or between PHP strings
- // Note : === is micro-faster than == when types are known to be the same
-
- return
- ($a >= ORD_a && $a <= ORD_z) ||
- ($a >= ORD_0 && $a <= ORD_9) ||
- ($a >= ORD_cA && $a <= ORD_cZ) ||
- $c === '_' || $c === '$' || $c === '\\' || $a > 126
- ;
- }
-
- /**
- * Get the next character from the input stream.
- *
- * If said character is a control character, translate it to a space or linefeed.
- *
- * @return string The next character from the specified input stream.
- * @see $in
- * @see peek()
- */
- function get() {
-
- // Get next input character and advance position in file
-//var_dump($this);
- if ($this->isString) {
- if ($this->inPos < $this->inLength) {
- $c = $this->in[$this->inPos];
- ++$this->inPos;
- }
- else {
- return EOF;
- }
- }
- else
- $c = $this->in->fgetc();
-
- // Test for non-problematic characters
-
- if ($c === "\n" || $c === EOF || ord($c) >= ORD_space) {
- return $c;
- }
-
- // else
- // Make linefeeds into newlines
-
- if ($c === "\r") {
- return "\n";
- }
-
- // else
- // Consider space
-
- return ' ';
- }
-
- /**
- * Get the next character from the input stream, without gettng it.
- *
- * @return string The next character from the specified input stream, without advancing the position
- * in the underlying file.
- * @see $in
- * @see get()
- */
- function peek() {
-
- if ($this->isString) {
- if ($this->inPos < $this->inLength) {
- $c = $this->in[$this->inPos];
- }
- else {
- return EOF;
- }
- }
- else {
- // Get next input character
-
- $c = $this->in->fgetc();
-
- // Regress position in file
-
- $this->in->fseek(-1, SEEK_CUR);
-
- // Return character obtained
- }
-
- return $c;
- }
-
- /**
- * Adds a char to the output steram / string
- * @see $out
- */
- function put($c)
- {
- if ($this->isString) {
- $this->out .= $c;
- }
- else {
- $this->out->fwrite($c);
- }
- }
-
- /**
- * Get the next character from the input stream, excluding comments.
- *
- * {@link peek()} is used to see if a '/' is followed by a '*' or '/'.
- * Multiline comments are actually returned as a single space.
- *
- * @return string The next character from the specified input stream, skipping comments.
- * @see $in
- */
- function next() {
-
- // Get next char from input, translated if necessary
-
- $c = $this->get();
-
- // Check comment possibility
-
- if ($c == '/') {
-
- // Look ahead : a comment is two slashes or slashes followed by asterisk (to be closed)
-
- switch ($this->peek()) {
-
- case '/' :
-
- // Comment is up to the end of the line
- // TOTEST : simple $this->in->fgets()
-
- while (true) {
-
- $c = $this->get();
-
- if (ord($c) <= ORD_NL) {
- return $c;
- }
- }
-
- case '*' :
-
- // Comment is up to comment close.
- // Might not be terminated, if we hit the end of file.
-
- while (true) {
-
- // N.B. not using switch() because of having to test EOF with ===
-
- $c = $this->get();
-
- if ($c == '*') {
-
- // Comment termination if the char ahead is a slash
-
- if ($this->peek() == '/') {
-
- // Advance again and make into a single space
-
- $this->get();
- return ' ';
- }
- }
- else if ($c === EOF) {
-
- // Whoopsie
-
- //throw new UnterminatedCommentJSMinException();
- trigger_error('UnterminatedComment', E_USER_ERROR);
- }
- }
-
- default :
-
- // Not a comment after all
-
- return $c;
- }
- }
-
- // No risk of a comment
-
- return $c;
- }
-
- /**
- * Do something !
- *
- * The action to perform is determined by the argument :
- *
- * JSMin::ACT_FULL : Output A. Copy B to A. Get the next B.
- * JSMin::ACT_BUF : Copy B to A. Get the next B. (Delete A).
- * JSMin::ACT_IMM : Get the next B. (Delete B).
- *
- * A string is treated as a single character. Also, regular expressions are recognized if preceded
- * by '(', ',' or '='.
- *
- * @param int $action The action to perform : one of the JSMin::ACT_* constants.
- */
- function action($action) {
-
- // Choice of possible actions
- // Note the frequent fallthroughs : the actions are decrementally "long"
-
- switch ($action) {
-
- case JSMIN_ACT_FULL :
-
- // Write A to output, then fall through
-
- $this->put($this->theA);
-
- case JSMIN_ACT_BUF : // N.B. possible fallthrough from above
-
- // Copy B to A
-
- $tmpA = $this->theA = $this->theB;
-
- // Treating a string as a single char : outputting it whole
- // Note that the string-opening char (" or ') is memorized in B
-
- if ($tmpA == '\'' || $tmpA == '"') {
-
- while (true) {
-
- // Output string contents
-
- $this->put($tmpA);
-
- // Get next character, watching out for termination of the current string,
- // new line & co (then the string is not terminated !), or a backslash
- // (upon which the following char is directly output to serve the escape mechanism)
-
- $tmpA = $this->theA = $this->get();
-
- if ($tmpA == $this->theB) {
-
- // String terminated
-
- break; // from while(true)
- }
-
- // else
-
- if (ord($tmpA) <= ORD_NL) {
-
- // Whoopsie
-
- //throw new UnterminatedStringLiteralJSMinException();
- trigger_error('UnterminatedStringLiteral', E_USER_ERROR);
- }
-
- // else
-
- if ($tmpA == '\\') {
-
- // Escape next char immediately
-
- $this->put($tmpA);
- $tmpA = $this->theA = $this->get();
- }
- }
- }
-
- case JSMIN_ACT_IMM : // N.B. possible fallthrough from above
-
- // Get the next B
-
- $this->theB = $this->next();
-
- // Special case of recognising regular expressions (beginning with /) that are
- // preceded by '(', ',' or '='
-
- $tmpA = $this->theA;
-
- if ($this->theB == '/' && ($tmpA == '(' || $tmpA == ',' || $tmpA == '=')) {
-
- // Output the two successive chars
-
- $this->put($tmpA);
- $this->put($this->theB);
-
- // Look for the end of the RE literal, watching out for escaped chars or a control /
- // end of line char (the RE literal then being unterminated !)
-
- while (true) {
-
- $tmpA = $this->theA = $this->get();
-
- if ($tmpA == '/') {
-
- // RE literal terminated
-
- break; // from while(true)
- }
-
- // else
-
- if ($tmpA == '\\') {
-
- // Escape next char immediately
-
- $this->put($tmpA);
- $tmpA = $this->theA = $this->get();
- }
- else if (ord($tmpA) <= ORD_NL) {
-
- // Whoopsie
-
- //throw new UnterminatedRegExpLiteralJSMinException();
- trigger_error('UnterminatedRegExpLiteral', E_USER_ERROR);
- }
-
- // Output RE characters
-
- $this->put($tmpA);
- }
-
- // Move forward after the RE literal
-
- $this->theB = $this->next();
- }
-
- break;
- default :
- //throw new JSMinException('Expected a JSMin::ACT_* constant in action().');
- trigger_error('Expected a JSMin::ACT_* constant in action()', E_USER_ERROR);
- }
- }
-
- /**
- * Run the JSMin application : minify some JS code.
- *
- * The code is read from the input stream, and its minified version is written to the output one.
- * In case input is a string, minified vesrions is also returned by this function as string.
- * That is : characters which are insignificant to JavaScript are removed, as well as comments ;
- * tabs are replaced with spaces ; carriage returns are replaced with linefeeds, and finally most
- * spaces and linefeeds are deleted.
- *
- * Note : name was changed from jsmin() because PHP identifiers are case-insensitive, and it is already
- * the name of this class.
- *
- * @see JSMin()
- * @return null | string
- */
- function minify() {
-
- // Initialize A and run the first (minimal) action
-
- $this->theA = "\n";
- $this->action(JSMIN_ACT_IMM);
-
- // Proceed all the way to the end of the input file
-
- while ($this->theA !== EOF) {
-
- switch ($this->theA) {
-
- case ' ' :
-
- if (JSMin::isAlphaNum($this->theB)) {
- $this->action(JSMIN_ACT_FULL);
- }
- else {
- $this->action(JSMIN_ACT_BUF);
- }
-
- break;
- case "\n" :
-
- switch ($this->theB) {
-
- case '{' : case '[' : case '(' :
- case '+' : case '-' :
-
- $this->action(JSMIN_ACT_FULL);
-
- break;
- case ' ' :
-
- $this->action(JSMIN_ACT_IMM);
-
- break;
- default :
-
- if (JSMin::isAlphaNum($this->theB)) {
- $this->action(JSMIN_ACT_FULL);
- }
- else {
- $this->action(JSMIN_ACT_BUF);
- }
-
- break;
- }
-
- break;
- default :
-
- switch ($this->theB) {
-
- case ' ' :
-
- if (JSMin::isAlphaNum($this->theA)) {
-
- $this->action(JSMIN_ACT_FULL);
- break;
- }
-
- // else
-
- $this->action(JSMIN_ACT_IMM);
-
- break;
- case "\n" :
-
- switch ($this->theA) {
-
- case '}' : case ']' : case ')' : case '+' :
- case '-' : case '"' : case '\'' :
-
- $this->action(JSMIN_ACT_FULL);
-
- break;
- default :
-
- if (JSMin::isAlphaNum($this->theA)) {
- $this->action(JSMIN_ACT_FULL);
- }
- else {
- $this->action(JSMIN_ACT_IMM);
- }
-
- break;
- }
-
- break;
- default :
-
- $this->action(JSMIN_ACT_FULL);
-
- break;
- }
-
- break;
- }
- }
-
- if ($this->isString) {
- return $this->out;
-
- }
- }
-
- /**
- * Prepare a new JSMin application.
- *
- * The next step is to {@link minify()} the input into the output.
- *
- * @param string $inFileName The pathname of the input (unminified JS) file. STDIN if '-' or absent.
- * @param string $outFileName The pathname of the output (minified JS) file. STDOUT if '-' or absent.
- * If outFileName === FALSE, we assume that inFileName is in fact the string to be minified!!!
- * @param array $comments Optional lines to present as comments at the beginning of the output.
- */
- function JSMin($inFileName = '-', $outFileName = '-', $comments = NULL) {
- if ($outFileName === FALSE) {
- $this->JSMin_String($inFileName, $comments);
- }
- else {
- $this->JSMin_File($inFileName, $outFileName, $comments);
- }
- }
-
- function JSMin_File($inFileName = '-', $outFileName = '-', $comments = NULL) {
-
- // Recuperate input and output streams.
- // Use STDIN and STDOUT by default, if they are defined (CLI mode) and no file names are provided
-
- if ($inFileName == '-') $inFileName = 'php://stdin';
- if ($outFileName == '-') $outFileName = 'php://stdout';
-
- try {
-
- $this->in = new SplFileObject($inFileName, 'rb', TRUE);
- }
- catch (Exception $e) {
-
- throw new FileOpenFailedJSMinException(
- 'Failed to open "'.$inFileName.'" for reading only.'
- );
- }
-
- try {
-
- $this->out = new SplFileObject($outFileName, 'wb', TRUE);
- }
- catch (Exception $e) {
-
- throw new FileOpenFailedJSMinException(
- 'Failed to open "'.$outFileName.'" for writing only.'
- );
- }
-
- /*$this->in = fopen($inFileName, 'rb');
- if (!$this->in) {
- trigger_error('Failed to open "'.$inFileName, E_USER_ERROR);
- }
- $this->out = fopen($outFileName, 'wb');
- if (!$this->out) {
- trigger_error('Failed to open "'.$outFileName, E_USER_ERROR);
- }*/
-
- // Present possible initial comments
-
- if ($comments !== NULL) {
- foreach ($comments as $comm) {
- $this->out->fwrite('// '.str_replace("\n", " ", $comm)."\n");
- }
- }
-
- }
-
- function JSMin_String($inString, $comments = NULL) {
- $this->in = $inString;
- $this->out = '';
- $this->inLength = strlen($inString);
- $this->inPos = 0;
- $this->isString = true;
-
- if ($comments !== NULL) {
- foreach ($comments as $comm) {
- $this->out .= '// '.str_replace("\n", " ", $comm)."\n";
- }
- }
- }
-}
-
-//
-// OTHER FUNCTIONS
-//
-
-/**
-* Displays inline help for the application.
-*/
-
-function printHelp() {
-
- // All the inline help
-
- echo "\n";
- echo "Usage : JSMin.php [inputFile] [outputFile] [[-c] comm1 comm2 ...]\n";
- echo " JSMin.php [-v|-h]\n";
- echo "\n";
- echo "Minify JavaScript code using JSMin, the JavaScript Minifier.\n";
- echo "\n";
- echo "JSMin is a filter which removes comments and unnecessary whitespace\n";
- echo "from a script read in the inputFile (stdin by default), as well as\n";
- echo "omitting or modifying some characters, before writing the results to\n";
- echo "the outputFile (stdout by default).\n";
- echo "It does not change the behaviour of the program that is minifies.\n";
- echo "The result may be harder to debug. It will definitely be harder to\n";
- echo "read. It typically reduces filesize by half, resulting in faster\n";
- echo "downloads. It also encourages a more expressive programming style\n";
- echo "because it eliminates the download cost of clean, literate self-\n";
- echo "documentation.\n";
- echo "\n";
- echo "The '-' character can be used to explicitely specify a standard\n";
- echo "stream for input or output.\n";
- echo "\n";
- echo "With the optional -c (--comm) option, all following parameters will\n";
- echo "be listed at the beginning of the output as comments. This is a\n";
- echo "convenient way of replacing copyright messages and other info. The\n";
- echo "option is unnecessary if an input and output file are specified :\n";
- echo "following parameters will then automatically be treated thus.\n";
- echo "\n";
- echo "Options :\n";
- echo "\n";
- echo " -c, --comm Present following parameters as initial comments.\n";
- echo " -h, --help Display this information.\n";
- echo " -v, --version Display short version information.\n";
- echo "\n";
- echo "The JavaScript Minifier is copyright (c) 2002 by Douglas Crockford\n";
- echo "and available online at http://javascript.crockford.com/jsmin.html.\n";
- echo "This PHP translation is by David Holmes of CFD Labs, France, 2006.\n";
- echo "\n";
-}
-
-/**
-* Displays version information for the application.
-*/
-
-function printVersion() {
-
- // Minimum info
-
- echo "JSMin, the JavaScript Minifier, copyright (c) 2002 by Douglas Crockford.\n";
- echo "PHP translation version ".JSMIN_VERSION." by David Holmes, CFD Labs.\n";
-}
-
-//
-// ENTRY POINT
-//
-
-// Allow user to include this file without having it run atomatically, ie. as if it was a lib
-if (!defined('JSMIN_AS_LIB')) {
-
-define('EXIT_SUCCESS', 0);
-define('EXIT_FAILURE', 1);
-
-// Examine command-line parameters
-// First shift off the first parameter, the executable's name
-
-if (!isset($argv)) {
- die("Please run this utility from a command line, or set php.ini setting 'register_argc_argv' to true.\nTo use this file in your own code, define 'JSMIN_AS_LIB' before inclusion.");
-}
-
-array_shift($argv);
-
-$inFileName = NULL;
-$outFileName = NULL;
-
-$haveCommentParams = FALSE;
-$comments = array();
-
-foreach ($argv as $arg) {
-
- // Bypass the rest if we are now considering initial comments
-
- if ($haveCommentParams) {
-
- $comments[] = $arg;
- continue;
- }
-
- // else
- // Look for an option (length > 1 because of '-' for indicating stdin or
- // stdout)
-
- if ($arg[0] == '-' && strlen($arg) > 1) {
-
- switch ($arg) {
-
- case '-c' : case '--comm' :
-
- // Following parameters will be initial comments
-
- $haveCommentParams = TRUE;
-
- break;
- case '-h' : case '--help' :
-
- // Display inline help and exit normally
-
- printHelp();
- exit(EXIT_SUCCESS);
-
- case '-v' : case '--version' :
-
- // Display short version information and exit normally
-
- printVersion();
- exit(EXIT_SUCCESS);
-
- default :
-
- // Reject any other (unknown) option
-
- echo "\n";
- echo "ERROR : unknown option \"$arg\", sorry.\n";
-
- printHelp();
- exit(EXIT_FAILURE);
- }
-
- continue;
- }
-
- // else
- // At this point, parameter is neither to be considered as an initial
- // comment, nor is it an option. It is an input or output file.
-
- if ($inFileName === NULL) {
-
- // No input file yet, this is it
-
- $inFileName = $arg;
- }
- else if ($outFileName === NULL) {
-
- // An input file but no output file yet, this is it
-
- $outFileName = $arg;
- }
- else {
-
- // Already have input and output file, this is a first initial comment
-
- $haveCommentParams = TRUE;
- $comments[] = $arg;
- }
-}
-
-if ($inFileName === NULL) $inFileName = '-';
-if ($outFileName === NULL) $outFileName = '-';
-
-// Prepare and run the JSMin application
-// If pathnames are not provided or '-', standard input/output streams are used
-
-$jsMin = new JSMin($inFileName, $outFileName, $comments);
-$jsMin->minify();
-
-}
-
-?> \ No newline at end of file
diff --git a/buildscripts/phing/tasks/PradoPackageTask.php b/buildscripts/phing/tasks/PradoPackageTask.php
index fefeb1e0..8784bb77 100644
--- a/buildscripts/phing/tasks/PradoPackageTask.php
+++ b/buildscripts/phing/tasks/PradoPackageTask.php
@@ -57,6 +57,9 @@ class PradoPackageTask extends Task
$content = preg_replace('/^\s*Prado::trace.*\s*;\s*$/mu','',$content);
$content = preg_replace('/(PradoBase::using|Prado::using|require_once|include_once)\s*\(.*?\);/mu','',$content);
$content = str_replace('Prado::', 'PradoBase::', $content);
+ $content = str_replace('PradoBase::getApplication()->getMode()', 'true', $content);
+ $content = str_replace('TApplicationMode::Debug', 'true', $content);
+ $content = str_replace('/Exceptions/messages', '/messages', $content);
if($this->strip)
$content=$this->strip_comments($content);
$content=$this->strip_empty_lines($content);
diff --git a/framework/3rdParty/geshi/geshi/prado.php b/framework/3rdParty/geshi/geshi/prado.php
index c9d96a35..ba2791f7 100644
--- a/framework/3rdParty/geshi/geshi/prado.php
+++ b/framework/3rdParty/geshi/geshi/prado.php
@@ -140,7 +140,7 @@ $language_data = array (
'<![CDATA[' => ']]>'
),
3 => array(
- '<' => '>'
+ '<' => '/>'
)
),
'HIGHLIGHT_STRICT_BLOCK' => array(
diff --git a/framework/Data/ActiveRecord/TActiveRecord.php b/framework/Data/ActiveRecord/TActiveRecord.php
index 0400661d..1ea06a60 100644
--- a/framework/Data/ActiveRecord/TActiveRecord.php
+++ b/framework/Data/ActiveRecord/TActiveRecord.php
@@ -17,7 +17,10 @@ Prado::using('System.Data.ActiveRecord.TActiveRecordCriteria');
* Base class for active records.
*
* An active record creates an object that wraps a row in a database table
- * or view, encapsulates the database access, and adds domain logic on that data.
+ * or view, encapsulates the database access, and adds domain logic on that data.
+ *
+ * Active record objects are stateful, this is main difference between the
+ * TActiveRecord implementation and the TTableGateway implementation.
*
* The essence of an Active Record is an object model of the
* domain (e.g. products, items) that incorporates both behavior and
@@ -140,7 +143,11 @@ abstract class TActiveRecord extends TComponent
}
/**
- * Returns the instance of a active record finder for a particular class.
+ * Returns the instance of a active record finder for a particular class.
+ * The finder objects are static instances for each ActiveRecord class.
+ * This means that event handlers bound to these finder instances are class wide.
+ * Create a new instance of the ActiveRecord class if you wish to bound the
+ * event handlers to object instance.
* @param string active record class name.
* @return TActiveRecord active record finder instance.
* @throws TActiveRecordException if class name equals 'TActiveRecord'.
@@ -168,6 +175,14 @@ abstract class TActiveRecord extends TComponent
public function getRecordManager()
{
return TActiveRecordManager::getInstance();
+ }
+
+ /**
+ * @return TActiveRecordGateway record table gateway.
+ */
+ public function getRecordGateway()
+ {
+ return $this->getRecordManager()->getRecordGateway();
}
/**
@@ -266,15 +281,20 @@ abstract class TActiveRecord extends TComponent
//try the cache (the cache object must be clean)
if(!is_null($obj = $registry->getCachedInstance($data)))
- return $obj;
+ return $obj;
+
+ $gateway = $this->getRecordManager()->getRecordGateway();
//create and populate the object
$obj = Prado::createComponent($type);
- foreach($data as $name => $value)
- $obj->{$name} = $value;
+ $tableInfo = $gateway->getRecordTableInfo($obj);
+ foreach($tableInfo->getColumns()->getKeys() as $name)
+ {
+ if(isset($data[$name]))
+ $obj->{$name} = $data[$name];
+ }
- $gateway = $this->getRecordManager()->getRecordGateway();
- $obj->_readOnly = $gateway->getRecordTableInfo($this)->getIsView();
+ $obj->_readOnly = $tableInfo->getIsView();
//cache it
return $registry->addCachedInstance($data,$obj);
@@ -484,21 +504,38 @@ abstract class TActiveRecord extends TComponent
else
throw new TActiveRecordException('ar_invalid_criteria');
}
+
+ /**
+ * Raised when a command is prepared and parameter binding is completed.
+ * The parameter object is TDataGatewayEventParameter of which the
+ * {@link TDataGatewayEventParameter::getCommand Command} property can be
+ * inspected to obtain the sql query to be executed.
+ *
+ * Note well that the finder objects obtained from ActiveRecord::finder()
+ * method are static objects. This means that the event handlers are
+ * bound to a static finder object and not to each distinct active record object.
+ * @param TDataGatewayEventParameter
+ */
+ public function onCreateCommand($param)
+ {
+ $this->raiseEvent('OnCreateCommand', $this, $param);
+ }
+
+ /**
+ * Raised when a command is executed and the result from the database was returned.
+ * The parameter object is TDataGatewayResultEventParameter of which the
+ * {@link TDataGatewayEventParameter::getResult Result} property contains
+ * the data return from the database. The data returned can be changed
+ * by setting the {@link TDataGatewayEventParameter::setResult Result} property.
+ *
+ * Note well that the finder objects obtained from ActiveRecord::finder()
+ * method are static objects. This means that the event handlers are
+ * bound to a static finder object and not to each distinct active record object.
+ * @param TDataGatewayResultEventParameter
+ */
+ public function onExecuteCommand($param)
+ {
+ $this->raiseEvent('OnExecuteCommand', $this, $param);
+ }
}
-
-/**
- * TActiveRecordEventParameter class.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.ActiveRecord
- * @since 3.1
- */
-class TActiveRecordEventParameter extends TEventParameter
-{
-
-}
-
-
-
?>
diff --git a/framework/Data/ActiveRecord/TActiveRecordCriteria.php b/framework/Data/ActiveRecord/TActiveRecordCriteria.php
index cc4da7c8..8328b4a6 100644
--- a/framework/Data/ActiveRecord/TActiveRecordCriteria.php
+++ b/framework/Data/ActiveRecord/TActiveRecordCriteria.php
@@ -34,29 +34,7 @@ Prado::using('System.Data.DataGateway.TSqlCriteria');
*/
class TActiveRecordCriteria extends TSqlCriteria
{
- /**
- * This method is invoked before the object is deleted from the database.
- * The method raises 'OnDelete' event.
- * If you override this method, be sure to call the parent implementation
- * so that the event handlers can be invoked.
- * @param TActiveRecordEventParameter event parameter to be passed to the event handlers
- */
- public function onDelete($param)
- {
- $this->raiseEvent('OnDelete', $this, $param);
- }
- /**
- * This method is invoked before any select query is executed on the database.
- * The method raises 'OnSelect' event.
- * If you override this method, be sure to call the parent implementation
- * so that the event handlers can be invoked.
- * @param TActiveRecordEventParameter event parameter to be passed to the event handlers
- */
- public function onSelect($param)
- {
- $this->raiseEvent('OnSelect', $this, $param);
- }
}
?> \ No newline at end of file
diff --git a/framework/Data/ActiveRecord/TActiveRecordGateway.php b/framework/Data/ActiveRecord/TActiveRecordGateway.php
index 9c480ad0..c3239c5c 100644
--- a/framework/Data/ActiveRecord/TActiveRecordGateway.php
+++ b/framework/Data/ActiveRecord/TActiveRecordGateway.php
@@ -1,6 +1,6 @@
<?php
/**
- * TActiveRecordGateway, TActiveRecordStatementType, TActiveRecordGatewayEventParameter classes file.
+ * TActiveRecordGateway, TActiveRecordStatementType, TActiveRecordEventParameter classes file.
*
* @author Wei Zhuo <weizhuo[at]gmail[dot]com>
* @link http://www.pradosoft.com/
@@ -25,6 +25,8 @@ class TActiveRecordGateway extends TComponent
private $_tables=array(); //table cache
private $_meta=array(); //meta data cache.
private $_commandBuilders=array();
+ private $_currentRecord;
+
/**
* Constant name for specifying optional table name in TActiveRecord.
*/
@@ -99,7 +101,7 @@ class TActiveRecordGateway extends TComponent
if(!isset($this->_meta[$connStr]))
{
Prado::using('System.Data.Common.TDbMetaData');
- $this->_meta[$connStr] = TDbMetaData::getMetaData($connection);
+ $this->_meta[$connStr] = TDbMetaData::getInstance($connection);
}
$tableInfo = $this->_meta[$connStr]->getTableInfo($tableName);
}
@@ -123,14 +125,53 @@ class TActiveRecordGateway extends TComponent
{
$builder = $tableInfo->createCommandBuilder($record->getDbConnection());
Prado::using('System.Data.DataGateway.TDataGatewayCommand');
- $this->_commandBuilders[$connStr] = new TDataGatewayCommand($builder);
+ $command = new TDataGatewayCommand($builder);
+ $command->OnCreateCommand[] = array($this, 'onCreateCommand');
+ $command->OnExecuteCommand[] = array($this, 'onExecuteCommand');
+ $this->_commandBuilders[$connStr] = $command;
+
}
$this->_commandBuilders[$connStr]->getBuilder()->setTableInfo($tableInfo);
-
+ $this->_currentRecord=$record;
return $this->_commandBuilders[$connStr];
}
/**
+ * Raised when a command is prepared and parameter binding is completed.
+ * The parameter object is TDataGatewayEventParameter of which the
+ * {@link TDataGatewayEventParameter::getCommand Command} property can be
+ * inspected to obtain the sql query to be executed.
+ * This method also raises the OnCreateCommand event on the ActiveRecord
+ * object calling this gateway.
+ * @param TDataGatewayCommand originator $sender
+ * @param TDataGatewayEventParameter
+ */
+ public function onCreateCommand($sender, $param)
+ {
+ $this->raiseEvent('OnCreateCommand', $this, $param);
+ if($this->_currentRecord!==null)
+ $this->_currentRecord->onCreateCommand($param);
+ }
+
+ /**
+ * Raised when a command is executed and the result from the database was returned.
+ * The parameter object is TDataGatewayResultEventParameter of which the
+ * {@link TDataGatewayEventParameter::getResult Result} property contains
+ * the data return from the database. The data returned can be changed
+ * by setting the {@link TDataGatewayEventParameter::setResult Result} property.
+ * This method also raises the OnCreateCommand event on the ActiveRecord
+ * object calling this gateway.
+ * @param TDataGatewayCommand originator $sender
+ * @param TDataGatewayResultEventParameter
+ */
+ public function onExecuteCommand($sender, $param)
+ {
+ $this->raiseEvent('OnExecuteCommand', $this, $param);
+ if($this->_currentRecord!==null)
+ $this->_currentRecord->onExecuteCommand($param);
+ }
+
+ /**
* Returns record data matching the given primary key(s). If the table uses
* composite key, specify the name value pairs as an array.
* @param TActiveRecord active record instance.
@@ -139,7 +180,8 @@ class TActiveRecordGateway extends TComponent
*/
public function findRecordByPK(TActiveRecord $record,$keys)
{
- return $this->getCommand($record)->findByPk($keys);
+ $command = $this->getCommand($record);
+ return $command->findByPk($keys);
}
/**
@@ -164,10 +206,8 @@ class TActiveRecordGateway extends TComponent
*/
public function findRecordsByCriteria(TActiveRecord $record, $criteria, $iterator=false)
{
- if($iterator)
- return $this->getCommand($record)->findAll($criteria);
- else
- return $this->getCommand($record)->find($criteria);
+ $command = $this->getCommand($record);
+ return $iterator ? $command->findAll($criteria) : $command->find($criteria);
}
/**
@@ -205,6 +245,10 @@ class TActiveRecordGateway extends TComponent
return $result;
}
+ /**
+ * Sets the last insert ID to the corresponding property of the record if available.
+ * @param TActiveRecord record for insertion
+ */
protected function updatePostInsert($record)
{
$command = $this->getCommand($record);
@@ -324,91 +368,16 @@ class TActiveRecordGateway extends TComponent
* @param string command type
* @param TDbCommand sql command to be executed.
* @param TActiveRecord active record
- * @param mixed data for the command.
+ * @param TActiveRecordCriteria data for the command.
*/
- protected function raiseCommandEvent($type,$command,$record=null,$data=null)
+ protected function raiseCommandEvent($event,$command,$record,$criteria)
{
- $param = new TActiveRecordGatewayEventParameter($type,$command,$record,$data);
+ if(!($criteria instanceof TSqlCriteria))
+ $criteria = new TActiveRecordCriteria(null,$criteria);
+ $param = new TActiveRecordEventParameter($command,$record,$criteria);
$manager = $record->getRecordManager();
- $event = 'on'.$type;
- if($data instanceof TActiveRecordCriteria)
- $data->{$event}($param);
$manager->{$event}($param);
- }
-}
-
-/**
- * Command statement types.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.ActiveRecord
- * @since 3.1
- */
-class TActiveRecordStatementType
-{
- const Insert='Insert';
- const Update='Update';
- const Delete='Delete';
- const Select='Select';
-}
-
-/**
- * Active Record command event parameter.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.ActiveRecord
- * @since 3.1
- */
-class TActiveRecordGatewayEventParameter extends TActiveRecordEventParameter
-{
- private $_type;
- private $_command;
- private $_record;
- private $_data;
-
- /**
- * New gateway command event parameter.
- */
- public function __construct($type,$command,$record=null,$data=null)
- {
- $this->_type=$type;
- $this->_command=$command;
- $this->_data=$data;
- $this->_record=$record;
- }
-
- /**
- * @return string TActiveRecordStateType
- */
- public function getType()
- {
- return $this->_type;
- }
-
- /**
- * @return TDbCommand command to be executed.
- */
- public function getCommand()
- {
- return $this->_command;
- }
-
- /**
- * @return TActiveRecord active record.
- */
- public function getRecord()
- {
- return $this->_record;
- }
-
- /**
- * @return mixed command data.
- */
- public function getData()
- {
- return $this->_data;
+ $record->{$event}($param);
}
}
diff --git a/framework/Data/ActiveRecord/TActiveRecordManager.php b/framework/Data/ActiveRecord/TActiveRecordManager.php
index 5e463d2d..ab6fe88d 100644
--- a/framework/Data/ActiveRecord/TActiveRecordManager.php
+++ b/framework/Data/ActiveRecord/TActiveRecordManager.php
@@ -20,20 +20,16 @@ Prado::using('System.Data.ActiveRecord.TActiveRecordStateRegistry');
* TActiveRecordManager provides the default DB connection, default object state
* registry, default active record gateway, and table meta data inspector.
*
- * You can provide a different registry by overriding the {@link createObjectStateRegistry()} method.
- * Similarly, override {@link createRecordGateway()} for default gateway and override
- * {@link createMetaDataInspector() }for meta data inspector.
- *
* The default connection can be set as follows:
* <code>
* TActiveRecordManager::getInstance()->setDbConnection($conn);
* </code>
* All new active record created after setting the
- * {@link DbConnection setDbConnection()} will use that connection.
+ * {@link DbConnection setDbConnection()} will use that connection unless
+ * the custom ActiveRecord class overrides the ActiveRecord::getDbConnection().
*
- * The {@link onInsert()}, {@link onUpdate()},
- * {@link onDelete()} and {@link onSelect()} events are raised
- * <b>before</b> their respective command are executed.
+ * Set the {@link setCache Cache} property to an ICache object to allow
+ * the active record gateway to cache the table meta data information.
*
* @author Wei Zhuo <weizho[at]gmail[dot]com>
* @version $Id$
@@ -84,10 +80,12 @@ class TActiveRecordManager extends TComponent
/**
* @return TActiveRecordManager static instance of record manager.
*/
- public static function getInstance()
+ public static function getInstance($self=null)
{
static $instance;
- if($instance===null)
+ if($self!==null)
+ $instance=$self;
+ else if($instance===null)
$instance = new self;
return $instance;
}
@@ -127,54 +125,6 @@ class TActiveRecordManager extends TComponent
{
return new TActiveRecordGateway($this);
}
-
- /**
- * This method is invoked before the object is inserted into the database.
- * The method raises 'OnInsert' event.
- * If you override this method, be sure to call the parent implementation
- * so that the event handlers can be invoked.
- * @param TActiveRecordEventParameter event parameter to be passed to the event handlers
- */
- public function onInsert($param)
- {
- $this->raiseEvent('OnInsert', $this, $param);
- }
-
- /**
- * This method is invoked before the object is deleted from the database.
- * The method raises 'OnDelete' event.
- * If you override this method, be sure to call the parent implementation
- * so that the event handlers can be invoked.
- * @param TActiveRecordEventParameter event parameter to be passed to the event handlers
- */
- public function onDelete($param)
- {
- $this->raiseEvent('OnDelete', $this, $param);
- }
-
- /**
- * This method is invoked before the object data is updated in the database.
- * The method raises 'OnUpdate' event.
- * If you override this method, be sure to call the parent implementation
- * so that the event handlers can be invoked.
- * @param TActiveRecordEventParameter event parameter to be passed to the event handlers
- */
- public function onUpdate($param)
- {
- $this->raiseEvent('OnUpdate', $this, $param);
- }
-
- /**
- * This method is invoked before any select query is executed on the database.
- * The method raises 'OnSelect' event.
- * If you override this method, be sure to call the parent implementation
- * so that the event handlers can be invoked.
- * @param TActiveRecordEventParameter event parameter to be passed to the event handlers
- */
- public function onSelect($param)
- {
- $this->raiseEvent('OnSelect', $this, $param);
- }
}
diff --git a/framework/Data/Common/Mssql/TMssqlMetaData.php b/framework/Data/Common/Mssql/TMssqlMetaData.php
index c70bc349..5d14aac1 100644
--- a/framework/Data/Common/Mssql/TMssqlMetaData.php
+++ b/framework/Data/Common/Mssql/TMssqlMetaData.php
@@ -1,4 +1,14 @@
<?php
+/**
+ * TMssqlMetaData class file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id: TPgsqlMetaData.php 1866 2007-04-14 05:02:29Z wei $
+ * @package System.Data.Common.Pgsql
+ */
/**
* Load the base TDbMetaData class.
@@ -6,6 +16,14 @@
Prado::using('System.Data.Common.TDbMetaData');
Prado::using('System.Data.Common.Mssql.TMssqlTableInfo');
+/**
+ * TMssqlMetaData loads MSSQL database table and column information.
+ *
+ * @author Wei Zhuo <weizho[at]gmail[dot]com>
+ * @version $Id: TPgsqlMetaData.php 1866 2007-04-14 05:02:29Z wei $
+ * @package System.Data.Commom.Pgsql
+ * @since 3.1
+ */
class TMssqlMetaData extends TDbMetaData
{
/**
@@ -45,9 +63,15 @@ EOD;
$tableInfo = $this->createNewTableInfo($col);
$this->processColumn($tableInfo,$col);
}
+ if($tableInfo===null)
+ throw new TDbException('dbmetadata_invalid_table_view', $table);
return $tableInfo;
}
+ /**
+ * @param string table name
+ * @return array tuple($catalogName,$schemaName,$tableName)
+ */
protected function getCatalogSchemaTableName($table)
{
//remove possible delimiters
diff --git a/framework/Data/Common/Mssql/TMssqlTableColumn.php b/framework/Data/Common/Mssql/TMssqlTableColumn.php
index 77c115e5..f108248d 100644
--- a/framework/Data/Common/Mssql/TMssqlTableColumn.php
+++ b/framework/Data/Common/Mssql/TMssqlTableColumn.php
@@ -37,16 +37,25 @@ class TMssqlTableColumn extends TDbTableColumn
return 'string';
}
+ /**
+ * @return boolean true if the column has identity (auto-increment)
+ */
public function getAutoIncrement()
{
return $this->getInfo('AutoIncrement',false);
}
+ /**
+ * @return boolean true if auto increments.
+ */
public function hasSequence()
{
return $this->getAutoIncrement();
}
+ /**
+ * @return boolean true if db type is 'timestamp'.
+ */
public function getIsExcluded()
{
return strtolower($this->getDbType())==='timestamp';
diff --git a/framework/Data/Common/Mssql/TMssqlTableInfo.php b/framework/Data/Common/Mssql/TMssqlTableInfo.php
index b407ad44..e408440b 100644
--- a/framework/Data/Common/Mssql/TMssqlTableInfo.php
+++ b/framework/Data/Common/Mssql/TMssqlTableInfo.php
@@ -34,6 +34,9 @@ class TMssqlTableInfo extends TDbTableInfo
return $this->getInfo('SchemaName');
}
+ /**
+ * @return string catalog name (database name)
+ */
public function getCatalogName()
{
return $this->getInfo('CatalogName');
@@ -44,6 +47,7 @@ class TMssqlTableInfo extends TDbTableInfo
*/
public function getTableFullName()
{
+ //MSSQL alway returns the catalog, schem and table names.
return '['.$this->getCatalogName().'].['.$this->getSchemaName().'].['.$this->getTableName().']';
}
diff --git a/framework/Data/Common/Mysql/TMysqlMetaData.php b/framework/Data/Common/Mysql/TMysqlMetaData.php
index 9e947298..32d5114f 100644
--- a/framework/Data/Common/Mysql/TMysqlMetaData.php
+++ b/framework/Data/Common/Mysql/TMysqlMetaData.php
@@ -26,6 +26,8 @@ class TMysqlMetaData extends TDbMetaData
$col['index'] = $index++;
$this->processColumn($tableInfo,$col);
}
+ if($index===0)
+ throw new TDbException('dbmetadata_invalid_table_view', $table);
return $tableInfo;
}
diff --git a/framework/Data/Common/Pgsql/TPgsqlMetaData.php b/framework/Data/Common/Pgsql/TPgsqlMetaData.php
index ac7e6b7a..bb03b6cd 100644
--- a/framework/Data/Common/Pgsql/TPgsqlMetaData.php
+++ b/framework/Data/Common/Pgsql/TPgsqlMetaData.php
@@ -109,6 +109,8 @@ EOD;
$col['index'] = $index++;
$this->processColumn($tableInfo, $col);
}
+ if($index===0)
+ throw new TDbException('dbmetadata_invalid_table_view', $table);
return $tableInfo;
}
diff --git a/framework/Data/Common/Sqlite/TSqliteMetaData.php b/framework/Data/Common/Sqlite/TSqliteMetaData.php
index 2ce46fb7..6fcf7b7f 100644
--- a/framework/Data/Common/Sqlite/TSqliteMetaData.php
+++ b/framework/Data/Common/Sqlite/TSqliteMetaData.php
@@ -52,6 +52,8 @@ class TSqliteMetaData extends TDbMetaData
$info['TableName'] = $table;
if($this->getIsView($tableName))
$info['IsView'] = true;
+ if(count($columns)===0)
+ throw new TDbException('dbmetadata_invalid_table_view', $tableName);
$tableInfo = new TSqliteTableInfo($info,$primary,$foreign);
$tableInfo->getColumns()->copyFrom($columns);
return $tableInfo;
diff --git a/framework/Data/Common/Sqlite/TSqliteTableColumn.php b/framework/Data/Common/Sqlite/TSqliteTableColumn.php
index b8287218..80dcd9d9 100644
--- a/framework/Data/Common/Sqlite/TSqliteTableColumn.php
+++ b/framework/Data/Common/Sqlite/TSqliteTableColumn.php
@@ -25,6 +25,9 @@ Prado::using('System.Data.Common.TDbTableColumn');
*/
class TSqliteTableColumn extends TDbTableColumn
{
+ /**
+ * @TODO add sqlite types.
+ */
private static $types = array();
/**
diff --git a/framework/Data/Common/TDbMetaData.php b/framework/Data/Common/TDbMetaData.php
index 6838d7dc..d0963f44 100644
--- a/framework/Data/Common/TDbMetaData.php
+++ b/framework/Data/Common/TDbMetaData.php
@@ -47,7 +47,7 @@ abstract class TDbMetaData extends TComponent
* @param TDbConnection database connection.
* @return TDbMetaData database specific TDbMetaData.
*/
- public static function getMetaData($conn)
+ public static function getInstance($conn)
{
$conn->setActive(true); //must be connected before retrieving driver name
$driver = $conn->getDriverName();
diff --git a/framework/Data/Common/TDbTableColumn.php b/framework/Data/Common/TDbTableColumn.php
index 6ff2ff46..84fb238c 100644
--- a/framework/Data/Common/TDbTableColumn.php
+++ b/framework/Data/Common/TDbTableColumn.php
@@ -100,7 +100,7 @@ class TDbTableColumn extends TComponent
}
/**
- * @return integer one-based ordinal position of the column in the table.
+ * @return integer zero-based ordinal position of the column in the table.
*/
public function getColumnIndex()
{
diff --git a/framework/Data/DataGateway/TDataGatewayCommand.php b/framework/Data/DataGateway/TDataGatewayCommand.php
index 8a340ee7..dbabd2b7 100644
--- a/framework/Data/DataGateway/TDataGatewayCommand.php
+++ b/framework/Data/DataGateway/TDataGatewayCommand.php
@@ -1,5 +1,39 @@
<?php
+/**
+ * TDataGatewayCommand, TDataGatewayEventParameter and TDataGatewayResultEventParameter class file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Data.DataGateway
+ */
+/**
+ * TDataGatewayCommand is command builder and executor class for
+ * TTableGateway and TActiveRecordGateway.
+ *
+ * TDataGatewayCommand builds the TDbCommand for TTableGateway
+ * and TActiveRecordGateway commands such as find(), update(), insert(), etc,
+ * using the TDbCommandBuilder classes (database specific TDbCommandBuilder
+ * classes are used).
+ *
+ * Once the command is built and the query parameters are binded, the
+ * {@link OnCreateCommand} event is raised. Event handlers for the OnCreateCommand
+ * event should not alter the Command property nor the Criteria property of the
+ * TDataGatewayEventParameter.
+ *
+ * TDataGatewayCommand excutes the TDbCommands and returns the result obtained from the
+ * database (returned value depends on the method executed). The
+ * {@link OnExecuteCommand} event is raised after the command is executed and resulting
+ * data is set in the TDataGatewayResultEventParameter object's Result property.
+ *
+ * @author Wei Zhuo <weizho[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.DataGateway
+ * @since 3.1
+ */
class TDataGatewayCommand extends TComponent
{
private $_builder;
@@ -46,6 +80,7 @@ class TDataGatewayCommand extends TComponent
$where = $criteria->getCondition();
$parameters = $criteria->getParameters()->toArray();
$command = $this->getBuilder()->createDeleteCommand($where, $parameters);
+ $this->onCreateCommand($command,$criteria);
$command->prepare();
return $command->execute();
}
@@ -61,8 +96,9 @@ class TDataGatewayCommand extends TComponent
$where = $criteria->getCondition();
$parameters = $criteria->getParameters()->toArray();
$command = $this->getBuilder()->createUpdateCommand($data,$where, $parameters);
+ $this->onCreateCommand($command,$criteria);
$command->prepare();
- return $command->execute();
+ return $this->onExecuteCommand($command, $command->execute());
}
/**
@@ -83,7 +119,8 @@ class TDataGatewayCommand extends TComponent
*/
public function find($criteria)
{
- return $this->getFindCommand($criteria)->queryRow();
+ $command = $this->getFindCommand($criteria);
+ return $this->onExecuteCommand($command, $command->queryRow());
}
/**
@@ -93,7 +130,27 @@ class TDataGatewayCommand extends TComponent
*/
public function findAll($criteria)
{
- return $this->getFindCommand($criteria)->query();
+ $command = $this->getFindCommand($criteria);
+ return $this->onExecuteCommand($command, $command->query());
+ }
+
+ /**
+ * Build the find command from the criteria. Limit, Offset and Ordering are applied if applicable.
+ * @param TSqlCriteria $criteria
+ * @return TDbCommand.
+ */
+ protected function getFindCommand($criteria)
+ {
+ if($criteria===null)
+ return $this->getBuilder()->createFindCommand();
+ $where = $criteria->getCondition();
+ $parameters = $criteria->getParameters()->toArray();
+ $ordering = $criteria->getOrdersBy();
+ $limit = $criteria->getLimit();
+ $offset = $criteria->getOffset();
+ $command = $this->getBuilder()->createFindCommand($where,$parameters,$ordering,$limit,$offset);
+ $this->onCreateCommand($command, $criteria);
+ return $command;
}
/**
@@ -104,7 +161,8 @@ class TDataGatewayCommand extends TComponent
{
list($where, $parameters) = $this->getPrimaryKeyCondition((array)$keys);
$command = $this->getBuilder()->createFindCommand($where, $parameters);
- return $command->queryRow();
+ $this->onCreateCommand($command, new TSqlCriteria($where,$parameters));
+ return $this->onExecuteCommand($command, $command->queryRow());
}
/**
@@ -115,7 +173,8 @@ class TDataGatewayCommand extends TComponent
{
$where = $this->getCompositeKeyCondition((array)$keys);
$command = $this->getBuilder()->createFindCommand($where);
- return $command->query();
+ $this->onCreateCommand($command, new TSqlCriteria($where,$keys));
+ return $this->onExecuteCommand($command,$command->query());
}
/**
@@ -126,8 +185,9 @@ class TDataGatewayCommand extends TComponent
{
$where = $this->getCompositeKeyCondition((array)$keys);
$command = $this->getBuilder()->createDeleteCommand($where);
+ $this->onCreateCommand($command, new TSqlCriteria($where,$keys));
$command->prepare();
- return $command->execute();
+ return $this->onExecuteCommand($command,$command->execute());
}
/**
@@ -209,7 +269,8 @@ class TDataGatewayCommand extends TComponent
*/
public function findBySql($criteria)
{
- return $this->getSqlCommand($criteria)->query();
+ $command = $this->getSqlCommand($criteria);
+ return $this->onExecuteCommand($command, $command->query());
}
/**
@@ -229,27 +290,11 @@ class TDataGatewayCommand extends TComponent
$sql = $this->getBuilder()->applyLimitOffset($sql, $limit, $offset);
$command = $this->getBuilder()->createCommand($sql);
$this->getBuilder()->bindArrayValues($command, $criteria->getParameters()->toArray());
+ $this->onCreateCommand($command, $criteria);
return $command;
}
/**
- * Build the find command from the criteria. Limit, Offset and Ordering are applied if applicable.
- * @param TSqlCriteria $criteria
- * @return TDbCommand.
- */
- protected function getFindCommand($criteria)
- {
- if($criteria===null)
- return $this->getBuilder()->createFindCommand();
- $where = $criteria->getCondition();
- $parameters = $criteria->getParameters()->toArray();
- $ordering = $criteria->getOrdersBy();
- $limit = $criteria->getLimit();
- $offset = $criteria->getOffset();
- return $this->getBuilder()->createFindCommand($where,$parameters,$ordering,$limit,$offset);
- }
-
- /**
* @param TSqlCriteria $criteria
* @return integer number of records.
*/
@@ -263,7 +308,8 @@ class TDataGatewayCommand extends TComponent
$limit = $criteria->getLimit();
$offset = $criteria->getOffset();
$command = $this->getBuilder()->createCountCommand($where,$parameters,$ordering,$limit,$offset);
- return intval($command->queryScalar());
+ $this->onCreateCommand($command, $criteria);
+ return $this->onExecuteCommand($command, intval($command->queryScalar()));
}
/**
@@ -276,8 +322,9 @@ class TDataGatewayCommand extends TComponent
public function insert($data)
{
$command=$this->getBuilder()->createInsertCommand($data);
+ $this->onCreateCommand($command, new TSqlCriteria(null,$data));
$command->prepare();
- if($command->execute() > 0)
+ if($this->onExecuteCommand($command, $command->execute()) > 0)
{
$value = $this->getLastInsertId();
return $value !== null ? $value : true;
@@ -344,6 +391,120 @@ class TDataGatewayCommand extends TComponent
}
return $fields;
}
+
+ /**
+ * Raised when a command is prepared and parameter binding is completed.
+ * The parameter object is TDataGatewayEventParameter of which the
+ * {@link TDataGatewayEventParameter::getCommand Command} property can be
+ * inspected to obtain the sql query to be executed.
+ * @param TDataGatewayCommand originator $sender
+ * @param TDataGatewayEventParameter
+ */
+ public function onCreateCommand($command, $criteria)
+ {
+ $this->raiseEvent('OnCreateCommand', $this, new TDataGatewayEventParameter($command,$criteria));
+ }
+
+ /**
+ * Raised when a command is executed and the result from the database was returned.
+ * The parameter object is TDataGatewayResultEventParameter of which the
+ * {@link TDataGatewayEventParameter::getResult Result} property contains
+ * the data return from the database. The data returned can be changed
+ * by setting the {@link TDataGatewayEventParameter::setResult Result} property.
+ * @param TDataGatewayCommand originator $sender
+ * @param TDataGatewayResultEventParameter
+ */
+ public function onExecuteCommand($command, $result)
+ {
+ $parameter = new TDataGatewayResultEventParameter($command, $result);
+ $this->raiseEvent('OnExecuteCommand', $this, $parameter);
+ return $parameter->getResult();
+ }
+}
+
+/**
+ * TDataGatewayEventParameter class contains the TDbCommand to be executed as
+ * well as the criteria object.
+ *
+ * @author Wei Zhuo <weizho[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.DataGateway
+ * @since 3.1
+ */
+class TDataGatewayEventParameter extends TEventParameter
+{
+ private $_command;
+ private $_criteria;
+
+ public function __construct($command,$criteria)
+ {
+ $this->_command=$command;
+ $this->_criteria=$criteria;
+ }
+
+ /**
+ * The database command to be executed. Do not rebind the parameters or change
+ * the sql query string.
+ * @return TDbCommand command to be executed.
+ */
+ public function getCommand()
+ {
+ return $this->_command;
+ }
+
+ /**
+ * @return TSqlCriteria criteria used to bind the sql query parameters.
+ */
+ public function getCriteria()
+ {
+ return $this->_criteria;
+ }
+}
+
+/**
+ * TDataGatewayResultEventParameter contains the TDbCommand executed and the resulting
+ * data returned from the database. The data can be changed by changing the
+ * {@link setResult Result} property.
+ *
+ * @author Wei Zhuo <weizho[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.DataGateway
+ * @since 3.1
+ */
+class TDataGatewayResultEventParameter extends TEventParameter
+{
+ private $_command;
+ private $_result;
+
+ public function __construct($command,$result)
+ {
+ $this->_command=$command;
+ $this->_result=$result;
+ }
+
+ /**
+ * @return TDbCommand database command executed.
+ */
+ public function getCommand()
+ {
+ return $this->_command;
+ }
+
+ /**
+ * @return mixed result returned from executing the command.
+ */
+ public function getResult()
+ {
+ return $this->_result;
+ }
+
+ /**
+ * @param mixed change the result returned by the gateway.
+ */
+ public function setResult($value)
+ {
+ $this->_result=$value;
+ }
}
?> \ No newline at end of file
diff --git a/framework/Data/DataGateway/TSqlCriteria.php b/framework/Data/DataGateway/TSqlCriteria.php
index ac5f00f2..d073cd10 100644
--- a/framework/Data/DataGateway/TSqlCriteria.php
+++ b/framework/Data/DataGateway/TSqlCriteria.php
@@ -7,7 +7,7 @@
* @copyright Copyright &copy; 2005-2007 PradoSoft
* @license http://www.pradosoft.com/license/
* @version $Id: TDbSqlCriteria.php 1835 2007-04-03 01:38:15Z wei $
- * @package System.Data.Common
+ * @package System.Data.DataGateway
*/
/**
@@ -26,7 +26,7 @@
*
* @author Wei Zhuo <weizho[at]gmail[dot]com>
* @version $Id: TDbSqlCriteria.php 1835 2007-04-03 01:38:15Z wei $
- * @package System.Data.Common
+ * @package System.Data.DataGateway
* @since 3.1
*/
class TSqlCriteria extends TComponent
diff --git a/framework/Data/DataGateway/TTableGateway.php b/framework/Data/DataGateway/TTableGateway.php
index 6a77c064..f278eed5 100644
--- a/framework/Data/DataGateway/TTableGateway.php
+++ b/framework/Data/DataGateway/TTableGateway.php
@@ -1,27 +1,163 @@
-<?php
+<?php
+/**
+ * TTableGateway class file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Data.DataGateway
+ */
+/**
+ * Loads the data gateway command builder and sql criteria.
+ */
Prado::using('System.Data.DataGateway.TSqlCriteria');
Prado::using('System.Data.DataGateway.TDataGatewayCommand');
+/**
+ * TTableGateway class provides several find methods to get data from the database
+ * and update, insert, and delete methods.
+ *
+ * Each method maps the input parameters into a SQL call and executes the SQL
+ * against a database connection. The TTableGateway is stateless
+ * (with respect to the data and data objects), as its role is to push data back and forth.
+ *
+ * Example usage:
+ * <code>
+ * //create a connection
+ * $dsn = 'pgsql:host=localhost;dbname=test';
+ * $conn = new TDbConnection($dsn, 'dbuser','dbpass');
+ *
+ * //create a table gateway for table/view named 'address'
+ * $table = new TTableGateway('address', $conn);
+ *
+ * //insert a new row, returns last insert id (if applicable)
+ * $id = $table->insert(array('name'=>'wei', 'phone'=>'111111'));
+ *
+ * $record1 = $table->findByPk($id); //find inserted record
+ *
+ * //finds all records, returns an iterator
+ * $records = $table->findAll();
+ * print_r($records->readAll());
+ *
+ * //update the row
+ * $table->updateByPk($record1, $id);
+ * </code>
+ *
+ * All methods that may return more than one row of data will return an
+ * TDbDataReader iterator.
+ *
+ * The OnCreateCommand event is raised when a command is prepared and parameter
+ * binding is completed. The parameter object is a TDataGatewayEventParameter of which the
+ * {@link TDataGatewayEventParameter::getCommand Command} property can be
+ * inspected to obtain the sql query to be executed.
+ *
+ * The OnExecuteCommand event is raised when a command is executed and the result
+ * from the database was returned. The parameter object is a
+ * TDataGatewayResultEventParameter of which the
+ * {@link TDataGatewayEventParameter::getResult Result} property contains
+ * the data return from the database. The data returned can be changed
+ * by setting the {@link TDataGatewayEventParameter::setResult Result} property.
+ *
+ * <code>
+ * $table->OnCreateCommand[] = 'log_it'; //any valid PHP callback statement
+ * $table->OnExecuteCommand[] = array($obj, 'method_name'); // calls 'method_name' on $obj
+ *
+ * function log_it($sender, $param)
+ * {
+ * var_dump($param); //TDataGatewayEventParameter object.
+ * }
+ * </code>
+ *
+ * @author Wei Zhuo <weizho[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.DataGateway
+ * @since 3.1
+ */
class TTableGateway extends TComponent
{
private $_command;
private $_connection;
- public function __construct($tableName,$connection)
+ /**
+ * Creates a new generic table gateway for a given table or view name
+ * and a database connection.
+ * @param string|TDbTableInfo table or view name or table information.
+ * @param TDbConnection database connection.
+ */
+ public function __construct($table,$connection)
{
$this->_connection=$connection;
- $this->setTableName($tableName);
+ if(is_string($table))
+ $this->setTableName($table);
+ else if($table instanceof TDbTableInfo)
+ $this->setTableInfo($table);
+ else
+ throw new TDbException('dbtablegateway_invalid_table_info');
+ }
+
+ /**
+ * @param TDbTableInfo table or view information.
+ */
+ protected function setTableInfo($tableInfo)
+ {
+ $builder = $tableInfo->createCommandBuilder($this->getDbConnection());
+ $this->initCommandBuilder($builder);
}
+ /**
+ * Sets up the command builder for the given table.
+ * @param string table or view name.
+ */
protected function setTableName($tableName)
{
Prado::using('System.Data.Common.TDbMetaData');
- $meta = TDbMetaData::getMetaData($this->getDbConnection());
- $builder = $meta->createCommandBuilder($tableName);
+ $meta = TDbMetaData::getInstance($this->getDbConnection());
+ $this->initCommandBuilder($meta->createCommandBuilder($tableName));
+ }
+
+ /**
+ * @param TDbCommandBuilder database specific command builder.
+ */
+ protected function initCommandBuilder($builder)
+ {
$this->_command = new TDataGatewayCommand($builder);
+ $this->_command->OnCreateCommand[] = array($this, 'onCreateCommand');
+ $this->_command->OnExecuteCommand[] = array($this, 'onExecuteCommand');
}
+ /**
+ * Raised when a command is prepared and parameter binding is completed.
+ * The parameter object is TDataGatewayEventParameter of which the
+ * {@link TDataGatewayEventParameter::getCommand Command} property can be
+ * inspected to obtain the sql query to be executed.
+ * @param TDataGatewayCommand originator $sender
+ * @param TDataGatewayEventParameter
+ */
+ public function onCreateCommand($sender, $param)
+ {
+ $this->raiseEvent('OnCreateCommand', $this, $param);
+ }
+
+ /**
+ * Raised when a command is executed and the result from the database was returned.
+ * The parameter object is TDataGatewayResultEventParameter of which the
+ * {@link TDataGatewayEventParameter::getResult Result} property contains
+ * the data return from the database. The data returned can be changed
+ * by setting the {@link TDataGatewayEventParameter::setResult Result} property.
+ * @param TDataGatewayCommand originator $sender
+ * @param TDataGatewayResultEventParameter
+ */
+ public function onExecuteCommand($sender, $param)
+ {
+ $this->raiseEvent('OnExecuteCommand', $this, $param);
+ }
+
+ /**
+ * @return TDataGatewayCommand command builder and executor.
+ */
protected function getCommand()
{
return $this->_command;
diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt
index ca7faed1..b3074ad6 100644
--- a/framework/Exceptions/messages.txt
+++ b/framework/Exceptions/messages.txt
@@ -371,12 +371,15 @@ dbcommandbuilder_value_must_not_be_null = Property {0} must not be null as defin
dbcommon_invalid_table_name = Database table '{0}' not found. Error Msg: {1}.
dbcommon_invalid_identifier_name = Invalid database identifier name '{0}', see {1} for details.
dbtableinfo_invalid_column_name = Invalid column name '{0}' for database table '{1}'.
+dbmetadata_invalid_table_view = Invalid table/view name '{0}', or that table/view '{0}' contains no accessible column/field definitions.
+
dbtablegateway_invalid_criteria = Invalid criteria object, must be a string or instance of TSqlCriteria.
dbtablegateway_no_primary_key_found = Table '{0}' does not contain any primary key fields.
dbtablegateway_missing_pk_values = Missing primary key values in forming IN(key1, key2, ...) for table '{0}'.
dbtablegateway_pk_value_count_mismatch = Composite key value count mismatch in forming IN( (key1, key2, ..), (key3, key4, ..)) for table '{0}'.
dbtablegateway_mismatch_args_exception = TTableGateway finder method '{0}' expects {1} parameters but found only {2} parameters instead.
dbtablegateway_mismatch_column_name = In dynamic __call() method '{0}', no matching columns were found, valid columns for table '{2}' are '{1}'.
+dbtablegateway_invalid_table_info = Table must be a string or an instanceof TDbTableInfo.
directorycachedependency_directory_invalid = TDirectoryCacheDependency.Directory {0} does not refer to a valid directory.
cachedependencylist_cachedependency_required = Only objects implementing ICacheDependency can be added into TCacheDependencyList.
diff --git a/tests/simple_unit/ActiveRecord/RecordEventTestCase.php b/tests/simple_unit/ActiveRecord/RecordEventTestCase.php
index c669bb72..fad54eb0 100644
--- a/tests/simple_unit/ActiveRecord/RecordEventTestCase.php
+++ b/tests/simple_unit/ActiveRecord/RecordEventTestCase.php
@@ -9,24 +9,28 @@ class RecordEventTestCase extends UnitTestCase
$conn = new TDbConnection('pgsql:host=localhost;dbname=test', 'test','test');
TActiveRecordManager::getInstance()->setDbConnection($conn);
}
-
+/*
function testFindByPk()
{
$user1 = UserRecord::finder()->findByPk('admin');
$this->assertNotNull($user1);
}
-
+*/
function test_same_data_returns_same_object()
{
$criteria = new TActiveRecordCriteria('username = ?', 'admin');
- $criteria->OnSelect = array($this, 'logger');
- $user1 = UserRecord::finder()->find($criteria);
- //var_dump($user1);
+ $finder = new UserRecord();
+ $finder->OnCreateCommand[] = array($this, 'logger');
+ $finder->OnExecuteCommand[] = array($this, 'logger');
+ $user1 = $finder->find($criteria);
+ var_dump($user1);
+
+ var_dump(UserRecord::finder()->find($criteria));
}
function logger($sender, $param)
{
- var_dump($param->Command->Text);
+ var_dump($param);
}
}
diff --git a/tests/simple_unit/SqlMap/ActiveRecordSqlMapTest.php b/tests/simple_unit/SqlMap/ActiveRecordSqlMapTest.php
index 63d62534..81ce93bb 100644
--- a/tests/simple_unit/SqlMap/ActiveRecordSqlMapTest.php
+++ b/tests/simple_unit/SqlMap/ActiveRecordSqlMapTest.php
@@ -65,7 +65,9 @@ class ActiveRecordSqlMapTest extends BaseCase
$this->assertTrue($record->save());
$check1 = $this->sqlmap->queryForObject('GetActiveRecordAccounts');
- $check2 = ActiveAccount::finder()->findByAccount_FirstName($record->Account_FirstName);
+ $finder = ActiveAccount::finder();
+ $check2 = $finder->findByAccount_FirstName($record->Account_FirstName);
+
$this->assertSameAccount($record,$check1);
$this->assertSameAccount($record,$check2);
diff --git a/tests/simple_unit/TableGateway/BaseGatewayTest.php b/tests/simple_unit/TableGateway/BaseGatewayTest.php
index 825f2d0e..ff7a58b0 100644
--- a/tests/simple_unit/TableGateway/BaseGatewayTest.php
+++ b/tests/simple_unit/TableGateway/BaseGatewayTest.php
@@ -88,7 +88,7 @@ class BaseGatewayTest extends UnitTestCase
}
function delete_all()
{
- $this->getGateway()->deleteAll('true');
+ $this->getGateway()->deleteAll('1=1');
}
}
?> \ No newline at end of file
diff --git a/tests/simple_unit/TableGateway/TableInfoGatewayTest.php b/tests/simple_unit/TableGateway/TableInfoGatewayTest.php
new file mode 100644
index 00000000..2be848c5
--- /dev/null
+++ b/tests/simple_unit/TableGateway/TableInfoGatewayTest.php
@@ -0,0 +1,17 @@
+<?php
+
+require_once(dirname(__FILE__).'/BaseGatewayTest.php');
+
+class TableInfoGatewayTest extends BaseGatewayTest
+{
+ function test_table_info()
+ {
+ $conn = $this->getGateway()->getDbConnection();
+ $this->add_record1();
+ $this->add_record2();
+ $info = TDbMetaData::getInstance($conn)->getTableInfo('address');
+ $table = new TTableGateway($info, $conn);
+ $this->assertEqual(count($table->findAll()->readAll()), 2);
+ }
+}
+?> \ No newline at end of file