23 if (function_exists(
'file_get_contents'))
return file_get_contents($file);
25 $f = fopen($file,
'r');
29 while ($s = fread($f,100000)) $t .= $s;
38 if( !defined(
'XMLS_DEBUG' ) ) {
39 define(
'XMLS_DEBUG', FALSE );
45 if( !defined(
'XMLS_PREFIX' ) ) {
46 define(
'XMLS_PREFIX',
'%%P' );
52 if( !defined(
'XMLS_PREFIX_MAXLEN' ) ) {
53 define(
'XMLS_PREFIX_MAXLEN', 10 );
59 if( !defined(
'XMLS_EXECUTE_INLINE' ) ) {
60 define(
'XMLS_EXECUTE_INLINE', FALSE );
66 if( !defined(
'XMLS_CONTINUE_ON_ERROR' ) ) {
67 define(
'XMLS_CONTINUE_ON_ERROR', FALSE );
73 if( !defined(
'XMLS_SCHEMA_VERSION' ) ) {
74 define(
'XMLS_SCHEMA_VERSION',
'0.2' );
80 if( !defined(
'XMLS_DEFAULT_SCHEMA_VERSION' ) ) {
81 define(
'XMLS_DEFAULT_SCHEMA_VERSION',
'0.1' );
87 if( !defined(
'XMLS_DEFAULT_UPGRADE_METHOD' ) ) {
88 define(
'XMLS_DEFAULT_UPGRADE_METHOD',
'ALTER' );
94 if( !defined(
'_ADODB_LAYER' ) ) {
95 require(
'adodb.inc.php' );
96 require(
'adodb-datadict.inc.php' );
171 return is_object( $this->parent ) ? $this->parent->supportedPlatform( $platform ) : TRUE;
181 return is_object( $this->parent ) ? $this->parent->prefix( $name ) : $name;
191 return strtoupper( preg_replace(
'/^`(.+)`$/',
'$1', $field ) );
253 $this->name = $this->
prefix($attributes[
'NAME']);
263 $this->currentElement = strtoupper( $tag );
265 switch( $this->currentElement ) {
267 if( !isset( $attributes[
'PLATFORM'] ) OR $this->
supportedPlatform( $attributes[
'PLATFORM'] ) ) {
268 xml_set_object( $parser, $this->
addIndex( $attributes ) );
272 if( !isset( $attributes[
'PLATFORM'] ) OR $this->
supportedPlatform( $attributes[
'PLATFORM'] ) ) {
273 xml_set_object( $parser, $this->
addData( $attributes ) );
281 $fieldName = $attributes[
'NAME'];
282 $fieldType = $attributes[
'TYPE'];
283 $fieldSize = isset( $attributes[
'SIZE'] ) ? $attributes[
'SIZE'] : NULL;
284 $fieldOpts = isset( $attributes[
'OPTS'] ) ? $attributes[
'OPTS'] : NULL;
286 $this->
addField( $fieldName, $fieldType, $fieldSize, $fieldOpts );
290 case 'AUTOINCREMENT':
292 $this->
addFieldOpt( $this->current_field, $this->currentElement );
298 if( $attributes[
'VALUE'] ==
'' ) {
299 $attributes[
'VALUE'] =
" '' ";
302 $this->
addFieldOpt( $this->current_field, $this->currentElement, $attributes[
'VALUE'] );
307 $this->
addFieldOpt( $this->current_field, $this->currentElement );
320 switch( $this->currentElement ) {
323 if( isset( $this->current_field ) ) {
324 $this->
addFieldOpt( $this->current_field, $this->currentElement, $cdata );
344 $this->currentElement =
'';
346 switch( strtoupper( $tag ) ) {
348 $this->parent->addSQL( $this->
create( $this->parent ) );
349 xml_set_object( $parser, $this->parent );
353 unset($this->current_field);
366 $name = strtoupper( $attributes[
'NAME'] );
367 $this->indexes[
$name] =
new dbIndex( $this, $attributes );
368 return $this->indexes[
$name];
378 if( !isset( $this->data ) ) {
379 $this->data =
new dbData( $this, $attributes );
417 $this->current_field = $field_id;
420 $this->fields[$field_id][
'NAME'] =
$name;
423 $this->fields[$field_id][
'TYPE'] = $type;
426 if( isset( $size ) ) {
427 $this->fields[$field_id][
'SIZE'] = $size;
431 if( isset(
$opts ) ) {
432 $this->fields[$field_id][
'OPTS'][] =
$opts;
448 if( !isset( $value ) ) {
449 $this->fields[$this->
FieldID( $field )][
'OPTS'][] = $opt;
452 $this->fields[$this->
FieldID( $field )][
'OPTS'][] = array( $opt => $value );
466 if(isset($this->currentPlatform)) {
467 $this->opts[$this->parent->db->databaseType] = $opt;
483 if( is_array( $legacy_indexes = $xmls->dict->MetaIndexes( $this->name ) ) ) {
484 foreach( $legacy_indexes as $index => $index_details ) {
485 $sql[] = $xmls->dict->DropIndexSQL( $index, $this->name );
490 foreach( $this->drop_field as $field ) {
491 unset( $this->fields[$field] );
495 if( is_array( $legacy_fields = $xmls->dict->MetaColumns( $this->name ) ) ) {
497 if( $this->drop_table ) {
498 $sql[] = $xmls->dict->DropTableSQL( $this->name );
504 foreach( $legacy_fields as $field_id => $field ) {
505 if( !isset( $this->fields[$field_id] ) ) {
506 $sql[] = $xmls->dict->DropColumnSQL( $this->name,
'`'.$field->name.
'`' );
511 if( $this->drop_table ) {
515 $legacy_fields = array();
521 foreach( $this->fields as $field_id => $finfo ) {
523 if( !isset( $finfo[
'SIZE'] ) ) {
528 $fldarray[$field_id] = array(
529 'NAME' => $finfo[
'NAME'],
530 'TYPE' => $finfo[
'TYPE'],
531 'SIZE' => $finfo[
'SIZE']
535 if( isset( $finfo[
'OPTS'] ) ) {
536 foreach( $finfo[
'OPTS'] as $opt ) {
538 if( is_array( $opt ) ) {
540 $value = $opt[key( $opt )];
541 @$fldarray[$field_id][$key] .= $value;
544 $fldarray[$field_id][$opt] = $opt;
550 if( empty( $legacy_fields ) ) {
552 $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
553 logMsg( end( $sql ),
'Generated CreateTableSQL' );
556 logMsg(
"Upgrading {$this->name} using '{$xmls->upgrade}'" );
557 switch( $xmls->upgrade ) {
560 logMsg(
'Generated ChangeTableSQL (ALTERing table)' );
561 $sql[] = $xmls->dict->ChangeTableSQL( $this->name, $fldarray, $this->opts );
564 logMsg(
'Doing upgrade REPLACE (testing)' );
565 $sql[] = $xmls->dict->DropTableSQL( $this->name );
566 $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
574 foreach( $this->indexes as $index ) {
575 $sql[] = $index->create( $xmls );
578 if( isset( $this->data ) ) {
579 $sql[] = $this->data->create( $xmls );
589 if( isset( $this->current_field ) ) {
591 logMsg(
"Dropping field '{$this->current_field}' from table '{$this->name}'" );
596 logMsg(
"Dropping table '{$this->name}'" );
598 $this->drop_table = TRUE;
648 $this->name = $this->
prefix ($attributes[
'NAME']);
660 $this->currentElement = strtoupper( $tag );
662 switch( $this->currentElement ) {
687 switch( $this->currentElement ) {
703 $this->currentElement =
'';
705 switch( strtoupper( $tag ) ) {
707 xml_set_object( $parser, $this->parent );
732 $this->opts[] = $opt;
750 foreach( $this->columns as $id => $col ) {
751 if( !isset( $this->parent->fields[$id] ) ) {
752 unset( $this->columns[$id] );
756 return $xmls->dict->CreateIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts );
802 $this->currentElement = strtoupper( $tag );
804 switch( $this->currentElement ) {
806 $this->row = count( $this->data );
824 switch( $this->currentElement ) {
840 $this->currentElement =
'';
842 switch( strtoupper( $tag ) ) {
844 xml_set_object( $parser, $this->parent );
856 if( isset( $attributes[
'NAME'] ) ) {
857 $name = $attributes[
'NAME'];
859 $name = count($this->data[$this->row]);
863 $this->current_field = $this->
FieldID( $name );
873 if( !isset( $this->data[$this->row] ) ) {
877 if( !isset( $this->data[$this->row][$this->current_field] ) ) {
878 $this->data[
$this->row][$this->current_field] =
'';
881 $this->data[
$this->row][$this->current_field] .= $cdata;
891 $table = $xmls->dict->TableName($this->parent->name);
892 $table_field_count = count($this->parent->fields);
896 foreach( $this->data as
$row ) {
897 $table_fields = $this->parent->fields;
900 foreach( $row as $field_id => $field_data ) {
901 if( !array_key_exists( $field_id, $table_fields ) ) {
902 if( is_numeric( $field_id ) ) {
903 $field_id = reset( array_keys( $table_fields ) );
909 $name = $table_fields[$field_id][
'NAME'];
911 switch( $table_fields[$field_id][
'TYPE'] ) {
916 $fields[$name] = $xmls->db->qstr( $field_data );
923 $fields[$name] = intval($field_data);
926 $fields[$name] = $field_data;
929 unset($table_fields[$field_id]);
933 if( empty( $fields ) ) {
938 if( count( $fields ) < $table_field_count ) {
939 foreach( $table_fields as $field ) {
940 if (isset( $field[
'OPTS'] ))
941 if( ( in_array(
'NOTNULL', $field[
'OPTS'] ) || in_array(
'KEY', $field[
'OPTS'] ) ) && !in_array(
'AUTOINCREMENT', $field[
'OPTS'] ) ) {
947 $sql[] =
'INSERT INTO '. $table .
' ('. implode(
',', array_keys( $fields ) ) .
') VALUES ('. implode(
',', $fields ) .
')';
992 if( isset( $attributes[
'KEY'] ) ) {
993 $this->prefixKey = $attributes[
'KEY'];
996 $prefixMethod = isset( $attributes[
'PREFIXMETHOD'] ) ? strtoupper( trim( $attributes[
'PREFIXMETHOD'] ) ) :
'';
1001 $this->prefixMethod =
'AUTO';
1004 $this->prefixMethod =
'MANUAL';
1007 $this->prefixMethod =
'NONE';
1019 $this->currentElement = strtoupper( $tag );
1021 switch( $this->currentElement ) {
1026 if( !isset( $attributes[
'PLATFORM'] ) OR $this->
supportedPlatform( $attributes[
'PLATFORM'] ) ) {
1041 switch( $this->currentElement ) {
1057 $this->currentElement =
'';
1059 switch( strtoupper( $tag ) ) {
1065 $this->parent->addSQL( $this->
create( $this->parent ) );
1066 xml_set_object( $parser, $this->parent );
1091 unset( $this->query );
1103 if( !isset( $this->query ) OR empty( $sql ) ) {
1107 $this->query .= $sql;
1118 if( !isset( $this->query ) ) {
1122 $this->queries[] = $return = trim($this->query);
1124 unset( $this->query );
1136 foreach( $this->queries as $id =>
$query ) {
1137 switch( $this->prefixMethod ) {
1143 $query = $this->
prefixQuery(
'/^\s*((?is)INSERT\s+(INTO\s+)?)((\w+\s*,?\s*)+)(\s.*$)/',
$query, $xmls->objectPrefix );
1144 $query = $this->
prefixQuery(
'/^\s*((?is)UPDATE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/',
$query, $xmls->objectPrefix );
1145 $query = $this->
prefixQuery(
'/^\s*((?is)DELETE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/',
$query, $xmls->objectPrefix );
1148 #$data = preg_replace( '/(?ias)(^\s*SELECT\s+.*\s+FROM)\s+(\W\s*,?\s*)+((?i)\s+WHERE.*$)/', "\1 $prefix\2 \3", $data );
1153 if( isset( $this->prefixKey ) AND( $this->prefixKey !==
'' ) ) {
1155 $query = str_replace( $this->prefixKey, $xmls->objectPrefix,
$query );
1158 $query = str_replace( XMLS_PREFIX , $xmls->objectPrefix,
$query );
1162 $this->queries[$id] = trim(
$query );
1178 if( !isset( $prefix ) ) {
1182 if( preg_match( $regex,
$query, $match ) ) {
1183 $preamble = $match[1];
1184 $postamble = $match[5];
1185 $objectList = explode(
',', $match[3] );
1190 foreach( $objectList as $object ) {
1191 if( $prefixedList !==
'' ) {
1192 $prefixedList .=
', ';
1195 $prefixedList .= $prefix . trim( $object );
1198 $query = $preamble .
' ' . $prefixedList .
' ' . $postamble;
1306 $this->mgq = get_magic_quotes_runtime();
1307 ini_set(
"magic_quotes_runtime", 0);
1308 #set_magic_quotes_runtime(0);
1311 $this->debug = $this->db->debug;
1312 $this->dict = NewDataDictionary( $this->db );
1313 $this->sqlArray = array();
1314 $this->schemaVersion = XMLS_SCHEMA_VERSION;
1315 $this->executeInline( XMLS_EXECUTE_INLINE );
1316 $this->continueOnError( XMLS_CONTINUE_ON_ERROR );
1317 $this->setUpgradeMethod();
1337 if( !is_string( $method ) ) {
1341 $method = strtoupper( $method );
1346 $this->upgrade = $method;
1349 $this->upgrade = $method;
1352 $this->upgrade =
'ALTER';
1355 $this->upgrade =
'NONE';
1359 $this->upgrade = XMLS_DEFAULT_UPGRADE_METHOD;
1379 if( is_bool( $mode ) ) {
1380 $this->executeInline = $mode;
1400 if( is_bool( $mode ) ) {
1401 $this->continueOnError = $mode;
1437 if( !($fp = fopen( $filename,
'r' )) ) {
1447 if ( $returnSchema )
1450 while( $data = fread( $fp, 100000 ) ) {
1451 $xmlstring .= $data;
1461 while( $data = fread( $fp, 4096 ) ) {
1462 if( !xml_parse( $xmlParser, $data, feof( $fp ) ) ) {
1464 "XML error: %s at line %d",
1465 xml_error_string( xml_get_error_code( $xmlParser) ),
1466 xml_get_current_line_number( $xmlParser)
1471 xml_parser_free( $xmlParser );
1488 if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
1497 if ( $returnSchema )
1506 if( !xml_parse( $xmlParser, $xmlstring, TRUE ) ) {
1508 "XML error: %s at line %d",
1509 xml_error_string( xml_get_error_code( $xmlParser) ),
1510 xml_get_current_line_number( $xmlParser)
1514 xml_parser_free( $xmlParser );
1569 if( !is_bool( $continueOnErr ) ) {
1580 $this->success = $this->dict->ExecuteSQLArray(
$sqlArray, $continueOnErr );
1618 $fp = fopen( $filename,
"w" );
1620 foreach(
$sqlArray as $key => $query ) {
1621 fwrite( $fp, $query .
";\n" );
1635 $xmlParser = xml_parser_create();
1636 xml_set_object( $xmlParser, $this );
1639 xml_set_element_handler( $xmlParser,
'_tag_open',
'_tag_close' );
1640 xml_set_character_data_handler( $xmlParser,
'_tag_cdata' );
1651 switch( strtoupper( $tag ) ) {
1653 $this->obj =
new dbTable( $this, $attributes );
1654 xml_set_object( $parser, $this->obj );
1657 if( !isset( $attributes[
'PLATFORM'] ) OR $this->
supportedPlatform( $attributes[
'PLATFORM'] ) ) {
1658 $this->obj =
new dbQuerySet( $this, $attributes );
1659 xml_set_object( $parser, $this->obj );
1709 if( !isset ($newVersion) ) {
1713 if( $version == $newVersion ) {
1719 if( is_string(
$result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile,
'w' ) ) ) {
1730 if (function_exists(
'file_get_contents'))
return file_get_contents($path);
1731 return join(
'',file($path));
1757 if( !isset ($newVersion) ) {
1761 if( $version == $newVersion ) {
1765 if( substr(
$result, 0, 3 ) == sprintf(
'%c%c%c', 239, 187, 191 ) ) {
1772 if( is_string(
$result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile,
'w' ) ) ) {
1783 if( ! function_exists(
'xslt_create' ) ) {
1787 $xsl_file = dirname( __FILE__ ) .
'/xsl/' . $xsl .
'.xsl';
1790 if( !is_readable( $xsl_file ) ) {
1794 switch( $schematype )
1797 if( !is_readable( $schema ) ) {
1805 if( !is_string( $schema ) ) {
1810 $arguments = array (
1816 $xh = xslt_create ();
1819 xslt_set_error_handler ($xh, array (&$this,
'xslt_error_handler'));
1822 $result = xslt_process ($xh,
'arg:/_xml',
'arg:/_xsl', NULL, $arguments);
1840 if( is_array( $fields ) ) {
1842 'Message Type' => ucfirst( $fields[
'msgtype'] ),
1843 'Message Code' => $fields[
'code'],
1844 'Message' => $fields[
'msg'],
1845 'Error Number' => $errno,
1849 switch( $fields[
'URI'] ) {
1851 $msg[
'Input'] =
'XML';
1854 $msg[
'Input'] =
'XSL';
1857 $msg[
'Input'] = $fields[
'URI'];
1860 $msg[
'Line'] = $fields[
'line'];
1863 'Message Type' =>
'Error',
1864 'Error Number' => $errno,
1866 'Fields' => var_export( $fields, TRUE )
1870 $error_details = $msg[
'Message Type'] .
' in XSLT Transformation' .
"\n"
1873 foreach( $msg as $label => $details ) {
1874 $error_details .=
'<tr><td><b>' . $label .
': </b></td><td>' . htmlentities( $details ) .
'</td></tr>' .
"\n";
1877 $error_details .=
'</table>';
1893 if( !($fp = fopen( $filename,
'r' )) ) {
1899 while( $data = fread( $fp, 4096 ) ) {
1900 if( preg_match( $this->versionRegex, $data, $matches ) ) {
1901 return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
1918 if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
1922 if( preg_match( $this->versionRegex, $xmlstring, $matches ) ) {
1923 return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
1940 $old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM );
1942 $schema =
'<?xml version="1.0"?>' .
"\n"
1943 .
'<schema version="' . $this->schemaVersion .
'">' .
"\n";
1945 if( is_array(
$tables = $this->db->MetaTables(
'TABLES' ) ) ) {
1946 foreach(
$tables as $table ) {
1947 $schema .=
' <table name="' . $table .
'">' .
"\n";
1950 $rs = $this->db->Execute(
'SELECT * FROM ' . $table .
' WHERE 1=1' );
1951 $fields = $this->db->MetaColumns( $table );
1952 $indexes = $this->db->MetaIndexes( $table );
1954 if( is_array( $fields ) ) {
1955 foreach( $fields as $details ) {
1959 if( $details->max_length > 0 ) {
1960 $extra .=
' size="' . $details->max_length .
'"';
1963 if( $details->primary_key ) {
1964 $content[] =
'<KEY/>';
1965 } elseif( $details->not_null ) {
1966 $content[] =
'<NOTNULL/>';
1969 if( $details->has_default ) {
1970 $content[] =
'<DEFAULT value="' . $details->default_value .
'"/>';
1973 if( $details->auto_increment ) {
1974 $content[] =
'<AUTOINCREMENT/>';
1979 $details->primary_key = 0;
1980 $type = $rs->MetaType( $details );
1982 $schema .=
' <field name="' . $details->name .
'" type="' . $type .
'"' . $extra .
'>';
1984 if( !empty( $content ) ) {
1985 $schema .=
"\n " . implode(
"\n ", $content ) .
"\n ";
1988 $schema .=
'</field>' .
"\n";
1992 if( is_array( $indexes ) ) {
1993 foreach( $indexes as $index => $details ) {
1994 $schema .=
' <index name="' . $index .
'">' .
"\n";
1996 if( $details[
'unique'] ) {
1997 $schema .=
' <UNIQUE/>' .
"\n";
2000 foreach( $details[
'columns'] as $column ) {
2001 $schema .=
' <col>' . $column .
'</col>' .
"\n";
2004 $schema .=
' </index>' .
"\n";
2009 $rs = $this->db->Execute(
'SELECT * FROM ' . $table );
2011 if( is_object( $rs ) ) {
2012 $schema .=
' <data>' .
"\n";
2014 while( $row = $rs->FetchRow() ) {
2015 foreach( $row as $key => $val ) {
2016 $row[$key] = htmlentities($val);
2019 $schema .=
' <row><f>' . implode(
'</f><f>', $row ) .
'</f></row>' .
"\n";
2022 $schema .=
' </data>' .
"\n";
2026 $schema .=
' </table>' .
"\n";
2030 $this->db->SetFetchMode( $old_mode );
2032 $schema .=
'</schema>';
2049 case empty( $prefix ):
2050 logMsg(
'Cleared prefix' );
2051 $this->objectPrefix =
'';
2054 case strlen( $prefix ) > XMLS_PREFIX_MAXLEN:
2056 case !preg_match(
'/^[a-z][a-z0-9_]+$/i', $prefix ):
2057 logMsg(
'Invalid prefix: ' . $prefix );
2061 if( $underscore AND substr( $prefix, -1 ) !=
'_' ) {
2066 logMsg(
'Set prefix: ' . $prefix );
2067 $this->objectPrefix = $prefix;
2081 if( !empty( $this->objectPrefix ) ) {
2084 return preg_replace(
'/^(`?)(.+)$/',
'$1' . $this->objectPrefix .
'$2', $name );
2100 $regex =
'/^(\w*\|)*' . $this->db->databaseType .
'(\|\w*)*$/';
2102 if( !isset( $platform ) OR preg_match( $regex, $platform ) ) {
2103 logMsg(
"Platform $platform is supported" );
2106 logMsg(
"Platform $platform is NOT supported" );
2117 $this->sqlArray = array();
2129 if( is_array( $sql ) ) {
2130 foreach( $sql as $line ) {
2137 if( is_string( $sql ) ) {
2138 $this->sqlArray[] = $sql;
2142 $saved = $this->db->debug;
2144 $ok = $this->db->Execute( $sql );
2145 $this->db->debug = $saved;
2148 if( $this->debug ) {
2149 ADOConnection::outp( $this->db->ErrorMsg() );
2179 switch( strtolower( $format ) ) {
2184 return !empty(
$sqlArray ) ? nl2br( htmlentities( implode(
";\n\n",
$sqlArray ) .
';' ) ) :
'';
2197 ini_set(
"magic_quotes_runtime", $this->mgq );
2198 #set_magic_quotes_runtime( $this->mgq );
2208 function logMsg( $msg, $title = NULL, $force = FALSE ) {
2209 if( XMLS_DEBUG or $force ) {
2212 if( isset( $title ) ) {
2213 echo
'<h3>' . htmlentities( $title ) .
'</h3>';
2216 if( is_object( $this ) ) {
2217 echo
'[' . get_class( $this ) .
'] ';