00001 <?php
00002
00003
00004
00005
00006
00007
00021 function _file_get_contents($file)
00022 {
00023 if (function_exists('file_get_contents')) return file_get_contents($file);
00024
00025 $f = fopen($file,'r');
00026 if (!$f) return '';
00027 $t = '';
00028
00029 while ($s = fread($f,100000)) $t .= $s;
00030 fclose($f);
00031 return $t;
00032 }
00033
00034
00038 if( !defined( 'XMLS_DEBUG' ) ) {
00039 define( 'XMLS_DEBUG', FALSE );
00040 }
00041
00045 if( !defined( 'XMLS_PREFIX' ) ) {
00046 define( 'XMLS_PREFIX', '%%P' );
00047 }
00048
00052 if( !defined( 'XMLS_PREFIX_MAXLEN' ) ) {
00053 define( 'XMLS_PREFIX_MAXLEN', 10 );
00054 }
00055
00059 if( !defined( 'XMLS_EXECUTE_INLINE' ) ) {
00060 define( 'XMLS_EXECUTE_INLINE', FALSE );
00061 }
00062
00066 if( !defined( 'XMLS_CONTINUE_ON_ERROR' ) ) {
00067 define( 'XMLS_CONTINUE_ON_ERROR', FALSE );
00068 }
00069
00073 if( !defined( 'XMLS_SCHEMA_VERSION' ) ) {
00074 define( 'XMLS_SCHEMA_VERSION', '0.3' );
00075 }
00076
00080 if( !defined( 'XMLS_DEFAULT_SCHEMA_VERSION' ) ) {
00081 define( 'XMLS_DEFAULT_SCHEMA_VERSION', '0.1' );
00082 }
00083
00089 if( !defined( 'XMLS_MODE_INSERT' ) ) {
00090 define( 'XMLS_MODE_INSERT', 0 );
00091 }
00092 if( !defined( 'XMLS_MODE_UPDATE' ) ) {
00093 define( 'XMLS_MODE_UPDATE', 1 );
00094 }
00095 if( !defined( 'XMLS_MODE_IGNORE' ) ) {
00096 define( 'XMLS_MODE_IGNORE', 2 );
00097 }
00098 if( !defined( 'XMLS_EXISTING_DATA' ) ) {
00099 define( 'XMLS_EXISTING_DATA', XMLS_MODE_INSERT );
00100 }
00101
00105 if( !defined( 'XMLS_DEFAULT_UPGRADE_METHOD' ) ) {
00106 define( 'XMLS_DEFAULT_UPGRADE_METHOD', 'ALTER' );
00107 }
00108
00112 if( !defined( '_ADODB_LAYER' ) ) {
00113 require( 'adodb.inc.php' );
00114 require( 'adodb-datadict.inc.php' );
00115 }
00116
00124 class dbObject {
00125
00129 var $parent;
00130
00134 var $currentElement;
00135
00139 function dbObject( &$parent, $attributes = NULL ) {
00140 $this->parent =& $parent;
00141 }
00142
00148 function _tag_open( &$parser, $tag, $attributes ) {
00149
00150 }
00151
00157 function _tag_cdata( &$parser, $cdata ) {
00158
00159 }
00160
00166 function _tag_close( &$parser, $tag ) {
00167
00168 }
00169
00170 function create() {
00171 return array();
00172 }
00173
00177 function destroy() {
00178 unset( $this );
00179 }
00180
00188 function supportedPlatform( $platform = NULL ) {
00189 return is_object( $this->parent ) ? $this->parent->supportedPlatform( $platform ) : TRUE;
00190 }
00191
00198 function prefix( $name = '' ) {
00199 return is_object( $this->parent ) ? $this->parent->prefix( $name ) : $name;
00200 }
00201
00208 function FieldID( $field ) {
00209 return strtoupper( preg_replace( '/^`(.+)`$/', '$1', $field ) );
00210 }
00211 }
00212
00224 class dbTable extends dbObject {
00225
00229 var $name;
00230
00234 var $fields = array();
00235
00239 var $indexes = array();
00240
00244 var $opts = array();
00245
00249 var $current_field;
00250
00255 var $drop_table;
00256
00261 var $drop_field = array();
00262
00267 var $currentPlatform = true;
00268
00269
00276 function dbTable( &$parent, $attributes = NULL ) {
00277 $this->parent =& $parent;
00278 $this->name = $this->prefix($attributes['NAME']);
00279 }
00280
00287 function _tag_open( &$parser, $tag, $attributes ) {
00288 $this->currentElement = strtoupper( $tag );
00289
00290 switch( $this->currentElement ) {
00291 case 'INDEX':
00292 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
00293 xml_set_object( $parser, $this->addIndex( $attributes ) );
00294 }
00295 break;
00296 case 'DATA':
00297 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
00298 xml_set_object( $parser, $this->addData( $attributes ) );
00299 }
00300 break;
00301 case 'DROP':
00302 $this->drop();
00303 break;
00304 case 'FIELD':
00305
00306 $fieldName = $attributes['NAME'];
00307 $fieldType = $attributes['TYPE'];
00308 $fieldSize = isset( $attributes['SIZE'] ) ? $attributes['SIZE'] : NULL;
00309 $fieldOpts = !empty( $attributes['OPTS'] ) ? $attributes['OPTS'] : NULL;
00310
00311 $this->addField( $fieldName, $fieldType, $fieldSize, $fieldOpts );
00312 break;
00313 case 'KEY':
00314 case 'NOTNULL':
00315 case 'AUTOINCREMENT':
00316 case 'DEFDATE':
00317 case 'DEFTIMESTAMP':
00318 case 'UNSIGNED':
00319
00320 $this->addFieldOpt( $this->current_field, $this->currentElement );
00321 break;
00322 case 'DEFAULT':
00323
00324
00325
00326 if( $attributes['VALUE'] == '' ) {
00327 $attributes['VALUE'] = " '' ";
00328 }
00329
00330 $this->addFieldOpt( $this->current_field, $this->currentElement, $attributes['VALUE'] );
00331 break;
00332 case 'OPT':
00333 case 'CONSTRAINT':
00334
00335 $this->currentPlatform = ( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) );
00336 break;
00337 default:
00338
00339 }
00340 }
00341
00347 function _tag_cdata( &$parser, $cdata ) {
00348 switch( $this->currentElement ) {
00349
00350 case 'CONSTRAINT':
00351 if( isset( $this->current_field ) ) {
00352 $this->addFieldOpt( $this->current_field, $this->currentElement, $cdata );
00353 } else {
00354 $this->addTableOpt( $cdata );
00355 }
00356 break;
00357
00358 case 'OPT':
00359 if( isset( $this->current_field ) ) {
00360 $this->addFieldOpt( $this->current_field, $cdata );
00361 } else {
00362 $this->addTableOpt( $cdata );
00363 }
00364 break;
00365 default:
00366
00367 }
00368 }
00369
00375 function _tag_close( &$parser, $tag ) {
00376 $this->currentElement = '';
00377
00378 switch( strtoupper( $tag ) ) {
00379 case 'TABLE':
00380 $this->parent->addSQL( $this->create( $this->parent ) );
00381 xml_set_object( $parser, $this->parent );
00382 $this->destroy();
00383 break;
00384 case 'FIELD':
00385 unset($this->current_field);
00386 break;
00387 case 'OPT':
00388 case 'CONSTRAINT':
00389 $this->currentPlatform = true;
00390 break;
00391 default:
00392
00393 }
00394 }
00395
00402 function &addIndex( $attributes ) {
00403 $name = strtoupper( $attributes['NAME'] );
00404 $this->indexes[$name] =& new dbIndex( $this, $attributes );
00405 return $this->indexes[$name];
00406 }
00407
00414 function &addData( $attributes ) {
00415 if( !isset( $this->data ) ) {
00416 $this->data =& new dbData( $this, $attributes );
00417 }
00418 return $this->data;
00419 }
00420
00450 function addField( $name, $type, $size = NULL, $opts = NULL ) {
00451 $field_id = $this->FieldID( $name );
00452
00453
00454 $this->current_field = $field_id;
00455
00456
00457 $this->fields[$field_id]['NAME'] = $name;
00458
00459
00460 $this->fields[$field_id]['TYPE'] = $type;
00461
00462
00463 if( isset( $size ) ) {
00464 $this->fields[$field_id]['SIZE'] = $size;
00465 }
00466
00467
00468 if( isset( $opts ) ) {
00469 $this->fields[$field_id]['OPTS'] = array($opts);
00470 } else {
00471 $this->fields[$field_id]['OPTS'] = array();
00472 }
00473 }
00474
00486 function addFieldOpt( $field, $opt, $value = NULL ) {
00487 if( $this->currentPlatform ) {
00488 if( !isset( $value ) ) {
00489 $this->fields[$this->FieldID( $field )]['OPTS'][] = $opt;
00490
00491 } else {
00492 $this->fields[$this->FieldID( $field )]['OPTS'][] = array( $opt => $value );
00493 }
00494 }
00495 }
00496
00506 function addTableOpt( $opt ) {
00507 if( $this->currentPlatform ) {
00508 $this->opts[] = $opt;
00509 }
00510 return $this->opts;
00511 }
00512
00519 function create( &$xmls ) {
00520 $sql = array();
00521
00522
00523 if( is_array( $legacy_indexes = $xmls->dict->MetaIndexes( $this->name ) ) ) {
00524 foreach( $legacy_indexes as $index => $index_details ) {
00525 $sql[] = $xmls->dict->DropIndexSQL( $index, $this->name );
00526 }
00527 }
00528
00529
00530 foreach( $this->drop_field as $field ) {
00531 unset( $this->fields[$field] );
00532 }
00533
00534
00535 if( is_array( $legacy_fields = $xmls->dict->MetaColumns( $this->name ) ) ) {
00536
00537 if( $this->drop_table ) {
00538 $sql[] = $xmls->dict->DropTableSQL( $this->name );
00539
00540 return $sql;
00541 }
00542
00543
00544 foreach( $legacy_fields as $field_id => $field ) {
00545 if( !isset( $this->fields[$field_id] ) ) {
00546 $sql[] = $xmls->dict->DropColumnSQL( $this->name, $field->name );
00547 }
00548 }
00549
00550 } else {
00551 if( $this->drop_table ) {
00552 return $sql;
00553 }
00554
00555 $legacy_fields = array();
00556 }
00557
00558
00559 $fldarray = array();
00560
00561 foreach( $this->fields as $field_id => $finfo ) {
00562
00563 if( !isset( $finfo['SIZE'] ) ) {
00564 $finfo['SIZE'] = '';
00565 }
00566
00567
00568 $fldarray[$field_id] = array(
00569 'NAME' => $finfo['NAME'],
00570 'TYPE' => $finfo['TYPE'],
00571 'SIZE' => $finfo['SIZE']
00572 );
00573
00574
00575 if( isset( $finfo['OPTS'] ) ) {
00576 foreach( $finfo['OPTS'] as $opt ) {
00577
00578 if( is_array( $opt ) ) {
00579 $key = key( $opt );
00580 $value = $opt[key( $opt )];
00581 @$fldarray[$field_id][$key] .= $value;
00582
00583 } else {
00584 $fldarray[$field_id][$opt] = $opt;
00585 }
00586 }
00587 }
00588 }
00589
00590 if( empty( $legacy_fields ) ) {
00591
00592 $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
00593 logMsg( end( $sql ), 'Generated CreateTableSQL' );
00594 } else {
00595
00596 logMsg( "Upgrading {$this->name} using '{$xmls->upgrade}'" );
00597 switch( $xmls->upgrade ) {
00598
00599 case 'ALTER':
00600 logMsg( 'Generated ChangeTableSQL (ALTERing table)' );
00601 $sql[] = $xmls->dict->ChangeTableSQL( $this->name, $fldarray, $this->opts );
00602 break;
00603 case 'REPLACE':
00604 logMsg( 'Doing upgrade REPLACE (testing)' );
00605 $sql[] = $xmls->dict->DropTableSQL( $this->name );
00606 $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
00607 break;
00608
00609 default:
00610 return array();
00611 }
00612 }
00613
00614 foreach( $this->indexes as $index ) {
00615 $sql[] = $index->create( $xmls );
00616 }
00617
00618 if( isset( $this->data ) ) {
00619 $sql[] = $this->data->create( $xmls );
00620 }
00621
00622 return $sql;
00623 }
00624
00628 function drop() {
00629 if( isset( $this->current_field ) ) {
00630
00631 logMsg( "Dropping field '{$this->current_field}' from table '{$this->name}'" );
00632
00633 $this->drop_field[$this->current_field] = $this->current_field;
00634 } else {
00635
00636 logMsg( "Dropping table '{$this->name}'" );
00637
00638 $this->drop_table = TRUE;
00639 }
00640 }
00641 }
00642
00654 class dbIndex extends dbObject {
00655
00659 var $name;
00660
00664 var $opts = array();
00665
00669 var $columns = array();
00670
00675 var $drop = FALSE;
00676
00685 function dbIndex( &$parent, $attributes = NULL ) {
00686 $this->parent =& $parent;
00687
00688 $this->name = $this->prefix ($attributes['NAME']);
00689 }
00690
00699 function _tag_open( &$parser, $tag, $attributes ) {
00700 $this->currentElement = strtoupper( $tag );
00701
00702 switch( $this->currentElement ) {
00703 case 'DROP':
00704 $this->drop();
00705 break;
00706 case 'CLUSTERED':
00707 case 'BITMAP':
00708 case 'UNIQUE':
00709 case 'FULLTEXT':
00710 case 'HASH':
00711
00712 $this->addIndexOpt( $this->currentElement );
00713 break;
00714 default:
00715
00716 }
00717 }
00718
00726 function _tag_cdata( &$parser, $cdata ) {
00727 switch( $this->currentElement ) {
00728
00729 case 'COL':
00730 $this->addField( $cdata );
00731 break;
00732 default:
00733
00734 }
00735 }
00736
00742 function _tag_close( &$parser, $tag ) {
00743 $this->currentElement = '';
00744
00745 switch( strtoupper( $tag ) ) {
00746 case 'INDEX':
00747 xml_set_object( $parser, $this->parent );
00748 break;
00749 }
00750 }
00751
00758 function addField( $name ) {
00759 $this->columns[$this->FieldID( $name )] = $name;
00760
00761
00762 return $this->columns;
00763 }
00764
00771 function addIndexOpt( $opt ) {
00772 $this->opts[] = $opt;
00773
00774
00775 return $this->opts;
00776 }
00777
00784 function create( &$xmls ) {
00785 if( $this->drop ) {
00786 return NULL;
00787 }
00788
00789
00790 foreach( $this->columns as $id => $col ) {
00791 if( !isset( $this->parent->fields[$id] ) ) {
00792 unset( $this->columns[$id] );
00793 }
00794 }
00795
00796 return $xmls->dict->CreateIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts );
00797 }
00798
00802 function drop() {
00803 $this->drop = TRUE;
00804 }
00805 }
00806
00816 class dbData extends dbObject {
00817
00818 var $data = array();
00819
00820 var $row;
00821
00830 function dbData( &$parent, $attributes = NULL ) {
00831 $this->parent =& $parent;
00832 }
00833
00842 function _tag_open( &$parser, $tag, $attributes ) {
00843 $this->currentElement = strtoupper( $tag );
00844
00845 switch( $this->currentElement ) {
00846 case 'ROW':
00847 $this->row = count( $this->data );
00848 $this->data[$this->row] = array();
00849 break;
00850 case 'F':
00851 $this->addField($attributes);
00852 default:
00853
00854 }
00855 }
00856
00864 function _tag_cdata( &$parser, $cdata ) {
00865 switch( $this->currentElement ) {
00866
00867 case 'F':
00868 $this->addData( $cdata );
00869 break;
00870 default:
00871
00872 }
00873 }
00874
00880 function _tag_close( &$parser, $tag ) {
00881 $this->currentElement = '';
00882
00883 switch( strtoupper( $tag ) ) {
00884 case 'DATA':
00885 xml_set_object( $parser, $this->parent );
00886 break;
00887 }
00888 }
00889
00896 function addField( $attributes ) {
00897
00898 if( !isset( $this->row ) || !isset( $this->data[$this->row] ) ) {
00899 return;
00900 }
00901
00902
00903 if( isset( $attributes['NAME'] ) ) {
00904 $this->current_field = $this->FieldID( $attributes['NAME'] );
00905 } else {
00906 $this->current_field = count( $this->data[$this->row] );
00907 }
00908
00909
00910 if( !isset( $this->data[$this->row][$this->current_field] ) ) {
00911 $this->data[$this->row][$this->current_field] = '';
00912 }
00913 }
00914
00921 function addData( $cdata ) {
00922
00923 if ( isset( $this->data[$this->row][$this->current_field] ) ) {
00924
00925 $this->data[$this->row][$this->current_field] .= $cdata;
00926 }
00927 }
00928
00935 function create( &$xmls ) {
00936 $table = $xmls->dict->TableName($this->parent->name);
00937 $table_field_count = count($this->parent->fields);
00938 $tables = $xmls->db->MetaTables();
00939 $sql = array();
00940
00941 $ukeys = $xmls->db->MetaPrimaryKeys( $table );
00942 if( !empty( $this->parent->indexes ) and !empty( $ukeys ) ) {
00943 foreach( $this->parent->indexes as $indexObj ) {
00944 if( !in_array( $indexObj->name, $ukeys ) ) $ukeys[] = $indexObj->name;
00945 }
00946 }
00947
00948
00949 foreach( $this->data as $row ) {
00950 $table_fields = $this->parent->fields;
00951 $fields = array();
00952 $rawfields = array();
00953
00954 foreach( $row as $field_id => $field_data ) {
00955 if( !array_key_exists( $field_id, $table_fields ) ) {
00956 if( is_numeric( $field_id ) ) {
00957 $field_id = reset( array_keys( $table_fields ) );
00958 } else {
00959 continue;
00960 }
00961 }
00962
00963 $name = $table_fields[$field_id]['NAME'];
00964
00965 switch( $table_fields[$field_id]['TYPE'] ) {
00966 case 'I':
00967 case 'I1':
00968 case 'I2':
00969 case 'I4':
00970 case 'I8':
00971 $fields[$name] = intval($field_data);
00972 break;
00973 case 'C':
00974 case 'C2':
00975 case 'X':
00976 case 'X2':
00977 default:
00978 $fields[$name] = $xmls->db->qstr( $field_data );
00979 $rawfields[$name] = $field_data;
00980 }
00981
00982 unset($table_fields[$field_id]);
00983
00984 }
00985
00986
00987 if( empty( $fields ) ) {
00988 continue;
00989 }
00990
00991
00992 if( count( $fields ) < $table_field_count ) {
00993 foreach( $table_fields as $field ) {
00994 if( isset( $field['OPTS'] ) and ( in_array( 'NOTNULL', $field['OPTS'] ) || in_array( 'KEY', $field['OPTS'] ) ) && !in_array( 'AUTOINCREMENT', $field['OPTS'] ) ) {
00995 continue(2);
00996 }
00997 }
00998 }
00999
01000
01001
01002 if( !in_array( $table, $tables ) or ( $mode = $xmls->existingData() ) == XMLS_MODE_INSERT ) {
01003
01004 logMsg( "$table doesn't exist, inserting or mode is INSERT" );
01005 $sql[] = 'INSERT INTO '. $table .' ('. implode( ',', array_keys( $fields ) ) .') VALUES ('. implode( ',', $fields ) .')';
01006 continue;
01007 }
01008
01009
01010 $mfields = array_merge( $fields, $rawfields );
01011 $keyFields = array_intersect( $ukeys, array_keys( $mfields ) );
01012
01013 if( empty( $ukeys ) or count( $keyFields ) == 0 ) {
01014
01015 logMsg( "Either schema or data has no unique keys, so safe to insert" );
01016 $sql[] = 'INSERT INTO '. $table .' ('. implode( ',', array_keys( $fields ) ) .') VALUES ('. implode( ',', $fields ) .')';
01017 continue;
01018 }
01019
01020
01021 $where = '';
01022 foreach( $ukeys as $key ) {
01023 if( isset( $mfields[$key] ) and $mfields[$key] ) {
01024 if( $where ) $where .= ' AND ';
01025 $where .= $key . ' = ' . $xmls->db->qstr( $mfields[$key] );
01026 }
01027 }
01028 $records = $xmls->db->Execute( 'SELECT * FROM ' . $table . ' WHERE ' . $where );
01029 switch( $records->RecordCount() ) {
01030 case 0:
01031
01032 logMsg( "No matching records. Inserting new row with unique data" );
01033 $sql[] = $xmls->db->GetInsertSQL( $records, $mfields );
01034 break;
01035 case 1:
01036
01037 logMsg( "One matching record..." );
01038 if( $mode == XMLS_MODE_UPDATE ) {
01039 logMsg( "...Updating existing row from unique data" );
01040 $sql[] = $xmls->db->GetUpdateSQL( $records, $mfields );
01041 }
01042 break;
01043 default:
01044
01045 logMsg( "More than one matching record. Ignoring row." );
01046 }
01047 }
01048 return $sql;
01049 }
01050 }
01051
01058 class dbQuerySet extends dbObject {
01059
01063 var $queries = array();
01064
01068 var $query;
01069
01073 var $prefixKey = '';
01074
01078 var $prefixMethod = 'AUTO';
01079
01086 function dbQuerySet( &$parent, $attributes = NULL ) {
01087 $this->parent =& $parent;
01088
01089
01090 if( isset( $attributes['KEY'] ) ) {
01091 $this->prefixKey = $attributes['KEY'];
01092 }
01093
01094 $prefixMethod = isset( $attributes['PREFIXMETHOD'] ) ? strtoupper( trim( $attributes['PREFIXMETHOD'] ) ) : '';
01095
01096
01097 switch( $prefixMethod ) {
01098 case 'AUTO':
01099 $this->prefixMethod = 'AUTO';
01100 break;
01101 case 'MANUAL':
01102 $this->prefixMethod = 'MANUAL';
01103 break;
01104 case 'NONE':
01105 $this->prefixMethod = 'NONE';
01106 break;
01107 }
01108 }
01109
01116 function _tag_open( &$parser, $tag, $attributes ) {
01117 $this->currentElement = strtoupper( $tag );
01118
01119 switch( $this->currentElement ) {
01120 case 'QUERY':
01121
01122
01123
01124 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
01125 $this->newQuery();
01126 } else {
01127 $this->discardQuery();
01128 }
01129 break;
01130 default:
01131
01132 }
01133 }
01134
01138 function _tag_cdata( &$parser, $cdata ) {
01139 switch( $this->currentElement ) {
01140
01141 case 'QUERY':
01142 $this->buildQuery( $cdata );
01143 break;
01144 default:
01145
01146 }
01147 }
01148
01154 function _tag_close( &$parser, $tag ) {
01155 $this->currentElement = '';
01156
01157 switch( strtoupper( $tag ) ) {
01158 case 'QUERY':
01159
01160 $this->addQuery();
01161 break;
01162 case 'SQL':
01163 $this->parent->addSQL( $this->create( $this->parent ) );
01164 xml_set_object( $parser, $this->parent );
01165 $this->destroy();
01166 break;
01167 default:
01168
01169 }
01170 }
01171
01177 function newQuery() {
01178 $this->query = '';
01179
01180 return TRUE;
01181 }
01182
01188 function discardQuery() {
01189 unset( $this->query );
01190
01191 return TRUE;
01192 }
01193
01200 function buildQuery( $sql = NULL ) {
01201 if( !isset( $this->query ) OR empty( $sql ) ) {
01202 return FALSE;
01203 }
01204
01205 $this->query .= $sql;
01206
01207 return $this->query;
01208 }
01209
01215 function addQuery() {
01216 if( !isset( $this->query ) ) {
01217 return FALSE;
01218 }
01219
01220 $this->queries[] = $return = trim($this->query);
01221
01222 unset( $this->query );
01223
01224 return $return;
01225 }
01226
01233 function create( &$xmls ) {
01234 foreach( $this->queries as $id => $query ) {
01235 switch( $this->prefixMethod ) {
01236 case 'AUTO':
01237
01238
01239
01240
01241 $query = $this->prefixQuery( '/^\s*((?is)INSERT\s+(INTO\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
01242 $query = $this->prefixQuery( '/^\s*((?is)UPDATE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
01243 $query = $this->prefixQuery( '/^\s*((?is)DELETE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
01244
01245
01246 #$data = preg_replace( '/(?ias)(^\s*SELECT\s+.*\s+FROM)\s+(\W\s*,?\s*)+((?i)\s+WHERE.*$)/', "\1 $prefix\2 \3", $data );
01247
01248 case 'MANUAL':
01249
01250
01251 if( isset( $this->prefixKey ) AND( $this->prefixKey !== '' ) ) {
01252
01253 $query = str_replace( $this->prefixKey, $xmls->objectPrefix, $query );
01254 } else {
01255
01256 $query = str_replace( XMLS_PREFIX , $xmls->objectPrefix, $query );
01257 }
01258 }
01259
01260 $this->queries[$id] = trim( $query );
01261 }
01262
01263
01264 return $this->queries;
01265 }
01266
01275 function prefixQuery( $regex, $query, $prefix = NULL ) {
01276 if( !isset( $prefix ) ) {
01277 return $query;
01278 }
01279
01280 if( preg_match( $regex, $query, $match ) ) {
01281 $preamble = $match[1];
01282 $postamble = $match[5];
01283 $objectList = explode( ',', $match[3] );
01284
01285
01286 $prefixedList = '';
01287
01288 foreach( $objectList as $object ) {
01289 if( $prefixedList !== '' ) {
01290 $prefixedList .= ', ';
01291 }
01292
01293 $prefixedList .= $prefix . trim( $object );
01294 }
01295
01296 $query = $preamble . ' ' . $prefixedList . ' ' . $postamble;
01297 }
01298
01299 return $query;
01300 }
01301 }
01302
01316 class adoSchema {
01317
01322 var $sqlArray;
01323
01328 var $db;
01329
01334 var $dict;
01335
01340 var $currentElement = '';
01341
01346 var $upgrade = '';
01347
01352 var $objectPrefix = '';
01353
01358 var $mgq;
01359
01364 var $debug;
01365
01370 var $versionRegex = '/<schema.*?( version="([^"]*)")?.*?>/';
01371
01376 var $schemaVersion;
01377
01381 var $success;
01382
01386 var $executeInline;
01387
01391 var $continueOnError;
01392
01396 var $existingData;
01397
01407 function adoSchema( &$db ) {
01408 // Initialize the environment
01409 $this->mgq = get_magic_quotes_runtime();
01410 set_magic_quotes_runtime(0);
01411
01412 $this->db =& $db;
01413 $this->debug = $this->db->debug;
01414 $this->dict = NewDataDictionary( $this->db );
01415 $this->sqlArray = array();
01416 $this->schemaVersion = XMLS_SCHEMA_VERSION;
01417 $this->executeInline( XMLS_EXECUTE_INLINE );
01418 $this->continueOnError( XMLS_CONTINUE_ON_ERROR );
01419 $this->existingData( XMLS_EXISTING_DATA );
01420 $this->setUpgradeMethod();
01421 }
01422
01439 function SetUpgradeMethod( $method = '' ) {
01440 if( !is_string( $method ) ) {
01441 return FALSE;
01442 }
01443
01444 $method = strtoupper( $method );
01445
01446 // Handle the upgrade methods
01447 switch( $method ) {
01448 case 'ALTER':
01449 $this->upgrade = $method;
01450 break;
01451 case 'REPLACE':
01452 $this->upgrade = $method;
01453 break;
01454 case 'BEST':
01455 $this->upgrade = 'ALTER';
01456 break;
01457 case 'NONE':
01458 $this->upgrade = 'NONE';
01459 break;
01460 default:
01461 // Use default if no legitimate method is passed.
01462 $this->upgrade = XMLS_DEFAULT_UPGRADE_METHOD;
01463 }
01464
01465 return $this->upgrade;
01466 }
01467
01487 function ExistingData( $mode = NULL ) {
01488 if( is_int( $mode ) ) {
01489 switch( $mode ) {
01490 case XMLS_MODE_UPDATE:
01491 $mode = XMLS_MODE_UPDATE;
01492 break;
01493 case XMLS_MODE_IGNORE:
01494 $mode = XMLS_MODE_IGNORE;
01495 break;
01496 case XMLS_MODE_INSERT:
01497 $mode = XMLS_MODE_INSERT;
01498 break;
01499 default:
01500 $mode = XMLS_EXISITNG_DATA;
01501 break;
01502 }
01503 $this->existingData = $mode;
01504 }
01505
01506 return $this->existingData;
01507 }
01508
01522 function ExecuteInline( $mode = NULL ) {
01523 if( is_bool( $mode ) ) {
01524 $this->executeInline = $mode;
01525 }
01526
01527 return $this->executeInline;
01528 }
01529
01543 function ContinueOnError( $mode = NULL ) {
01544 if( is_bool( $mode ) ) {
01545 $this->continueOnError = $mode;
01546 }
01547
01548 return $this->continueOnError;
01549 }
01550
01564 function ParseSchema( $filename, $returnSchema = FALSE ) {
01565 return $this->ParseSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
01566 }
01567
01589 function ParseSchemaFile( $filename, $returnSchema = FALSE ) {
01590 // Open the file
01591 if( !($fp = fopen( $filename, 'r' )) ) {
01592 logMsg( 'Unable to open file' );
01593 return FALSE;
01594 }
01595
01596 // do version detection here
01597 if( $this->SchemaFileVersion( $filename ) != $this->schemaVersion ) {
01598 logMsg( 'Invalid Schema Version' );
01599 return FALSE;
01600 }
01601
01602 if( $returnSchema ) {
01603 $xmlstring = '';
01604 while( $data = fread( $fp, 4096 ) ) {
01605 $xmlstring .= $data . "\n";
01606 }
01607 return $xmlstring;
01608 }
01609
01610 $this->success = 2;
01611
01612 $xmlParser = $this->create_parser();
01613
01614 // Process the file
01615 while( $data = fread( $fp, 4096 ) ) {
01616 if( !xml_parse( $xmlParser, $data, feof( $fp ) ) ) {
01617 die( sprintf(
01618 "XML error: %s at line %d",
01619 xml_error_string( xml_get_error_code( $xmlParser) ),
01620 xml_get_current_line_number( $xmlParser)
01621 ) );
01622 }
01623 }
01624
01625 xml_parser_free( $xmlParser );
01626
01627 return $this->sqlArray;
01628 }
01629
01641 function ParseSchemaString( $xmlstring, $returnSchema = FALSE ) {
01642 if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
01643 logMsg( 'Empty or Invalid Schema' );
01644 return FALSE;
01645 }
01646
01647 // do version detection here
01648 if( $this->SchemaStringVersion( $xmlstring ) != $this->schemaVersion ) {
01649 logMsg( 'Invalid Schema Version' );
01650 return FALSE;
01651 }
01652
01653 if( $returnSchema ) {
01654 return $xmlstring;
01655 }
01656
01657 $this->success = 2;
01658
01659 $xmlParser = $this->create_parser();
01660
01661 if( !xml_parse( $xmlParser, $xmlstring, TRUE ) ) {
01662 die( sprintf(
01663 "XML error: %s at line %d",
01664 xml_error_string( xml_get_error_code( $xmlParser) ),
01665 xml_get_current_line_number( $xmlParser)
01666 ) );
01667 }
01668
01669 xml_parser_free( $xmlParser );
01670
01671 return $this->sqlArray;
01672 }
01673
01685 function RemoveSchema( $filename, $returnSchema = FALSE ) {
01686 return $this->RemoveSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
01687 }
01688
01700 function RemoveSchemaString( $schema, $returnSchema = FALSE ) {
01701
01702 // grab current version
01703 if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
01704 return FALSE;
01705 }
01706
01707 return $this->ParseSchemaString( $this->TransformSchema( $schema, 'remove-' . $version), $returnSchema );
01708 }
01709
01723 function ExecuteSchema( $sqlArray = NULL, $continueOnErr = NULL ) {
01724 if( !is_bool( $continueOnErr ) ) {
01725 $continueOnErr = $this->ContinueOnError();
01726 }
01727
01728 if( !isset( $sqlArray ) ) {
01729 $sqlArray = $this->sqlArray;
01730 }
01731
01732 if( !is_array( $sqlArray ) ) {
01733 $this->success = 0;
01734 } else {
01735 $this->success = $this->dict->ExecuteSQLArray( $sqlArray, $continueOnErr );
01736 }
01737
01738 return $this->success;
01739 }
01740
01750 function PrintSQL( $format = 'NONE' ) {
01751 $sqlArray = null;
01752 return $this->getSQL( $format, $sqlArray );
01753 }
01754
01764 function SaveSQL( $filename = './schema.sql' ) {
01765
01766 if( !isset( $sqlArray ) ) {
01767 $sqlArray = $this->sqlArray;
01768 }
01769 if( !isset( $sqlArray ) ) {
01770 return FALSE;
01771 }
01772
01773 $fp = fopen( $filename, "w" );
01774
01775 foreach( $sqlArray as $key => $query ) {
01776 fwrite( $fp, $query . ";\n" );
01777 }
01778 fclose( $fp );
01779 }
01780
01788 function &create_parser() {
01789 // Create the parser
01790 $xmlParser = xml_parser_create();
01791 xml_set_object( $xmlParser, $this );
01792
01793 // Initialize the XML callback functions
01794 xml_set_element_handler( $xmlParser, '_tag_open', '_tag_close' );
01795 xml_set_character_data_handler( $xmlParser, '_tag_cdata' );
01796
01797 return $xmlParser;
01798 }
01799
01805 function _tag_open( &$parser, $tag, $attributes ) {
01806 switch( strtoupper( $tag ) ) {
01807 case 'TABLE':
01808 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
01809 $this->obj = new dbTable( $this, $attributes );
01810 xml_set_object( $parser, $this->obj );
01811 }
01812 break;
01813 case 'SQL':
01814 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
01815 $this->obj = new dbQuerySet( $this, $attributes );
01816 xml_set_object( $parser, $this->obj );
01817 }
01818 break;
01819 default:
01820 // print_r( array( $tag, $attributes ) );
01821 }
01822
01823 }
01824
01830 function _tag_cdata( &$parser, $cdata ) {
01831 }
01832
01839 function _tag_close( &$parser, $tag ) {
01840
01841 }
01842
01859 function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
01860
01861 // grab current version
01862 if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
01863 return FALSE;
01864 }
01865
01866 if( !isset ($newVersion) ) {
01867 $newVersion = $this->schemaVersion;
01868 }
01869
01870 if( $version == $newVersion ) {
01871 $result = $schema;
01872 } else {
01873 $result = $this->TransformSchema( $schema, 'convert-' . $version . '-' . $newVersion);
01874 }
01875
01876 if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
01877 fwrite( $fp, $result );
01878 fclose( $fp );
01879 }
01880
01881 return $result;
01882 }
01883
01884 /*
01885 // compat for pre-4.3 - jlim
01886 function _file_get_contents($path)
01887 {
01888 if (function_exists('file_get_contents')) return file_get_contents($path);
01889 return join('',file($path));
01890 }*/
01891
01908 function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
01909
01910 // grab current version
01911 if( !( $version = $this->SchemaFileVersion( $filename ) ) ) {
01912 return FALSE;
01913 }
01914
01915 if( !isset ($newVersion) ) {
01916 $newVersion = $this->schemaVersion;
01917 }
01918
01919 if( $version == $newVersion ) {
01920 $result = _file_get_contents( $filename );
01921
01922 // remove unicode BOM if present
01923 if( substr( $result, 0, 3 ) == sprintf( '%c%c%c', 239, 187, 191 ) ) {
01924 $result = substr( $result, 3 );
01925 }
01926 } else {
01927 $result = $this->TransformSchema( $filename, 'convert-' . $version . '-' . $newVersion, 'file' );
01928 }
01929
01930 if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
01931 fwrite( $fp, $result );
01932 fclose( $fp );
01933 }
01934
01935 return $result;
01936 }
01937
01938 function TransformSchema( $schema, $xsl, $schematype='string' )
01939 {
01940 // Fail if XSLT extension is not available
01941 if( ! function_exists( 'xslt_create' ) ) {
01942 return FALSE;
01943 }
01944
01945 $xsl_file = dirname( __FILE__ ) . '/xsl/' . $xsl . '.xsl';
01946
01947 // look for xsl
01948 if( !is_readable( $xsl_file ) ) {
01949 return FALSE;
01950 }
01951
01952 switch( $schematype )
01953 {
01954 case 'file':
01955 if( !is_readable( $schema ) ) {
01956 return FALSE;
01957 }
01958
01959 $schema = _file_get_contents( $schema );
01960 break;
01961 case 'string':
01962 default:
01963 if( !is_string( $schema ) ) {
01964 return FALSE;
01965 }
01966 }
01967
01968 $arguments = array (
01969 '/_xml' => $schema,
01970 '/_xsl' => _file_get_contents( $xsl_file )
01971 );
01972
01973 // create an XSLT processor
01974 $xh = xslt_create ();
01975
01976 // set error handler
01977 xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler'));
01978
01979 // process the schema
01980 $result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
01981
01982 xslt_free ($xh);
01983
01984 return $result;
01985 }
01986
01997 function xslt_error_handler( $parser, $errno, $level, $fields ) {
01998 if( is_array( $fields ) ) {
01999 $msg = array(
02000 'Message Type' => ucfirst( $fields['msgtype'] ),
02001 'Message Code' => $fields['code'],
02002 'Message' => $fields['msg'],
02003 'Error Number' => $errno,
02004 'Level' => $level
02005 );
02006
02007 switch( $fields['URI'] ) {
02008 case 'arg:/_xml':
02009 $msg['Input'] = 'XML';
02010 break;
02011 case 'arg:/_xsl':
02012 $msg['Input'] = 'XSL';
02013 break;
02014 default:
02015 $msg['Input'] = $fields['URI'];
02016 }
02017
02018 $msg['Line'] = $fields['line'];
02019 } else {
02020 $msg = array(
02021 'Message Type' => 'Error',
02022 'Error Number' => $errno,
02023 'Level' => $level,
02024 'Fields' => var_export( $fields, TRUE )
02025 );
02026 }
02027
02028 $error_details = $msg['Message Type'] . ' in XSLT Transformation' . "\n"
02029 . '<table>' . "\n";
02030
02031 foreach( $msg as $label => $details ) {
02032 $error_details .= '<tr><td><b>' . $label . ': </b></td><td>' . htmlentities( $details ) . '</td></tr>' . "\n";
02033 }
02034
02035 $error_details .= '</table>';
02036
02037 trigger_error( $error_details, E_USER_ERROR );
02038 }
02039
02049 function SchemaFileVersion( $filename ) {
02050 // Open the file
02051 if( !($fp = fopen( $filename, 'r' )) ) {
02052 // die( 'Unable to open file' );
02053 return FALSE;
02054 }
02055
02056 // Process the file
02057 while( $data = fread( $fp, 4096 ) ) {
02058 if( preg_match( $this->versionRegex, $data, $matches ) ) {
02059 return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
02060 }
02061 }
02062
02063 return FALSE;
02064 }
02065
02075 function SchemaStringVersion( $xmlstring ) {
02076 if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
02077 return FALSE;
02078 }
02079
02080 if( preg_match( $this->versionRegex, $xmlstring, $matches ) ) {
02081 return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
02082 }
02083
02084 return FALSE;
02085 }
02086
02097 function ExtractSchema( $data = FALSE, $indent = ' ' ) {
02098 $old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM );
02099
02100 $schema = '<?xml version="1.0"?>' . "\n"
02101 . '<schema version="' . $this->schemaVersion . '">' . "\n";
02102
02103 if( is_array( $tables = $this->db->MetaTables( 'TABLES' ) ) ) {
02104 foreach( $tables as $table ) {
02105 $schema .= $indent . '<table name="' . htmlentities( $table ) . '">' . "\n";
02106
02107 // grab details from database
02108 $rs = $this->db->Execute( 'SELECT * FROM ' . $table . ' WHERE -1' );
02109 $fields = $this->db->MetaColumns( $table );
02110 $indexes = $this->db->MetaIndexes( $table );
02111
02112 if( is_array( $fields ) ) {
02113 foreach( $fields as $details ) {
02114 $extra = '';
02115 $content = array();
02116
02117 if( isset($details->max_length) && $details->max_length > 0 ) {
02118 $extra .= ' size="' . $details->max_length . '"';
02119 }
02120
02121 if( isset($details->primary_key) && $details->primary_key ) {
02122 $content[] = '<KEY/>';
02123 } elseif( isset($details->not_null) && $details->not_null ) {
02124 $content[] = '<NOTNULL/>';
02125 }
02126
02127 if( isset($details->has_default) && $details->has_default ) {
02128 $content[] = '<DEFAULT value="' . htmlentities( $details->default_value ) . '"/>';
02129 }
02130
02131 if( isset($details->auto_increment) && $details->auto_increment ) {
02132 $content[] = '<AUTOINCREMENT/>';
02133 }
02134
02135 if( isset($details->unsigned) && $details->unsigned ) {
02136 $content[] = '<UNSIGNED/>';
02137 }
02138
02139
02140
02141 $details->primary_key = 0;
02142 $type = $rs->MetaType( $details );
02143
02144 $schema .= str_repeat( $indent, 2 ) . '<field name="' . htmlentities( $details->name ) . '" type="' . $type . '"' . $extra;
02145
02146 if( !empty( $content ) ) {
02147 $schema .= ">\n" . str_repeat( $indent, 3 )
02148 . implode( "\n" . str_repeat( $indent, 3 ), $content ) . "\n"
02149 . str_repeat( $indent, 2 ) . '</field>' . "\n";
02150 } else {
02151 $schema .= "/>\n";
02152 }
02153 }
02154 }
02155
02156 if( is_array( $indexes ) ) {
02157 foreach( $indexes as $index => $details ) {
02158 $schema .= str_repeat( $indent, 2 ) . '<index name="' . $index . '">' . "\n";
02159
02160 if( $details['unique'] ) {
02161 $schema .= str_repeat( $indent, 3 ) . '<UNIQUE/>' . "\n";
02162 }
02163
02164 foreach( $details['columns'] as $column ) {
02165 $schema .= str_repeat( $indent, 3 ) . '<col>' . htmlentities( $column ) . '</col>' . "\n";
02166 }
02167
02168 $schema .= str_repeat( $indent, 2 ) . '</index>' . "\n";
02169 }
02170 }
02171
02172 if( $data ) {
02173 $rs = $this->db->Execute( 'SELECT * FROM ' . $table );
02174
02175 if( is_object( $rs ) && !$rs->EOF ) {
02176 $schema .= str_repeat( $indent, 2 ) . "<data>\n";
02177
02178 while( $row = $rs->FetchRow() ) {
02179 foreach( $row as $key => $val ) {
02180 if ( $val != htmlentities( $val ) ) {
02181 $row[$key] = '<![CDATA[' . $val . ']]>';
02182 }
02183 }
02184
02185 $schema .= str_repeat( $indent, 3 ) . '<row><f>' . implode( '</f><f>', $row ) . "</f></row>\n";
02186 }
02187
02188 $schema .= str_repeat( $indent, 2 ) . "</data>\n";
02189 }
02190 }
02191
02192 $schema .= $indent . "</table>\n";
02193 }
02194 }
02195
02196 $this->db->SetFetchMode( $old_mode );
02197
02198 $schema .= '</schema>';
02199 return $schema;
02200 }
02201
02212 function SetPrefix( $prefix = '', $underscore = TRUE ) {
02213 switch( TRUE ) {
02214
02215 case empty( $prefix ):
02216 logMsg( 'Cleared prefix' );
02217 $this->objectPrefix = '';
02218 return TRUE;
02219
02220 case strlen( $prefix ) > XMLS_PREFIX_MAXLEN:
02221
02222 case !preg_match( '/^[a-z][a-z0-9_]+$/i', $prefix ):
02223 logMsg( 'Invalid prefix: ' . $prefix );
02224 return FALSE;
02225 }
02226
02227 if( $underscore AND substr( $prefix, -1 ) != '_' ) {
02228 $prefix .= '_';
02229 }
02230
02231
02232 logMsg( 'Set prefix: ' . $prefix );
02233 $this->objectPrefix = $prefix;
02234 return TRUE;
02235 }
02236
02245 function prefix( $name = '' ) {
02246
02247 if( !empty( $this->objectPrefix ) ) {
02248
02249
02250 return preg_replace( '/^(`?)(.+)$/', '$1' . $this->objectPrefix . '$2', $name );
02251 }
02252
02253
02254 return $name;
02255 }
02256
02265 function supportedPlatform( $platform = NULL ) {
02266 if( !empty( $platform ) ) {
02267 $regex = '/(^|\|)' . $this->db->databaseType . '(\||$)/i';
02268
02269 if( preg_match( '/^- /', $platform ) ) {
02270 if (preg_match ( $regex, substr( $platform, 2 ) ) ) {
02271 logMsg( 'Platform ' . $platform . ' is NOT supported' );
02272 return FALSE;
02273 }
02274 } else {
02275 if( !preg_match ( $regex, $platform ) ) {
02276 logMsg( 'Platform ' . $platform . ' is NOT supported' );
02277 return FALSE;
02278 }
02279 }
02280 }
02281
02282 logMsg( 'Platform ' . $platform . ' is supported' );
02283 return TRUE;
02284 }
02285
02291 function clearSQL() {
02292 $this->sqlArray = array();
02293 }
02294
02303 function addSQL( $sql = NULL ) {
02304 if( is_array( $sql ) ) {
02305 foreach( $sql as $line ) {
02306 $this->addSQL( $line );
02307 }
02308
02309 return TRUE;
02310 }
02311
02312 if( is_string( $sql ) ) {
02313 $this->sqlArray[] = $sql;
02314
02315
02316 if( $this->ExecuteInline() && ( $this->success == 2 || $this->ContinueOnError() ) ) {
02317 $saved = $this->db->debug;
02318 $this->db->debug = $this->debug;
02319 $ok = $this->db->Execute( $sql );
02320 $this->db->debug = $saved;
02321
02322 if( !$ok ) {
02323 if( $this->debug ) {
02324 ADOConnection::outp( $this->db->ErrorMsg() );
02325 }
02326
02327 $this->success = 1;
02328 }
02329 }
02330
02331 return TRUE;
02332 }
02333
02334 return FALSE;
02335 }
02336
02345 function getSQL( $format = NULL, $sqlArray = NULL ) {
02346 if( !is_array( $sqlArray ) ) {
02347 $sqlArray = $this->sqlArray;
02348 }
02349
02350 if( !is_array( $sqlArray ) ) {
02351 return FALSE;
02352 }
02353
02354 switch( strtolower( $format ) ) {
02355 case 'string':
02356 case 'text':
02357 return !empty( $sqlArray ) ? implode( ";\n\n", $sqlArray ) . ';' : '';
02358 case'html':
02359 return !empty( $sqlArray ) ? nl2br( htmlentities( implode( ";\n\n", $sqlArray ) . ';' ) ) : '';
02360 }
02361
02362 return $this->sqlArray;
02363 }
02364
02371 function Destroy() {
02372 set_magic_quotes_runtime( $this->mgq );
02373 unset( $this );
02374 }
02375 }
02376
02382 function logMsg( $msg, $title = NULL, $force = FALSE ) {
02383 if( XMLS_DEBUG or $force ) {
02384 echo '<pre>';
02385
02386 if( isset( $title ) ) {
02387 echo '<h3>' . htmlentities( $title ) . '</h3>';
02388 }
02389
02390 if( @is_object( $this ) ) {
02391 echo '[' . get_class( $this ) . '] ';
02392 }
02393
02394 print_r( $msg );
02395
02396 echo '</pre>';
02397 }
02398 }
02399 ?>