12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775 |
- <?php
- class_exists('DB_DataObject') ? '' : require_once '../DataObject.php';
- class DB_DataObject_Generator extends DB_DataObject
- {
-
-
-
-
- public $tables;
-
- public $_definitions;
-
- public $table;
-
- public $_fkeys;
-
- public $_newConfig;
-
- public $_extends = 'DB_DataObject';
-
- public $_extendsFile = "DB/DataObject.php";
-
- public $_className;
-
- public function start()
- {
- $options = &(new 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();
- $t->_createForiegnKeys();
- 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");
- return null;
- }
-
- public function _createTableList()
- {
- $this->_connect();
- $options = &(new 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_object($__DB) && is_a($__DB, 'PEAR_Error')) {
- return (new PEAR)->raiseError($__DB->toString(), null, PEAR_ERROR_DIE);
- }
- if (!$is_MDB2) {
-
- $__DB->expectError(DB_ERROR_UNSUPPORTED);
- $this->tables = $__DB->getListOf('schema.tables');
- $__DB->popExpect();
- } else {
-
- $db_options = (new PEAR)->getStaticProperty('MDB2', 'options');
- if (empty($db_options)) {
- $__DB->setOption('portability', MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_FIX_CASE);
- }
- $__DB->loadModule('Manager');
- $__DB->loadModule('Reverse');
- }
- if ((empty($this->tables) || (is_object($this->tables) && is_a($this->tables, 'PEAR_Error')))) {
-
- if (!$is_MDB2) {
-
- $__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_object($this->tables) && is_a($this->tables, 'PEAR_Error')) {
- return (new PEAR)->raiseError($this->tables->toString(), null, PEAR_ERROR_DIE);
- }
-
- if (!empty($options['build_views'])) {
- if (!$is_MDB2) {
- $views = $__DB->getListOf(is_string($options['build_views']) ?
- $options['build_views'] : 'views');
- } else {
- $views = $__DB->manager->listViews();
- }
- if (is_object($views) && is_a($views, 'PEAR_Error')) {
- return (new 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);
- }
-
- $tmp_table = array();
- foreach ($this->tables as $table) {
- if (isset($options['generator_include_regex']) &&
- !preg_match($options['generator_include_regex'], $table)) {
- $this->debug("SKIPPING (generator_include_regex) : $table");
- continue;
- }
- if (isset($options['generator_exclude_regex']) &&
- preg_match($options['generator_exclude_regex'], $table)) {
- continue;
- }
- $strip = empty($options['generator_strip_schema']) ? false : $options['generator_strip_schema'];
- $strip = is_numeric($strip) ? (bool)$strip : $strip;
- $strip = (is_string($strip) && strtolower($strip) == 'true') ? true : $strip;
-
- if (!empty($strip)) {
- if (!is_string($strip) || preg_match($strip, $table)) {
- $bits = explode('.', $table, 2);
- $table = $bits[0];
- if (count($bits) > 1) {
- $table = $bits[1];
- }
- }
- }
- $this->debug("EXTRACTING : $table");
- $quotedTable = !empty($options['quote_identifiers_tableinfo']) ?
- $__DB->quoteIdentifier($table) : $table;
- if (!$is_MDB2) {
- $defs = $__DB->tableInfo($quotedTable);
- } else {
- $defs = $__DB->reverse->tableInfo($quotedTable);
-
- }
- if (is_object($defs) && is_a($defs, 'PEAR_Error')) {
-
- $this->debug("Error reading tableInfo: $table");
- $this->raiseError('Error reading tableInfo, ' . $defs->toString());
- continue;
- }
-
- foreach ($defs as $def) {
- if (!is_array($def)) {
- continue;
- }
-
- if (isset($def['length']) && !isset($def['len'])) {
- $def['len'] = $def['length'];
- }
- $this->_definitions[$table][] = (object)$def;
- }
-
- $tmp_table[] = $table;
- }
-
-
- $this->tables = $tmp_table;
-
- return null;
- }
-
- public function generateDefinitions()
- {
- $this->debug("Generating Definitions file: ");
- if (!$this->tables) {
- $this->debug("-- NO TABLES -- \n");
- return null;
- }
- $options = &(new PEAR)->getStaticProperty('DB_DataObject', 'options');
-
- $this->_newConfig = '';
- foreach ($this->tables as $this->table) {
- $this->_generateDefinitionsTable();
- }
- $this->_connect();
-
-
- if (empty($options['schema_location']) && empty($options["ini_{$this->_database}"])) {
- return null;
- }
- if (!empty($options['generator_no_ini'])) {
- return null;
- }
- $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';
- (new System)->mkdir(array('-p', '-m', 0755, dirname($file)));
- }
- $this->debug("Writing ini as {$file}\n");
-
- $tmpname = tempnam(session_save_path(), 'DataObject_');
-
- $fh = fopen($tmpname, 'w');
- if (!$fh) {
- return (new PEAR)->raiseError(
- "Failed to create temporary file: $tmpname\n" .
- "make sure session.save_path is set and is writable\n",
- null,
- PEAR_ERROR_DIE
- );
- }
- fwrite($fh, $this->_newConfig);
- fclose($fh);
- $perms = file_exists($file) ? fileperms($file) : 0755;
-
- if (!@rename($tmpname, $file)) {
- unlink($file);
- rename($tmpname, $file);
- }
- chmod($file, $perms);
-
-
-
-
- return null;
- }
-
- public function _generateDefinitionsTable()
- {
- global $_DB_DATAOBJECT;
- $options = (new PEAR)->getStaticProperty('DB_DataObject', 'options');
- $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':
- case 'INT4':
- case 'INT8':
- case 'SERIAL4':
- case 'SERIAL8':
- 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':
- case 'FLOAT':
- case 'FLOAT4':
- case 'FLOAT8':
- case 'DECIMAL':
- case 'MONEY':
- case 'NUMERIC':
- case 'NUMBER':
- $type = DB_DATAOBJECT_INT;
- break;
- case 'YEAR':
- $type = DB_DATAOBJECT_INT;
- break;
- case 'BIT':
- case 'BOOL':
- case 'BOOLEAN':
- $type = DB_DATAOBJECT_BOOL;
-
- if ($dbtype == 'pgsql') {
- $type += DB_DATAOBJECT_STR;
- }
- break;
- case 'STRING':
- case 'CHAR':
- case 'VARCHAR':
- case 'VARCHAR2':
- case 'TINYTEXT':
- case 'ENUM':
- case 'SET':
- case 'POINT':
- case 'TIMESTAMPTZ':
- case 'BPCHAR':
- case 'INTERVAL':
- case 'CIDR':
- case 'INET':
- case 'MACADDR':
- case 'INTEGER[]':
- case 'BOOLEAN[]':
- $type = DB_DATAOBJECT_STR;
- break;
- case 'TEXT':
- case 'MEDIUMTEXT':
- case 'LONGTEXT':
- case '_TEXT':
- $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':
- $type = ($dbtype == 'mysql') ?
- DB_DATAOBJECT_MYSQLTIMESTAMP :
- DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME;
- break;
- case 'BLOB':
- case 'TINYBLOB':
- case 'MEDIUMBLOB':
- case 'LONGBLOB':
- case 'CLOB':
- case 'BYTEA':
- $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;
- }
- 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;
-
-
-
-
- $secondary_key_match = isset($options['generator_secondary_key_match']) ? $options['generator_secondary_key_match'] : 'primary|unique';
- $m = array();
- if (preg_match('/(auto_increment|nextval\(([^)]*))/i', rawurldecode($t->flags), $m)
- || (isset($t->autoincrement) && ($t->autoincrement === true))) {
- $sn = 'N';
- if ($DB->phptype == 'pgsql' && !empty($m[2])) {
- $sn = preg_replace('/[("]+/', '', $m[2]);
-
- }
-
- if ($write_ini) {
- $keys_out_primary .= "{$t->name} = $sn\n";
- }
- $ret_keys_primary[$t->name] = $sn;
- } elseif ($secondary_key_match && preg_match('/(' . $secondary_key_match . ')/i', $t->flags)) {
-
- $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;
- }
-
- public function _createForiegnKeys()
- {
- $options = (new 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', 'pgsql'))) {
- echo "WARNING: cant handle non-mysql and pgsql introspection for defaults.";
- return null;
- }
- $this->debug("generateForeignKeys: Start");
- $DB = $this->getDatabaseConnection();
- $fk = array();
- switch ($DB->phptype) {
- case 'pgsql':
- foreach ($this->tables as $this->table) {
- $quotedTable = !empty($options['quote_identifiers_tableinfo']) ? $DB->quoteIdentifier($this->table) : $this->table;
- $res =& $DB->query("SELECT
- pg_catalog.pg_get_constraintdef(r.oid, true) AS condef
- FROM pg_catalog.pg_constraint r,
- pg_catalog.pg_class c
- WHERE c.oid=r.conrelid
- AND r.contype = 'f'
- AND c.relname = '" . $quotedTable . "'");
- if ((new PEAR)->isError($res)) {
- die($res->getMessage());
- }
- if ($db_driver == 'DB') {
- $fetchmode = DB_FETCHMODE_ASSOC;
- } else {
- $fetchmode = MDB2_FETCHMODE_ASSOC;
- }
- while ($row = $res->fetchRow($fetchmode)) {
- $treffer = array();
-
- preg_match(
- "/FOREIGN KEY \((\w*)\) REFERENCES (\w*)\((\w*)\)/i",
- $row['condef'],
- $treffer
- );
- if (!count($treffer)) {
- continue;
- }
- $fk[$this->table][$treffer[1]] = $treffer[2] . ":" . $treffer[3];
- }
- }
- break;
- case 'mysql':
- case 'mysqli':
- default:
- foreach ($this->tables as $this->table) {
- $quotedTable = !empty($options['quote_identifiers_tableinfo']) ? $DB->quoteIdentifier($this->table) : $this->table;
- $res =& $DB->query('SHOW CREATE TABLE ' . $quotedTable);
- if ((new PEAR)->isError($res)) {
- die($res->getMessage());
- }
- if ($db_driver == 'DB') {
- $text = $res->fetchRow(DB_FETCHMODE_DEFAULT, 0);
- } else {
- $text = $res->fetchRow(MDB2_FETCHMODE_DEFAULT, 0);
- }
- $treffer = array();
-
- preg_match_all(
- "/FOREIGN KEY \(`(\w*)`\) REFERENCES `(\w*)` \(`(\w*)`\)/i",
- $text[1],
- $treffer,
- PREG_SET_ORDER
- );
- if (!count($treffer)) {
- continue;
- }
- foreach ($treffer as $i => $tref) {
- $fk[$this->table][$tref[1]] = $tref[2] . ":" . $tref[3];
- }
- }
- }
- $this->_fkeys = $fk;
- return null;
- }
-
- public function generateForeignKeys()
- {
- $options = (new 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', 'pgsql'))) {
- echo "WARNING: cant handle non-mysql and pgsql introspection for defaults.";
- return null;
- }
- $this->debug("generateForeignKeys: Start");
- $fk = $this->_fkeys;
- $links_ini = "";
- foreach ($fk as $table => $details) {
- $links_ini .= "[$table]\n";
- foreach ($details as $col => $ref) {
- $links_ini .= "$col = $ref\n";
- }
- $links_ini .= "\n";
- }
-
-
- $options = (new PEAR)->getStaticProperty('DB_DataObject', 'options');
- if (!empty($options['schema_location'])) {
- $file = "{$options['schema_location']}/{$this->_database}.links.ini";
- } elseif (isset($options["ini_{$this->_database}"])) {
- $file = preg_replace('/\.ini/', '.links.ini', $options["ini_{$this->_database}"]);
- } else {
- $this->debug("generateForeignKeys: SKIP - schema_location or ini_{database} was not set");
- return null;
- }
- if (!file_exists(dirname($file))) {
- mkdir(dirname($file), 0755, true);
- }
- $this->debug("Writing ini as {$file}\n");
-
- $tmpname = tempnam(session_save_path(), 'DataObject_');
- $fh = fopen($tmpname, 'w');
- if (!$fh) {
- return (new PEAR)->raiseError(
- "Failed to create temporary file: $tmpname\n" .
- "make sure session.save_path is set and is writable\n",
- null,
- PEAR_ERROR_DIE
- );
- }
- fwrite($fh, $links_ini);
- fclose($fh);
- $perms = file_exists($file) ? fileperms($file) : 0755;
-
- if (!@rename($tmpname, $file)) {
- unlink($file);
- rename($tmpname, $file);
- }
- chmod($file, $perms);
- return null;
- }
-
- public function generateClasses()
- {
-
- $options = &(new PEAR)->getStaticProperty('DB_DataObject', 'options');
- $this->_extends = empty($options['extends']) ? $this->_extends : $options['extends'];
- $this->_extendsFile = !isset($options['extends_location']) ? $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)) {
-
- $oldcontents = implode('', file($outfilename));
- }
- $out = $this->_generateClassTable($oldcontents);
- $this->debug("writing $this->classname\n");
- $tmpname = tempnam(session_save_path(), 'DataObject_');
- $fh = fopen($tmpname, "w");
- if (!$fh) {
- return (new PEAR)->raiseError(
- "Failed to create temporary file: $tmpname\n" .
- "make sure session.save_path is set and is writable\n",
- null,
- PEAR_ERROR_DIE
- );
- }
- fputs($fh, $out);
- fclose($fh);
- $perms = file_exists($outfilename) ? fileperms($outfilename) : 0755;
-
- if (!@rename($tmpname, $outfilename)) {
- unlink($outfilename);
- rename($tmpname, $outfilename);
- }
- chmod($outfilename, $perms);
- }
-
- return null;
- }
-
- public function getClassNameFromTableName($table)
- {
- $options = &(new 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)));
- }
-
- public function getFileNameFromTableName($table)
- {
- $options = &(new 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';
- (new 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;
- }
-
- public function _generateClassTable($input = '')
- {
-
- $foot = "";
- $head = "<?php\n/**\n * Table Definition for {$this->table}\n";
- $head .= $this->derivedHookPageLevelDocBlock();
- $head .= " */\n";
- $head .= $this->derivedHookExtendsDocBlock();
-
-
- if (!empty($this->_extendsFile)) {
- $head .= "require_once '{$this->_extendsFile}';\n\n";
- }
-
-
- $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";
-
- $p = str_repeat(' ', max(2, (18 - strlen($this->table))));
- $options = &(new 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 (empty($GLOBALS['_DB_DATAOBJECT']['CONFIG'])) {
- DB_DataObject::_loadConfig();
- }
-
- if (isset($options["database_{$this->_database}"]) && empty($GLOBALS['_DB_DATAOBJECT']['CONFIG']['generator_omit_database_var'])) {
- $p = str_repeat(' ', max(2, (16 - strlen($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];
-
- $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;
- }
- $pad = str_repeat(' ', max(2, (30 - strlen($t->name))));
- $length = empty($t->len) ? '' : '(' . $t->len . ')';
- $flags = strlen($t->flags) ? (' ' . trim($t->flags)) : '';
- $body .= " {$var} \${$t->name}; {$pad}// {$t->type}{$length}{$flags}\n";
-
-
-
- $body .= $this->derivedHookVar($t, strlen($p));
- }
- $body .= $this->derivedHookPostVar($defs);
-
-
-
-
-
- $static = 'static';
- if (substr(phpversion(), 0, 1) < 5) {
- $body .= "\n";
- $body .= " /* ZE2 compatibility trick*/\n";
- $body .= " function __clone() { return \$this;}\n";
- }
-
- if (!empty($options['static_get'])) {
-
- $body .= "\n";
- $body .= " /* Static get */\n";
- $body .= " $static function staticGet(\$k,\$v=NULL) { " .
- "return DB_DataObject::staticGet('{$this->classname}',\$k,\$v = null); }\n";
- }
-
- $body .= $this->_generateGetters($input);
- $body .= $this->_generateSetters($input);
- $body .= $this->_generateLinkMethods($input);
-
-
-
-
-
-
- if (!empty($options['generator_no_ini'])) {
- $def = $this->_generateDefinitionsTable();
- $body .= $this->_generateTableFunction($def['table']);
- $body .= $this->_generateKeysFunction($def['keys']);
- $body .= $this->_generateSequenceKeyFunction($def);
- $body .= $this->_generateDefaultsFunction($this->table, $def['table']);
- } elseif (!empty($options['generator_add_defaults'])) {
-
-
- $def = $this->_generateDefinitionsTable();
- $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";
-
- if (!empty($options['generator_add_validate_stubs'])) {
- foreach ($defs as $t) {
- if (!strlen(trim($t->name))) {
- continue;
- }
- $validate_fname = 'validate' . $this->getMethodNameFromColumnName($t->name);
-
- 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;
- }
-
- $class_rewrite = 'DB_DataObject';
- $options = &(new 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 (new 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;
- }
-
- public function derivedHookPageLevelDocBlock()
- {
- return '';
- }
-
- public function derivedHookExtendsDocBlock()
- {
- return '';
- }
-
- public function derivedHookClassDocBlock()
- {
- return '';
- }
-
- public function derivedHookVar(&$t, $padding)
- {
-
-
- return "";
- }
-
- public function derivedHookPostVar($t)
- {
-
-
- return "";
- }
-
- public function _generateGetters($input)
- {
- $options = &(new PEAR)->getStaticProperty('DB_DataObject', 'options');
- $getters = '';
-
- if (empty($options['generate_getters'])) {
- return '';
- }
-
- $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];
-
- foreach ($defs as $t) {
-
- $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;
- }
-
- public function getMethodNameFromColumnName($col)
- {
- return ucfirst($col);
- }
-
- public function _generateSetters($input)
- {
- $options = &(new PEAR)->getStaticProperty('DB_DataObject', 'options');
- $setters = '';
-
- if (empty($options['generate_setters'])) {
- return '';
- }
-
- $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];
-
- foreach ($defs as $t) {
-
- $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;
- }
-
- public function _generateLinkMethods($input)
- {
- $options = &(new PEAR)->getStaticProperty('DB_DataObject', 'options');
- $setters = '';
-
-
- if (empty($options['generate_link_methods'])) {
-
- return '';
- }
- if (empty($this->_fkeys)) {
-
- return '';
- }
- if (empty($this->_fkeys[$this->table])) {
-
- return '';
- }
-
- $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->_fkeys[$this->table];
-
-
- foreach ($defs as $k => $info) {
-
- $methodName = is_callable($options['generate_link_methods']) ?
- $options['generate_link_methods']($k) : $k;
- if (!strlen(trim($k)) || preg_match("/function[\s]+[&]?$methodName\(/i", $input)) {
- continue;
- }
- $setters .= " /**\n";
- $setters .= " * Getter / Setter for \${$k}\n";
- $setters .= " *\n";
- $setters .= " * @param mixed (optional) value to assign\n";
- $setters .= " * @access public\n";
- $setters .= " */\n";
- $setters .= (substr(phpversion(), 0, 1) > 4) ? ' public '
- : ' ';
- $setters .= "function $methodName() {\n";
- $setters .= " return \$this->link('$k', func_get_args());\n";
- $setters .= " }\n\n";
- }
- return $setters;
- }
-
- 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);
- }
-
- $ret .= ' \'' . addslashes($k) . '\' => ' . $str . ",\n";
- }
- return $ret . " );\n" .
- " }\n";
- }
-
- public function _generateKeysFunction($def)
- {
- $ret = "\n" .
- " function keys()\n" .
- " {\n" .
- " return array(";
- foreach ($def as $k => $type) {
-
- $ret .= '\'' . addslashes($k) . '\', ';
- }
- $ret = preg_replace('#, $#', '', $ret);
- return $ret . ");\n" .
- " }\n";
- }
-
- public function _generateSequenceKeyFunction($def)
- {
-
-
- global $_DB_DATAOBJECT;
-
- $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')
- ) {
-
- $ar = array($usekey, true, $seqname);
- } else {
-
- 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:
- $ret .= "null, ";
- }
- }
- $ret = preg_replace('#, $#', '', $ret);
- return $ret . ");\n" .
- " }\n";
- }
-
- public function _generateDefaultsFunction($table, $defs)
- {
- $__DB = &$GLOBALS['_DB_DATAOBJECT']['CONNECTIONS'][$this->_database_dsn_md5];
- if (!in_array($__DB->phptype, array('mysql', 'mysqli'))) {
- return null;
- }
- $options = (new PEAR)->getStaticProperty('DB_DataObject', 'options');
- $db_driver = empty($options['db_driver']) ? 'DB' : $options['db_driver'];
- $method = $db_driver == 'DB' ? 'getAll' : 'queryAll';
- if ($db_driver == 'DB') {
- $res = $__DB->$method('DESCRIBE ' . $table, DB_FETCHMODE_ASSOC);
- } else {
- $res = $__DB->$method('DESCRIBE ' . $table, MDB2_FETCHMODE_ASSOC);
- }
- $defaults = array();
- foreach ($res as $ar) {
-
- $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):
- 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:
- if (!strlen($ar['Default'])) {
- continue;
- }
- if (is_numeric($ar['Default'])) {
- $defaults[$ar['Field']] = $ar['Default'];
- }
- break;
- }
-
- }
- if (empty($defaults)) {
- return null;
- }
- $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";
- }
-
- public function derivedHookFunctions($input = "")
- {
-
-
- return "";
- }
-
- public function getProxyFull($database, $table)
- {
- if ($err = $this->fillTableSchema($database, $table)) {
- return $err;
- }
- $options = &(new PEAR)->getStaticProperty('DB_DataObject', 'options');
- $class_prefix = empty($options['class_prefix']) ? '' : $options['class_prefix'];
- $this->_extends = empty($options['extends']) ? $this->_extends : $options['extends'];
- $this->_extendsFile = !isset($options['extends_location']) ? $this->_extendsFile : $options['extends_location'];
- $classname = $this->classname = $this->getClassNameFromTableName($this->table);
- $out = $this->_generateClassTable();
-
- eval('?>' . $out);
- return new $classname;
- }
-
- public function fillTableSchema($database, $table)
- {
- global $_DB_DATAOBJECT;
-
- if ((false !== strpos($database, "'")) || (false !== strpos($database, ";"))) {
- return (new PEAR)->raiseError("Error: Database name contains a quote or semi-colon", null, PEAR_ERROR_DIE);
- }
- $this->_database = $database;
- $this->_connect();
- $table = trim($table);
-
- if ((false !== strpos($table, "'")) || (false !== strpos($table, ";"))) {
- return (new PEAR)->raiseError("Error: Table contains a quote or semi-colon", null, PEAR_ERROR_DIE);
- }
- $__DB = &$GLOBALS['_DB_DATAOBJECT']['CONNECTIONS'][$this->_database_dsn_md5];
- $options = (new 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) {
-
- $__DB->expectError(DB_ERROR_UNSUPPORTED);
- $this->tables = $__DB->getListOf('schema.tables');
- $__DB->popExpect();
- } else {
-
- $__DB->setOption('portability', MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_FIX_CASE);
- $__DB->loadModule('Manager');
- $__DB->loadModule('Reverse');
- }
- $quotedTable = !empty($options['quote_identifiers_tableinfo']) ?
- $__DB->quoteIdentifier($table) : $table;
- if (!$is_MDB2) {
- $defs = $__DB->tableInfo($quotedTable);
- } else {
- $defs = $__DB->reverse->tableInfo($quotedTable);
- if ((new PEAR)->isError($defs)) {
- return $defs;
- }
- foreach ($defs as $k => $v) {
- if (!isset($defs[$k]['length'])) {
- continue;
- }
- $defs[$k]['len'] = $defs[$k]['length'];
- }
- }
- if ((new 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');
- }
-
- 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;
- }
- }
|