summaryrefslogtreecommitdiff
path: root/_darcs/pristine/extlib/DB/DataObject/Generator.php
diff options
context:
space:
mode:
Diffstat (limited to '_darcs/pristine/extlib/DB/DataObject/Generator.php')
-rw-r--r--_darcs/pristine/extlib/DB/DataObject/Generator.php1553
1 files changed, 0 insertions, 1553 deletions
diff --git a/_darcs/pristine/extlib/DB/DataObject/Generator.php b/_darcs/pristine/extlib/DB/DataObject/Generator.php
deleted file mode 100644
index de16af692..000000000
--- a/_darcs/pristine/extlib/DB/DataObject/Generator.php
+++ /dev/null
@@ -1,1553 +0,0 @@
-<?php
-/**
- * Generation tools for DB_DataObject
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.0 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_0.txt. If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category Database
- * @package DB_DataObject
- * @author Alan Knowles <alan@akbkhome.com>
- * @copyright 1997-2006 The PHP Group
- * @license http://www.php.net/license/3_0.txt PHP License 3.0
- * @version CVS: $Id: Generator.php,v 1.141 2008/01/30 02:29:39 alan_k Exp $
- * @link http://pear.php.net/package/DB_DataObject
- */
-
- /*
- * Security Notes:
- * This class uses eval to create classes on the fly.
- * The table name and database name are used to check the database before writing the
- * class definitions, we now check for quotes and semi-colon's in both variables
- * so I cant see how it would be possible to generate code even if
- * for some crazy reason you took the classname and table name from User Input.
- *
- * If you consider that wrong, or can prove it.. let me know!
- */
-
- /**
- *
- * Config _$ptions
- * [DB_DataObject_Generator]
- * ; optional default = DB/DataObject.php
- * extends_location =
- * ; optional default = DB_DataObject
- * extends =
- * ; alter the extends field when updating a class (defaults to only replacing DB_DataObject)
- * generator_class_rewrite = ANY|specific_name // default is DB_DataObject
- *
- */
-
-/**
- * Needed classes
- * We lazy load here, due to problems with the tests not setting up include path correctly.
- * FIXME!
- */
-class_exists('DB_DataObject') ? '' : require_once 'DB/DataObject.php';
-//require_once('Config.php');
-
-/**
- * Generator class
- *
- * @package DB_DataObject
- */
-class DB_DataObject_Generator extends DB_DataObject
-{
- /* =========================================================== */
- /* Utility functions - for building db config files */
- /* =========================================================== */
-
- /**
- * Array of table names
- *
- * @var array
- * @access private
- */
- var $tables;
-
- /**
- * associative array table -> array of table row objects
- *
- * @var array
- * @access private
- */
- var $_definitions;
-
- /**
- * active table being output
- *
- * @var string
- * @access private
- */
- var $table; // active tablename
-
-
- /**
- * The 'starter' = call this to start the process
- *
- * @access public
- * @return none
- */
- function start()
- {
- $options = &PEAR::getStaticProperty('DB_DataObject','options');
- $db_driver = empty($options['db_driver']) ? 'DB' : $options['db_driver'];
-
- $databases = array();
- foreach($options as $k=>$v) {
- if (substr($k,0,9) == 'database_') {
- $databases[substr($k,9)] = $v;
- }
- }
-
- if (isset($options['database'])) {
- if ($db_driver == 'DB') {
- require_once 'DB.php';
- $dsn = DB::parseDSN($options['database']);
- } else {
- require_once 'MDB2.php';
- $dsn = MDB2::parseDSN($options['database']);
- }
-
- if (!isset($database[$dsn['database']])) {
- $databases[$dsn['database']] = $options['database'];
- }
- }
-
- foreach($databases as $databasename => $database) {
- if (!$database) {
- continue;
- }
- $this->debug("CREATING FOR $databasename\n");
- $class = get_class($this);
- $t = new $class;
- $t->_database_dsn = $database;
-
-
- $t->_database = $databasename;
- if ($db_driver == 'DB') {
- require_once 'DB.php';
- $dsn = DB::parseDSN($database);
- } else {
- require_once 'MDB2.php';
- $dsn = MDB2::parseDSN($database);
- }
-
- if (($dsn['phptype'] == 'sqlite') && is_file($databasename)) {
- $t->_database = basename($t->_database);
- }
- $t->_createTableList();
-
- foreach(get_class_methods($class) as $method) {
- if (substr($method,0,8 ) != 'generate') {
- continue;
- }
- $this->debug("calling $method");
- $t->$method();
- }
- }
- $this->debug("DONE\n\n");
- }
-
- /**
- * Output File was config object, now just string
- * Used to generate the Tables
- *
- * @var string outputbuffer for table definitions
- * @access private
- */
- var $_newConfig;
-
- /**
- * Build a list of tables;
- * and store it in $this->tables and $this->_definitions[tablename];
- *
- * @access private
- * @return none
- */
- function _createTableList()
- {
- $this->_connect();
- $options = &PEAR::getStaticProperty('DB_DataObject','options');
-
- $__DB= &$GLOBALS['_DB_DATAOBJECT']['CONNECTIONS'][$this->_database_dsn_md5];
-
- $db_driver = empty($options['db_driver']) ? 'DB' : $options['db_driver'];
- $is_MDB2 = ($db_driver != 'DB') ? true : false;
-
- if (is_a($__DB , 'PEAR_Error')) {
- return PEAR::raiseError($__DB->toString(), null, PEAR_ERROR_DIE);
- }
-
- if (!$is_MDB2) {
- // try getting a list of schema tables first. (postgres)
- $__DB->expectError(DB_ERROR_UNSUPPORTED);
- $this->tables = $__DB->getListOf('schema.tables');
- $__DB->popExpect();
- } else {
- /**
- * set portability and some modules to fetch the informations
- */
- $__DB->setOption('portability', MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_FIX_CASE);
- $__DB->loadModule('Manager');
- $__DB->loadModule('Reverse');
- }
-
- if ((empty($this->tables) || is_a($this->tables , 'PEAR_Error'))) {
- //if that fails fall back to clasic tables list.
- if (!$is_MDB2) {
- // try getting a list of schema tables first. (postgres)
- $__DB->expectError(DB_ERROR_UNSUPPORTED);
- $this->tables = $__DB->getListOf('tables');
- $__DB->popExpect();
- } else {
- $this->tables = $__DB->manager->listTables();
- $sequences = $__DB->manager->listSequences();
- foreach ($sequences as $k => $v) {
- $this->tables[] = $__DB->getSequenceName($v);
- }
- }
- }
-
- if (is_a($this->tables , 'PEAR_Error')) {
- return PEAR::raiseError($this->tables->toString(), null, PEAR_ERROR_DIE);
- }
-
- // build views as well if asked to.
- if (!empty($options['build_views'])) {
- if (!$is_MDB2) {
- $views = $__DB->getListOf('views');
- } else {
- $views = $__DB->manager->listViews();
- }
- if (is_a($views,'PEAR_Error')) {
- return PEAR::raiseError(
- 'Error getting Views (check the PEAR bug database for the fix to DB), ' .
- $views->toString(),
- null,
- PEAR_ERROR_DIE
- );
- }
- $this->tables = array_merge ($this->tables, $views);
- }
-
- // declare a temporary table to be filled with matching tables names
- $tmp_table = array();
-
-
- foreach($this->tables as $table) {
- if (isset($options['generator_include_regex']) &&
- !preg_match($options['generator_include_regex'],$table)) {
- continue;
- } else if (isset($options['generator_exclude_regex']) &&
- preg_match($options['generator_exclude_regex'],$table)) {
- continue;
- }
- // postgres strip the schema bit from the
- if (!empty($options['generator_strip_schema'])) {
- $bits = explode('.', $table,2);
- $table = $bits[0];
- if (count($bits) > 1) {
- $table = $bits[1];
- }
- }
- $quotedTable = !empty($options['quote_identifiers_tableinfo']) ?
- $__DB->quoteIdentifier($table) : $table;
-
- if (!$is_MDB2) {
-
- $defs = $__DB->tableInfo($quotedTable);
- } else {
- $defs = $__DB->reverse->tableInfo($quotedTable);
- // rename the length value, so it matches db's return.
- foreach ($defs as $k => $v) {
- if (!isset($defs[$k]['length'])) {
- continue;
- }
- $defs[$k]['len'] = $defs[$k]['length'];
- }
- }
-
- if (is_a($defs,'PEAR_Error')) {
- // running in debug mode should pick this up as a big warning..
- $this->raiseError('Error reading tableInfo, '. $defs->toString());
- continue;
- }
- // cast all definitions to objects - as we deal with that better.
-
-
-
- foreach($defs as $def) {
- if (!is_array($def)) {
- continue;
- }
-
- $this->_definitions[$table][] = (object) $def;
-
- }
- // we find a matching table, just store it into a temporary array
- $tmp_table[] = $table;
-
-
- }
- // the temporary table array is now the right one (tables names matching
- // with regex expressions have been removed)
- $this->tables = $tmp_table;
- //print_r($this->_definitions);
- }
-
- /**
- * Auto generation of table data.
- *
- * it will output to db_oo_{database} the table definitions
- *
- * @access private
- * @return none
- */
- function generateDefinitions()
- {
- $this->debug("Generating Definitions file: ");
- if (!$this->tables) {
- $this->debug("-- NO TABLES -- \n");
- return;
- }
-
- $options = &PEAR::getStaticProperty('DB_DataObject','options');
-
-
- //$this->_newConfig = new Config('IniFile');
- $this->_newConfig = '';
- foreach($this->tables as $this->table) {
- $this->_generateDefinitionsTable();
- }
- $this->_connect();
- // dont generate a schema if location is not set
- // it's created on the fly!
- if (empty($options['schema_location']) && empty($options["ini_{$this->_database}"]) ) {
- return;
- }
- if (!empty($options['generator_no_ini'])) { // built in ini files..
- return;
- }
- $base = @$options['schema_location'];
- if (isset($options["ini_{$this->_database}"])) {
- $file = $options["ini_{$this->_database}"];
- } else {
- $file = "{$base}/{$this->_database}.ini";
- }
-
- if (!file_exists(dirname($file))) {
- require_once 'System.php';
- System::mkdir(array('-p','-m',0755,dirname($file)));
- }
- $this->debug("Writing ini as {$file}\n");
- //touch($file);
- $tmpname = tempnam(session_save_path(),'DataObject_');
- //print_r($this->_newConfig);
- $fh = fopen($tmpname,'w');
- fwrite($fh,$this->_newConfig);
- fclose($fh);
- $perms = file_exists($file) ? fileperms($file) : 0755;
- // windows can fail doing this. - not a perfect solution but otherwise it's getting really kludgy..
-
- if (!@rename($tmpname, $file)) {
- unlink($file);
- rename($tmpname, $file);
- }
- chmod($file,$perms);
- //$ret = $this->_newConfig->writeInput($file,false);
-
- //if (PEAR::isError($ret) ) {
- // return PEAR::raiseError($ret->message,null,PEAR_ERROR_DIE);
- // }
- }
-
- /**
- * generate Foreign Keys (for links.ini)
- * Currenly only works with mysql / mysqli
- * to use, you must set option: generate_links=true
- *
- * @author Pascal Schöni
- */
- function generateForeignKeys()
- {
- $options = PEAR::getStaticProperty('DB_DataObject','options');
- if (empty($options['generate_links'])) {
- return false;
- }
- $__DB = &$GLOBALS['_DB_DATAOBJECT']['CONNECTIONS'][$this->_database_dsn_md5];
- if (!in_array($__DB->phptype, array('mysql','mysqli'))) {
- echo "WARNING: cant handle non-mysql introspection for defaults.";
- return; // cant handle non-mysql introspection for defaults.
- }
-
- $DB = $this->getDatabaseConnection();
-
- $fk = array();
-
- foreach($this->tables as $this->table) {
- $res =& $DB->query('SHOW CREATE TABLE ' . $this->table);
- if (PEAR::isError($res)) {
- die($res->getMessage());
- }
-
- $text = $res->fetchRow(DB_FETCHMODE_DEFAULT, 0);
- $treffer = array();
- // Extract FOREIGN KEYS
- preg_match_all(
- "/FOREIGN KEY \(`(\w*)`\) REFERENCES `(\w*)` \(`(\w*)`\)/i",
- $text[1],
- $treffer,
- PREG_SET_ORDER);
-
- if (count($treffer) < 1) {
- continue;
- }
- for ($i = 0; $i < count($treffer); $i++) {
- $fk[$this->table][$treffer[$i][1]] = $treffer[$i][2] . ":" . $treffer[$i][3];
- }
-
- }
-
- $links_ini = "";
-
- foreach($fk as $table => $details) {
- $links_ini .= "[$table]\n";
- foreach ($details as $col => $ref) {
- $links_ini .= "$col = $ref\n";
- }
- $links_ini .= "\n";
- }
-
- // dont generate a schema if location is not set
- // it's created on the fly!
- $options = PEAR::getStaticProperty('DB_DataObject','options');
-
- if (empty($options['schema_location'])) {
- return;
- }
-
-
- $file = "{$options['schema_location']}/{$this->_database}.links.ini";
-
- if (!file_exists(dirname($file))) {
- require_once 'System.php';
- System::mkdir(array('-p','-m',0755,dirname($file)));
- }
-
- $this->debug("Writing ini as {$file}\n");
-
- //touch($file); // not sure why this is needed?
- $tmpname = tempnam(session_save_path(),'DataObject_');
-
- $fh = fopen($tmpname,'w');
- fwrite($fh,$links_ini);
- fclose($fh);
- $perms = file_exists($file) ? fileperms($file) : 0755;
- // windows can fail doing this. - not a perfect solution but otherwise it's getting really kludgy..
- if (!@rename($tmpname, $file)) {
- unlink($file);
- rename($tmpname, $file);
- }
- chmod($file, $perms);
- }
-
-
- /**
- * The table geneation part
- *
- * @access private
- * @return tabledef and keys array.
- */
- function _generateDefinitionsTable()
- {
- global $_DB_DATAOBJECT;
-
- $defs = $this->_definitions[$this->table];
- $this->_newConfig .= "\n[{$this->table}]\n";
- $keys_out = "\n[{$this->table}__keys]\n";
- $keys_out_primary = '';
- $keys_out_secondary = '';
- if (@$_DB_DATAOBJECT['CONFIG']['debug'] > 2) {
- echo "TABLE STRUCTURE FOR {$this->table}\n";
- print_r($defs);
- }
- $DB = $this->getDatabaseConnection();
- $dbtype = $DB->phptype;
-
- $ret = array(
- 'table' => array(),
- 'keys' => array(),
- );
-
- $ret_keys_primary = array();
- $ret_keys_secondary = array();
-
-
-
- foreach($defs as $t) {
-
- $n=0;
- $write_ini = true;
-
-
- switch (strtoupper($t->type)) {
-
- case 'INT':
- case 'INT2': // postgres
- case 'INT4': // postgres
- case 'INT8': // postgres
- case 'SERIAL4': // postgres
- case 'SERIAL8': // postgres
- case 'INTEGER':
- case 'TINYINT':
- case 'SMALLINT':
- case 'MEDIUMINT':
- case 'BIGINT':
- $type = DB_DATAOBJECT_INT;
- if ($t->len == 1) {
- $type += DB_DATAOBJECT_BOOL;
- }
- break;
-
- case 'REAL':
- case 'DOUBLE':
- case 'DOUBLE PRECISION': // double precision (firebird)
- case 'FLOAT':
- case 'FLOAT4': // real (postgres)
- case 'FLOAT8': // double precision (postgres)
- case 'DECIMAL':
- case 'MONEY': // mssql and maybe others
- case 'NUMERIC':
- case 'NUMBER': // oci8
- $type = DB_DATAOBJECT_INT; // should really by FLOAT!!! / MONEY...
- break;
-
- case 'YEAR':
- $type = DB_DATAOBJECT_INT;
- break;
-
- case 'BIT':
- case 'BOOL':
- case 'BOOLEAN':
-
- $type = DB_DATAOBJECT_BOOL;
- // postgres needs to quote '0'
- if ($dbtype == 'pgsql') {
- $type += DB_DATAOBJECT_STR;
- }
- break;
-
- case 'STRING':
- case 'CHAR':
- case 'VARCHAR':
- case 'VARCHAR2':
- case 'TINYTEXT':
-
- case 'ENUM':
- case 'SET': // not really but oh well
- case 'TIMESTAMPTZ': // postgres
- case 'BPCHAR': // postgres
- case 'INTERVAL': // postgres (eg. '12 days')
-
- case 'CIDR': // postgres IP net spec
- case 'INET': // postgres IP
- case 'MACADDR': // postgress network Mac address.
-
- case 'INTEGER[]': // postgres type
- case 'BOOLEAN[]': // postgres type
-
- $type = DB_DATAOBJECT_STR;
- break;
-
- case 'TEXT':
- case 'MEDIUMTEXT':
- case 'LONGTEXT':
-
- $type = DB_DATAOBJECT_STR + DB_DATAOBJECT_TXT;
- break;
-
-
- case 'DATE':
- $type = DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE;
- break;
-
- case 'TIME':
- $type = DB_DATAOBJECT_STR + DB_DATAOBJECT_TIME;
- break;
-
-
- case 'DATETIME':
-
- $type = DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME;
- break;
-
- case 'TIMESTAMP': // do other databases use this???
-
- $type = ($dbtype == 'mysql') ?
- DB_DATAOBJECT_MYSQLTIMESTAMP :
- DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME;
- break;
-
-
- case 'TINYBLOB':
- case 'BLOB': /// these should really be ignored!!!???
- case 'MEDIUMBLOB':
- case 'LONGBLOB':
- case 'BYTEA': // postgres blob support..
- $type = DB_DATAOBJECT_STR + DB_DATAOBJECT_BLOB;
- break;
- default:
- echo "*****************************************************************\n".
- "** WARNING UNKNOWN TYPE **\n".
- "** Found column '{$t->name}', of type '{$t->type}' **\n".
- "** Please submit a bug, describe what type you expect this **\n".
- "** column to be **\n".
- "** ---------POSSIBLE FIX / WORKAROUND -------------------------**\n".
- "** Try using MDB2 as the backend - eg set the config option **\n".
- "** db_driver = MDB2 **\n".
- "*****************************************************************\n";
- $write_ini = false;
- break;
- }
-
- if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $t->name)) {
- echo "*****************************************************************\n".
- "** WARNING COLUMN NAME UNUSABLE **\n".
- "** Found column '{$t->name}', of type '{$t->type}' **\n".
- "** Since this column name can't be converted to a php variable **\n".
- "** name, and the whole idea of mapping would result in a mess **\n".
- "** This column has been ignored... **\n".
- "*****************************************************************\n";
- continue;
- }
-
- if (!strlen(trim($t->name))) {
- continue; // is this a bug?
- }
-
- if (preg_match('/not[ _]null/i',$t->flags)) {
- $type += DB_DATAOBJECT_NOTNULL;
- }
-
-
- if (in_array($t->name,array('null','yes','no','true','false'))) {
- echo "*****************************************************************\n".
- "** WARNING **\n".
- "** Found column '{$t->name}', which is invalid in an .ini file **\n".
- "** This line will not be writen to the file - you will have **\n".
- "** define the keys()/method manually. **\n".
- "*****************************************************************\n";
- $write_ini = false;
- } else {
- $this->_newConfig .= "{$t->name} = $type\n";
- }
-
- $ret['table'][$t->name] = $type;
- // i've no idea if this will work well on other databases?
- // only use primary key or nextval(), cause the setFrom blocks you setting all key items...
- // if no keys exist fall back to using unique
- //echo "\n{$t->name} => {$t->flags}\n";
- if (preg_match("/(auto_increment|nextval\()/i",rawurldecode($t->flags))
- || (isset($t->autoincrement) && ($t->autoincrement === true))) {
-
- // native sequences = 2
- if ($write_ini) {
- $keys_out_primary .= "{$t->name} = N\n";
- }
- $ret_keys_primary[$t->name] = 'N';
-
- } else if (preg_match("/(primary|unique)/i",$t->flags)) {
- // keys.. = 1
- $key_type = 'K';
- if (!preg_match("/(primary)/i",$t->flags)) {
- $key_type = 'U';
- }
-
- if ($write_ini) {
- $keys_out_secondary .= "{$t->name} = {$key_type}\n";
- }
- $ret_keys_secondary[$t->name] = $key_type;
- }
-
-
- }
-
- $this->_newConfig .= $keys_out . (empty($keys_out_primary) ? $keys_out_secondary : $keys_out_primary);
- $ret['keys'] = empty($keys_out_primary) ? $ret_keys_secondary : $ret_keys_primary;
-
- if (@$_DB_DATAOBJECT['CONFIG']['debug'] > 2) {
- print_r(array("dump for {$this->table}", $ret));
- }
-
- return $ret;
-
-
- }
-
- /**
- * Convert a table name into a class name -> override this if you want a different mapping
- *
- * @access public
- * @return string class name;
- */
-
-
- function getClassNameFromTableName($table)
- {
- $options = &PEAR::getStaticProperty('DB_DataObject','options');
- $class_prefix = empty($options['class_prefix']) ? '' : $options['class_prefix'];
- return $class_prefix.preg_replace('/[^A-Z0-9]/i','_',ucfirst(trim($this->table)));
- }
-
-
- /**
- * Convert a table name into a file name -> override this if you want a different mapping
- *
- * @access public
- * @return string file name;
- */
-
-
- function getFileNameFromTableName($table)
- {
- $options = &PEAR::getStaticProperty('DB_DataObject','options');
- $base = $options['class_location'];
- if (strpos($base,'%s') !== false) {
- $base = dirname($base);
- }
- if (!file_exists($base)) {
- require_once 'System.php';
- System::mkdir(array('-p',$base));
- }
- if (strpos($options['class_location'],'%s') !== false) {
- $outfilename = sprintf($options['class_location'],
- preg_replace('/[^A-Z0-9]/i','_',ucfirst($this->table)));
- } else {
- $outfilename = "{$base}/".preg_replace('/[^A-Z0-9]/i','_',ucfirst($this->table)).".php";
- }
- return $outfilename;
-
- }
-
-
- /**
- * Convert a column name into a method name (usually prefixed by get/set/validateXXXXX)
- *
- * @access public
- * @return string method name;
- */
-
-
- function getMethodNameFromColumnName($col)
- {
- return ucfirst($col);
- }
-
-
-
-
- /*
- * building the class files
- * for each of the tables output a file!
- */
- function generateClasses()
- {
- //echo "Generating Class files: \n";
- $options = &PEAR::getStaticProperty('DB_DataObject','options');
-
-
- if ($extends = @$options['extends']) {
- $this->_extends = $extends;
- $this->_extendsFile = $options['extends_location'];
- }
-
- foreach($this->tables as $this->table) {
- $this->table = trim($this->table);
- $this->classname = $this->getClassNameFromTableName($this->table);
- $i = '';
- $outfilename = $this->getFileNameFromTableName($this->table);
-
- $oldcontents = '';
- if (file_exists($outfilename)) {
- // file_get_contents???
- $oldcontents = implode('',file($outfilename));
- }
-
- $out = $this->_generateClassTable($oldcontents);
- $this->debug( "writing $this->classname\n");
- $tmpname = tempnam(session_save_path(),'DataObject_');
-
- $fh = fopen($tmpname, "w");
- fputs($fh,$out);
- fclose($fh);
- $perms = file_exists($outfilename) ? fileperms($outfilename) : 0755;
-
- // windows can fail doing this. - not a perfect solution but otherwise it's getting really kludgy..
- if (!@rename($tmpname, $outfilename)) {
- unlink($outfilename);
- rename($tmpname, $outfilename);
- }
-
- chmod($outfilename, $perms);
- }
- //echo $out;
- }
-
- /**
- * class being extended (can be overridden by [DB_DataObject_Generator] extends=xxxx
- *
- * @var string
- * @access private
- */
- var $_extends = 'DB_DataObject';
-
- /**
- * line to use for require('DB/DataObject.php');
- *
- * @var string
- * @access private
- */
- var $_extendsFile = "DB/DataObject.php";
-
- /**
- * class being generated
- *
- * @var string
- * @access private
- */
- var $_className;
-
- /**
- * The table class geneation part - single file.
- *
- * @access private
- * @return none
- */
- function _generateClassTable($input = '')
- {
- // title = expand me!
- $foot = "";
- $head = "<?php\n/**\n * Table Definition for {$this->table}\n";
- $head .= $this->derivedHookPageLevelDocBlock();
- $head .= " */\n";
- $head .= $this->derivedHookExtendsDocBlock();
-
-
- // requires
- $head .= "require_once '{$this->_extendsFile}';\n\n";
- // add dummy class header in...
- // class
- $head .= $this->derivedHookClassDocBlock();
- $head .= "class {$this->classname} extends {$this->_extends} \n{";
-
- $body = "\n ###START_AUTOCODE\n";
- $body .= " /* the code below is auto generated do not remove the above tag */\n\n";
- // table
- $padding = (30 - strlen($this->table));
- $padding = ($padding < 2) ? 2 : $padding;
-
- $p = str_repeat(' ',$padding) ;
-
- $options = &PEAR::getStaticProperty('DB_DataObject','options');
-
-
- $var = (substr(phpversion(),0,1) > 4) ? 'public' : 'var';
- $var = !empty($options['generator_var_keyword']) ? $options['generator_var_keyword'] : $var;
-
-
- $body .= " {$var} \$__table = '{$this->table}'; {$p}// table name\n";
-
-
- // if we are using the option database_{databasename} = dsn
- // then we should add var $_database = here
- // as database names may not always match..
-
-
-
-
- if (isset($options["database_{$this->_database}"])) {
- $body .= " {$var} \$_database = '{$this->_database}'; {$p}// database name (used with database_{*} config)\n";
- }
-
-
- if (!empty($options['generator_novars'])) {
- $var = '//'.$var;
- }
-
- $defs = $this->_definitions[$this->table];
-
- // show nice information!
- $connections = array();
- $sets = array();
- foreach($defs as $t) {
- if (!strlen(trim($t->name))) {
- continue;
- }
- if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $t->name)) {
- echo "*****************************************************************\n".
- "** WARNING COLUMN NAME UNUSABLE **\n".
- "** Found column '{$t->name}', of type '{$t->type}' **\n".
- "** Since this column name can't be converted to a php variable **\n".
- "** name, and the whole idea of mapping would result in a mess **\n".
- "** This column has been ignored... **\n".
- "*****************************************************************\n";
- continue;
- }
-
-
- $padding = (30 - strlen($t->name));
- if ($padding < 2) $padding =2;
- $p = str_repeat(' ',$padding) ;
-
- $body .=" {$var} \${$t->name}; {$p}// {$t->type}({$t->len}) {$t->flags}\n";
-
- // can not do set as PEAR::DB table info doesnt support it.
- //if (substr($t->Type,0,3) == "set")
- // $sets[$t->Field] = "array".substr($t->Type,3);
- $body .= $this->derivedHookVar($t,$padding);
- }
-
- // THIS IS TOTALLY BORKED old FC creation
- // IT WILL BE REMOVED!!!!! in DataObjects 1.6
- // grep -r __clone * to find all it's uses
- // and replace them with $x = clone($y);
- // due to the change in the PHP5 clone design.
-
- if ( substr(phpversion(),0,1) < 5) {
- $body .= "\n";
- $body .= " /* ZE2 compatibility trick*/\n";
- $body .= " function __clone() { return \$this;}\n";
- }
-
- // simple creation tools ! (static stuff!)
- $body .= "\n";
- $body .= " /* Static get */\n";
- $body .= " function staticGet(\$k,\$v=NULL) { return DB_DataObject::staticGet('{$this->classname}',\$k,\$v); }\n";
-
- // generate getter and setter methods
- $body .= $this->_generateGetters($input);
- $body .= $this->_generateSetters($input);
-
- /*
- theoretically there is scope here to introduce 'list' methods
- based up 'xxxx_up' column!!! for heiracitcal trees..
- */
-
- // set methods
- //foreach ($sets as $k=>$v) {
- // $kk = strtoupper($k);
- // $body .=" function getSets{$k}() { return {$v}; }\n";
- //}
-
- if (!empty($options['generator_no_ini'])) {
- $def = $this->_generateDefinitionsTable(); // simplify this!?
- $body .= $this->_generateTableFunction($def['table']);
- $body .= $this->_generateKeysFunction($def['keys']);
- $body .= $this->_generateSequenceKeyFunction($def);
- $body .= $this->_generateDefaultsFunction($this->table, $def['table']);
- } else if (!empty($options['generator_add_defaults'])) {
- // I dont really like doing it this way (adding another option)
- // but it helps on older projects.
- $def = $this->_generateDefinitionsTable(); // simplify this!?
- $body .= $this->_generateDefaultsFunction($this->table,$def['table']);
-
- }
- $body .= $this->derivedHookFunctions($input);
-
- $body .= "\n /* the code above is auto generated do not remove the tag below */";
- $body .= "\n ###END_AUTOCODE\n";
-
-
- // stubs..
-
- if (!empty($options['generator_add_validate_stubs'])) {
- foreach($defs as $t) {
- if (!strlen(trim($t->name))) {
- continue;
- }
- $validate_fname = 'validate' . $this->getMethodNameFromColumnName($t->name);
- // dont re-add it..
- if (preg_match('/\s+function\s+' . $validate_fname . '\s*\(/i', $input)) {
- continue;
- }
- $body .= "\n function {$validate_fname}()\n {\n return false;\n }\n";
- }
- }
-
-
-
-
- $foot .= "}\n";
- $full = $head . $body . $foot;
-
- if (!$input) {
- return $full;
- }
- if (!preg_match('/(\n|\r\n)\s*###START_AUTOCODE(\n|\r\n)/s',$input)) {
- return $full;
- }
- if (!preg_match('/(\n|\r\n)\s*###END_AUTOCODE(\n|\r\n)/s',$input)) {
- return $full;
- }
-
-
- /* this will only replace extends DB_DataObject by default,
- unless use set generator_class_rewrite to ANY or a name*/
-
- $class_rewrite = 'DB_DataObject';
- $options = &PEAR::getStaticProperty('DB_DataObject','options');
- if (empty($options['generator_class_rewrite']) || !($class_rewrite = $options['generator_class_rewrite'])) {
- $class_rewrite = 'DB_DataObject';
- }
- if ($class_rewrite == 'ANY') {
- $class_rewrite = '[a-z_]+';
- }
-
- $input = preg_replace(
- '/(\n|\r\n)class\s*[a-z0-9_]+\s*extends\s*' .$class_rewrite . '\s*(\n|\r\n)\{(\n|\r\n)/si',
- "\nclass {$this->classname} extends {$this->_extends} \n{\n",
- $input);
-
- $ret = preg_replace(
- '/(\n|\r\n)\s*###START_AUTOCODE(\n|\r\n).*(\n|\r\n)\s*###END_AUTOCODE(\n|\r\n)/s',
- $body,$input);
-
- if (!strlen($ret)) {
- return PEAR::raiseError(
- "PREG_REPLACE failed to replace body, - you probably need to set these in your php.ini\n".
- "pcre.backtrack_limit=1000000\n".
- "pcre.recursion_limit=1000000\n"
- ,null, PEAR_ERROR_DIE);
- }
-
- return $ret;
- }
-
- /**
- * hook to add extra methods to all classes
- *
- * called once for each class, use with $this->table and
- * $this->_definitions[$this->table], to get data out of the current table,
- * use it to add extra methods to the default classes.
- *
- * @access public
- * @return string added to class eg. functions.
- */
- function derivedHookFunctions($input = "")
- {
- // This is so derived generator classes can generate functions
- // It MUST NOT be changed here!!!
- return "";
- }
-
- /**
- * hook for var lines
- * called each time a var line is generated, override to add extra var
- * lines
- *
- * @param object t containing type,len,flags etc. from tableInfo call
- * @param int padding number of spaces
- * @access public
- * @return string added to class eg. functions.
- */
- function derivedHookVar(&$t,$padding)
- {
- // This is so derived generator classes can generate variabels
- // It MUST NOT be changed here!!!
- return "";
- }
-
- /**
- * hook to add extra page-level (in terms of phpDocumentor) DocBlock
- *
- * called once for each class, use it add extra page-level docs
- * @access public
- * @return string added to class eg. functions.
- */
- function derivedHookPageLevelDocBlock() {
- return '';
- }
-
- /**
- * hook to add extra doc block (in terms of phpDocumentor) to extend string
- *
- * called once for each class, use it add extra comments to extends
- * string (require_once...)
- * @access public
- * @return string added to class eg. functions.
- */
- function derivedHookExtendsDocBlock() {
- return '';
- }
-
- /**
- * hook to add extra class level DocBlock (in terms of phpDocumentor)
- *
- * called once for each class, use it add extra comments to class
- * string (require_once...)
- * @access public
- * @return string added to class eg. functions.
- */
- function derivedHookClassDocBlock() {
- return '';
- }
-
- /**
-
- /**
- * getProxyFull - create a class definition on the fly and instantate it..
- *
- * similar to generated files - but also evals the class definitoin code.
- *
- *
- * @param string database name
- * @param string table name of table to create proxy for.
- *
- *
- * @return object Instance of class. or PEAR Error
- * @access public
- */
- function getProxyFull($database,$table)
- {
-
- if ($err = $this->fillTableSchema($database,$table)) {
- return $err;
- }
-
-
- $options = &PEAR::getStaticProperty('DB_DataObject','options');
- $class_prefix = empty($options['class_prefix']) ? '' : $options['class_prefix'];
-
- if ($extends = @$options['extends']) {
- $this->_extends = $extends;
- $this->_extendsFile = $options['extends_location'];
- }
- $classname = $this->classname = $this->getClassNameFromTableName($this->table);
-
- $out = $this->_generateClassTable();
- //echo $out;
- eval('?>'.$out);
- return new $classname;
-
- }
-
- /**
- * fillTableSchema - set the database schema on the fly
- *
- *
- *
- * @param string database name
- * @param string table name of table to create schema info for
- *
- * @return none | PEAR::error()
- * @access public
- */
- function fillTableSchema($database,$table)
- {
- global $_DB_DATAOBJECT;
- // a little bit of sanity testing.
- if ((false !== strpos($database,"'")) || (false !== strpos($database,";"))) {
- return PEAR::raiseError("Error: Database name contains a quote or semi-colon", null, PEAR_ERROR_DIE);
- }
-
- $this->_database = $database;
-
- $this->_connect();
- $table = trim($table);
-
- // a little bit of sanity testing.
- if ((false !== strpos($table,"'")) || (false !== strpos($table,";"))) {
- return PEAR::raiseError("Error: Table contains a quote or semi-colon", null, PEAR_ERROR_DIE);
- }
- $__DB= &$GLOBALS['_DB_DATAOBJECT']['CONNECTIONS'][$this->_database_dsn_md5];
-
-
- $options = PEAR::getStaticProperty('DB_DataObject','options');
- $db_driver = empty($options['db_driver']) ? 'DB' : $options['db_driver'];
- $is_MDB2 = ($db_driver != 'DB') ? true : false;
-
- if (!$is_MDB2) {
- // try getting a list of schema tables first. (postgres)
- $__DB->expectError(DB_ERROR_UNSUPPORTED);
- $this->tables = $__DB->getListOf('schema.tables');
- $__DB->popExpect();
- } else {
- /**
- * set portability and some modules to fetch the informations
- */
- $__DB->setOption('portability', MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_FIX_CASE);
- $__DB->loadModule('Manager');
- $__DB->loadModule('Reverse');
- }
- $quotedTable = !empty($options['quote_identifiers']) ?
- $__DB->quoteIdentifier($table) : $table;
-
- if (!$is_MDB2) {
- $defs = $__DB->tableInfo($quotedTable);
- } else {
- $defs = $__DB->reverse->tableInfo($quotedTable);
- foreach ($defs as $k => $v) {
- if (!isset($defs[$k]['length'])) {
- continue;
- }
- $defs[$k]['len'] = $defs[$k]['length'];
- }
- }
-
-
-
-
- if (PEAR::isError($defs)) {
- return $defs;
- }
- if (@$_DB_DATAOBJECT['CONFIG']['debug'] > 2) {
- $this->debug("getting def for $database/$table",'fillTable');
- $this->debug(print_r($defs,true),'defs');
- }
- // cast all definitions to objects - as we deal with that better.
-
-
- foreach($defs as $def) {
- if (is_array($def)) {
- $this->_definitions[$table][] = (object) $def;
- }
- }
-
- $this->table = trim($table);
- $ret = $this->_generateDefinitionsTable();
-
- $_DB_DATAOBJECT['INI'][$database][$table] = $ret['table'];
- $_DB_DATAOBJECT['INI'][$database][$table.'__keys'] = $ret['keys'];
- return false;
-
- }
-
- /**
- * Generate getter methods for class definition
- *
- * @param string $input Existing class contents
- * @return string
- * @access public
- */
- function _generateGetters($input)
- {
-
- $options = &PEAR::getStaticProperty('DB_DataObject','options');
- $getters = '';
-
- // only generate if option is set to true
- if (empty($options['generate_getters'])) {
- return '';
- }
-
- // remove auto-generated code from input to be able to check if the method exists outside of the auto-code
- $input = preg_replace('/(\n|\r\n)\s*###START_AUTOCODE(\n|\r\n).*(\n|\r\n)\s*###END_AUTOCODE(\n|\r\n)/s', '', $input);
-
- $getters .= "\n\n";
- $defs = $this->_definitions[$this->table];
-
- // loop through properties and create getter methods
- foreach ($defs = $defs as $t) {
-
- // build mehtod name
- $methodName = 'get' . $this->getMethodNameFromColumnName($t->name);
-
- if (!strlen(trim($t->name)) || preg_match("/function[\s]+[&]?$methodName\(/i", $input)) {
- continue;
- }
-
- $getters .= " /**\n";
- $getters .= " * Getter for \${$t->name}\n";
- $getters .= " *\n";
- $getters .= (stristr($t->flags, 'multiple_key')) ? " * @return object\n"
- : " * @return {$t->type}\n";
- $getters .= " * @access public\n";
- $getters .= " */\n";
- $getters .= (substr(phpversion(),0,1) > 4) ? ' public '
- : ' ';
- $getters .= "function $methodName() {\n";
- $getters .= " return \$this->{$t->name};\n";
- $getters .= " }\n\n";
- }
-
-
- return $getters;
- }
-
-
- /**
- * Generate setter methods for class definition
- *
- * @param string Existing class contents
- * @return string
- * @access public
- */
- function _generateSetters($input)
- {
-
- $options = &PEAR::getStaticProperty('DB_DataObject','options');
- $setters = '';
-
- // only generate if option is set to true
- if (empty($options['generate_setters'])) {
- return '';
- }
-
- // remove auto-generated code from input to be able to check if the method exists outside of the auto-code
- $input = preg_replace('/(\n|\r\n)\s*###START_AUTOCODE(\n|\r\n).*(\n|\r\n)\s*###END_AUTOCODE(\n|\r\n)/s', '', $input);
-
- $setters .= "\n";
- $defs = $this->_definitions[$this->table];
-
- // loop through properties and create setter methods
- foreach ($defs = $defs as $t) {
-
- // build mehtod name
- $methodName = 'set' . $this->getMethodNameFromColumnName($t->name);
-
- if (!strlen(trim($t->name)) || preg_match("/function[\s]+[&]?$methodName\(/i", $input)) {
- continue;
- }
-
- $setters .= " /**\n";
- $setters .= " * Setter for \${$t->name}\n";
- $setters .= " *\n";
- $setters .= " * @param mixed input value\n";
- $setters .= " * @access public\n";
- $setters .= " */\n";
- $setters .= (substr(phpversion(),0,1) > 4) ? ' public '
- : ' ';
- $setters .= "function $methodName(\$value) {\n";
- $setters .= " \$this->{$t->name} = \$value;\n";
- $setters .= " }\n\n";
- }
-
-
- return $setters;
- }
- /**
- * Generate table Function - used when generator_no_ini is set.
- *
- * @param array table array.
- * @return string
- * @access public
- */
- function _generateTableFunction($def)
- {
- $defines = explode(',','INT,STR,DATE,TIME,BOOL,TXT,BLOB,NOTNULL,MYSQLTIMESTAMP');
-
- $ret = "\n" .
- " function table()\n" .
- " {\n" .
- " return array(\n";
-
- foreach($def as $k=>$v) {
- $str = '0';
- foreach($defines as $dn) {
- if ($v & constant('DB_DATAOBJECT_' . $dn)) {
- $str .= ' + DB_DATAOBJECT_' . $dn;
- }
- }
- if (strlen($str) > 1) {
- $str = substr($str,3); // strip the 0 +
- }
- // hopefully addslashes is good enough here!!!
- $ret .= ' \''.addslashes($k).'\' => ' . $str . ",\n";
- }
- return $ret . " );\n" .
- " }\n";
-
-
-
- }
- /**
- * Generate keys Function - used generator_no_ini is set.
- *
- * @param array keys array.
- * @return string
- * @access public
- */
- function _generateKeysFunction($def)
- {
-
- $ret = "\n" .
- " function keys()\n" .
- " {\n" .
- " return array(";
-
- foreach($def as $k=>$type) {
- // hopefully addslashes is good enough here!!!
- $ret .= '\''.addslashes($k).'\', ';
- }
- $ret = preg_replace('#, $#', '', $ret);
- return $ret . ");\n" .
- " }\n";
-
-
-
- }
- /**
- * Generate sequenceKey Function - used generator_no_ini is set.
- *
- * @param array table and key definition.
- * @return string
- * @access public
- */
- function _generateSequenceKeyFunction($def)
- {
-
- //print_r($def);
- // DB_DataObject::debugLevel(5);
- global $_DB_DATAOBJECT;
- // print_r($def);
-
-
- $dbtype = $_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]->dsn['phptype'];
- $realkeys = $def['keys'];
- $keys = array_keys($realkeys);
- $usekey = isset($keys[0]) ? $keys[0] : false;
- $table = $def['table'];
-
-
- $seqname = false;
-
-
-
-
- $ar = array(false,false,false);
- if ($usekey !== false) {
- if (!empty($_DB_DATAOBJECT['CONFIG']['sequence_'.$this->__table])) {
- $usekey = $_DB_DATAOBJECT['CONFIG']['sequence_'.$this->__table];
- if (strpos($usekey,':') !== false) {
- list($usekey,$seqname) = explode(':',$usekey);
- }
- }
-
- if (in_array($dbtype , array( 'mysql', 'mysqli', 'mssql', 'ifx')) &&
- ($table[$usekey] & DB_DATAOBJECT_INT) &&
- isset($realkeys[$usekey]) && ($realkeys[$usekey] == 'N')
- ) {
- // use native sequence keys.
- $ar = array($usekey,true,$seqname);
- } else {
- // use generated sequence keys..
- if ($table[$usekey] & DB_DATAOBJECT_INT) {
- $ar = array($usekey,false,$seqname);
- }
- }
- }
-
-
-
-
- $ret = "\n" .
- " function sequenceKey() // keyname, use native, native name\n" .
- " {\n" .
- " return array(";
- foreach($ar as $v) {
- switch (gettype($v)) {
- case 'boolean':
- $ret .= ($v ? 'true' : 'false') . ', ';
- break;
-
- case 'string':
- $ret .= "'" . $v . "', ";
- break;
-
- default: // eak
- $ret .= "null, ";
-
- }
- }
- $ret = preg_replace('#, $#', '', $ret);
- return $ret . ");\n" .
- " }\n";
-
- }
- /**
- * Generate defaults Function - used generator_add_defaults or generator_no_ini is set.
- * Only supports mysql and mysqli ... welcome ideas for more..
- *
- *
- * @param array table and key definition.
- * @return string
- * @access public
- */
- function _generateDefaultsFunction($table,$defs)
- {
- $__DB= &$GLOBALS['_DB_DATAOBJECT']['CONNECTIONS'][$this->_database_dsn_md5];
- if (!in_array($__DB->phptype, array('mysql','mysqli'))) {
- return; // cant handle non-mysql introspection for defaults.
- }
- $options = PEAR::getStaticProperty('DB_DataObject','options');
- $db_driver = empty($options['db_driver']) ? 'DB' : $options['db_driver'];
- $method = $db_driver == 'DB' ? 'getAll' : 'queryAll';
- $res = $__DB->$method('DESCRIBE ' . $table,DB_FETCHMODE_ASSOC);
- $defaults = array();
- foreach($res as $ar) {
- // this is initially very dumb... -> and it may mess up..
- $type = $defs[$ar['Field']];
-
- switch (true) {
-
- case (is_null( $ar['Default'])):
- $defaults[$ar['Field']] = 'null';
- break;
-
- case ($type & DB_DATAOBJECT_DATE):
- case ($type & DB_DATAOBJECT_TIME):
- case ($type & DB_DATAOBJECT_MYSQLTIMESTAMP): // not supported yet..
- break;
-
- case ($type & DB_DATAOBJECT_BOOL):
- $defaults[$ar['Field']] = (int)(boolean) $ar['Default'];
- break;
-
-
- case ($type & DB_DATAOBJECT_STR):
- $defaults[$ar['Field']] = "'" . addslashes($ar['Default']) . "'";
- break;
-
-
- default: // hopefully eveything else... - numbers etc.
- if (!strlen($ar['Default'])) {
- continue;
- }
- if (is_numeric($ar['Default'])) {
- $defaults[$ar['Field']] = $ar['Default'];
- }
- break;
-
- }
- //var_dump(array($ar['Field'], $ar['Default'], $defaults[$ar['Field']]));
- }
- if (empty($defaults)) {
- return;
- }
-
- $ret = "\n" .
- " function defaults() // column default values \n" .
- " {\n" .
- " return array(\n";
- foreach($defaults as $k=>$v) {
- $ret .= ' \''.addslashes($k).'\' => ' . $v . ",\n";
- }
- return $ret . " );\n" .
- " }\n";
-
-
-
-
- }
-
-
-
-
-
-}