From 4a2ebb333d239b58c19d09ee88646fa0e32e71ed Mon Sep 17 00:00:00 2001 From: wei <> Date: Mon, 16 Apr 2007 02:02:27 +0000 Subject: Updates to db stuff, removed js build from build.xml (no longer necessary) --- .gitattributes | 3 +- .gitignore | 1 - build.xml | 41 +- buildscripts/jsbuilder/build.php | 121 --- buildscripts/jsbuilder/jsmin.php | 931 --------------------- buildscripts/phing/tasks/PradoPackageTask.php | 3 + framework/3rdParty/geshi/geshi/prado.php | 2 +- framework/Data/ActiveRecord/TActiveRecord.php | 83 +- .../Data/ActiveRecord/TActiveRecordCriteria.php | 22 - .../Data/ActiveRecord/TActiveRecordGateway.php | 149 ++-- .../Data/ActiveRecord/TActiveRecordManager.php | 66 +- framework/Data/Common/Mssql/TMssqlMetaData.php | 24 + framework/Data/Common/Mssql/TMssqlTableColumn.php | 9 + framework/Data/Common/Mssql/TMssqlTableInfo.php | 4 + framework/Data/Common/Mysql/TMysqlMetaData.php | 2 + framework/Data/Common/Pgsql/TPgsqlMetaData.php | 2 + framework/Data/Common/Sqlite/TSqliteMetaData.php | 2 + .../Data/Common/Sqlite/TSqliteTableColumn.php | 3 + framework/Data/Common/TDbMetaData.php | 2 +- framework/Data/Common/TDbTableColumn.php | 2 +- framework/Data/DataGateway/TDataGatewayCommand.php | 213 ++++- framework/Data/DataGateway/TSqlCriteria.php | 4 +- framework/Data/DataGateway/TTableGateway.php | 146 +++- framework/Exceptions/messages.txt | 3 + .../ActiveRecord/RecordEventTestCase.php | 16 +- .../simple_unit/SqlMap/ActiveRecordSqlMapTest.php | 4 +- tests/simple_unit/TableGateway/BaseGatewayTest.php | 2 +- .../TableGateway/TableInfoGatewayTest.php | 17 + 28 files changed, 570 insertions(+), 1307 deletions(-) delete mode 100644 buildscripts/jsbuilder/build.php delete mode 100644 buildscripts/jsbuilder/jsmin.php create mode 100644 tests/simple_unit/TableGateway/TableInfoGatewayTest.php 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 @@ - + - + + @@ -36,7 +37,7 @@ - + - + Building pradolite.php... @@ -234,7 +250,7 @@ - + @@ -290,7 +306,7 @@ Generating CHM Content (Quickstart + ClassDocs) - @@ -366,11 +382,6 @@ the PRADO distribution: - - - - - @@ -425,7 +436,7 @@ the PRADO distribution: - + 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 -, Qiang Xue - * @link http://www.pradosoft.com/ - * @copyright Copyright © 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 @@ - 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 ( ' ']]>' ), 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 - * @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 @@ * @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,13 +125,52 @@ 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. @@ -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 - * @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 - * @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: * * TActiveRecordManager::getInstance()->setDbConnection($conn); * * 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 - * before 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 * @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 @@ + * @link http://www.pradosoft.com/ + * @copyright Copyright © 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 + * @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 @@ + * @link http://www.pradosoft.com/ + * @copyright Copyright © 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 + * @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,26 +290,10 @@ 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 + * @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 + * @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 © 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 * @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 @@ - + * @link http://www.pradosoft.com/ + * @copyright Copyright © 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: + * + * //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); + * + * + * 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. + * + * + * $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. + * } + * + * + * @author Wei Zhuo + * @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 @@ +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 -- cgit v1.2.3